Chrome中还原包裹链接的正则脚本失效问题求助
问题
我编写了如下脚本,用于还原所用服务中无法禁用的包裹链接:
<script> $(function($) { $('a[href]').each(function() { $(this).attr('href', $(this).attr('href') // these two lines make the script work for Firefox as well .replace(/.+?(?=(clk(n|g)\/https\/))/, '') .replace(/.+?(?=(clk(n|g)\/http\/))/, '') // this works for Chrome and Safari only .replace(/clk(n|g)\/https\//, 'https://') .replace(/clk(n|g)\/http\//, 'http://') .replace(/clk(n|g)\/tel\//, 'tel:') .replace(/clk(n|g)\/rel\//, '')); }); }); </script>
但在Chrome浏览器中,加载包含如下链接的页面时,链接仍处于包裹状态:
<a class="lp-element lp-pom-button" id="lp-pom-button-538" href="clkg/https/calendly.com/mydemo/my-demo" target="_blank"><span class="label">REQUEST A DEMO AND RELAX</span></a>
正则表达式在调试工具中能匹配,但脚本却不生效。此前该脚本可解决此问题,但现在突然失效。
补充说明:包裹链接是指服务会将原始链接(如https://calendly.com/mydemo/my-demo)转换为clkg/https/calendly.com/mydemo/my-demo,点击后先跳转到该子目录再重定向至原始链接。这是服务的转化追踪功能,但会破坏原生链接装饰器,导致UTM参数持久化和跨域测量失效。
原因分析
- 脚本执行时机不匹配:你的脚本依赖
$(function(){})(DOMContentLoaded事件)触发,若目标链接是页面加载后动态生成的(比如服务的追踪脚本晚于你的脚本执行,或通过AJAX/前端框架异步渲染),脚本执行时还未生成包裹链接,自然无法处理。 - Chrome的DOM属性读取延迟:Chrome对DOM属性的处理存在异步延迟,服务脚本修改href的操作可能晚于你的脚本读取href的时机,导致脚本拿到的是未被包裹的原始链接。
- 正则替换顺序冗余:前置的Firefox兼容替换逻辑对
clkg/https/...这类开头无前置内容的链接无效,虽然后续正则能匹配,但如果服务调整了链接生成的时序,就会出现脚本执行时还没触发替换的情况。
解决方案
方案1:延迟执行脚本
通过延迟执行确保服务的追踪脚本已完成链接包裹,可根据实际情况调整延迟时长:
<script> // 延迟1秒执行,适配多数服务的脚本执行节奏 setTimeout(function() { $('a[href]').each(function() { let href = $(this).attr('href'); if (!href) return; // 合并正则,简化替换逻辑 href = href.replace(/^(.*?)clk(n|g)\/(https|http|tel)\//, '$3://') .replace(/^(.*?)clk(n|g)\/rel\//, ''); $(this).attr('href', href); }); }, 1000); </script>
方案2:监听DOM变化实时处理
使用MutationObserver监听页面DOM变化,自动处理新增的包裹链接:
<script> $(function() { // 定义统一的链接修复函数 function fixWrappedLinks() { $('a[href]').each(function() { let href = $(this).attr('href'); // 跳过已修复或无需修复的链接 if (!href || (href.includes('://') && !href.match(/clk(n|g)\//))) return; // 一次完成所有类型的链接替换 href = href.replace(/^(.*?)clk(n|g)\/(https|http|tel)\//, '$3://') .replace(/^(.*?)clk(n|g)\/rel\//, ''); $(this).attr('href', href); }); } // 先处理页面已加载的链接 fixWrappedLinks(); // 监听DOM新增元素,实时修复 const observer = new MutationObserver(function(mutations) { mutations.forEach(mutation => { if (mutation.addedNodes.length > 0) fixWrappedLinks(); }); }); observer.observe(document.body, { childList: true, subtree: true }); }); </script>
方案3:简化正则替换逻辑
合并冗余的正则规则,减少替换步骤,避免顺序问题:
将原脚本中的多步替换合并为:
href = href.replace(/^(.*?)clk(n|g)\/(https|http|tel)\//, '$3://') .replace(/^(.*?)clk(n|g)\/rel\//, '');
这个正则能同时处理带前置内容和无前置内容的包裹链接,兼容所有浏览器。
内容的提问来源于stack exchange,提问作者MrChadMWood
相关产品推荐
相关产品推荐

