0

Cloudflare Workers 301跳转保留UTM参数:3行代码解决流量追踪丢失问题

2026.05.28 | youres | 9次围观

为什么Cloudflare默认跳转会丢失UTM参数?

很多站长在Cloudflare开启了"始终使用HTTPS"或者配置了页面规则做HTTP跳转HTTPS,结果发现Google Analytics里的UTM参数全丢了,流量来源全部变成了direct。这个问题太常见了,原因也很简单——Cloudflare的"始终使用HTTPS"功能在做302跳转时,不会自动保留查询字符串

具体来说,当用户访问 http://example.com?utm_source=wechat 时,Cloudflare的默认跳转可能只把用户送到 https://example.com,后面的 ?utm_source=wechat 就没了。你的流量归因数据就这么消失了。

方案一:Cloudflare Workers保留查询参数(推荐)

这是最灵活、最可靠的方案。用Workers拦截请求,手动拼接完整URL再做301跳转,查询参数一个都不会丢。

核心代码

export default {
  async fetch(request) {
    const url = new URL(request.url);
    // 只处理HTTP请求,HTTPS直接放行
    if (url.protocol === 'http:') {
      const destinationURL = `https://${url.hostname}${url.pathname}${url.search}`;
      return Response.redirect(destinationURL, 301);
    }
    return fetch(request);
  }
};

关键就在 url.search 这一段——它包含了原始URL的所有查询参数,包括UTM参数。这样跳转后的地址就是 https://example.com?utm_source=wechat,参数完整保留。

部署步骤

  1. 登录Cloudflare Dashboard,进入Workers & Pages
  2. 点击"创建应用程序",选择"创建Worker"
  3. 把上面的代码粘贴到编辑器中
  4. 点击"保存并部署"
  5. 回到你的域名设置,添加一条路由:yourdomain.com/* 指向这个Worker

注意:如果你同时开了"始终使用HTTPS",建议关掉,让Worker来处理跳转逻辑,避免两个跳转规则冲突。

方案二:Cloudflare Transform Rules保留参数

如果你不想写代码,Cloudflare的Transform Rules也能实现类似效果。这个方案适合简单场景。

配置方法

  1. 进入Cloudflare Dashboard → Rules → Transform Rules
  2. 点击"Modify URL"
  3. 设置条件:当 URI Scheme 等于 HTTP
  4. 操作选择"重写URL",类型选"301永久重定向"
  5. 目标URL填:https://yourdomain.com${uri}

这里的 ${uri} 会自动包含路径和查询字符串,相当于Nginx里的 $request_uri

局限性:Transform Rules的变量替换功能在某些套餐下可能不可用,免费套餐支持的规则数量也有限。如果你的跳转逻辑比较复杂,还是用Workers更灵活。

方案三:页面规则配合查询字符串保留

Cloudflare的页面规则(Page Rules)也可以做301跳转,但需要特别注意查询字符串的处理。

配置要点

  1. 创建页面规则,匹配URL填 http://yourdomain.com/*
  2. 设置"Forwarding URL",类型选"301 - Permanent"
  3. 目标URL填 https://yourdomain.com/$1

但这里有个坑:页面规则的 $1 只捕获路径,不包含查询字符串。所以这个方案并不适合保留UTM参数,除非你把匹配模式改成更精细的正则。

实际操作中,页面规则更适合做整站跳转,不太适合需要保留参数的场景。

Workers方案进阶:处理特殊参数场景

场景一:跳转时追加额外参数

export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.protocol === 'http:') {
      url.protocol = 'https:';
      url.searchParams.set('redirected', '1');
      return Response.redirect(url.toString(), 301);
    }
    return fetch(request);
  }
};

URLSearchParams API追加参数,比手动拼接字符串安全得多,不用担心重复的问号或者编码问题。

场景二:只保留UTM参数,过滤其他参数

export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.protocol === 'http:') {
      const newUrl = new URL(`https://${url.hostname}${url.pathname}`);
      for (const [key, value] of url.searchParams) {
        if (key.startsWith('utm_')) {
          newUrl.searchParams.set(key, value);
        }
      }
      return Response.redirect(newUrl.toString(), 301);
    }
    return fetch(request);
  }
};

这个写法只保留 utm_ 开头的参数,其他参数全部丢弃。适合你想要"清洁URL"同时又不想丢失流量归因数据的场景。

场景三:多域名跳转保留完整参数

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const domainMap = {
      'old-domain.com': 'new-domain.com',
      'www.old-domain.com': 'new-domain.com',
    };
    const target = domainMap[url.hostname];
    if (target) {
      const destinationURL = `https://${target}${url.pathname}${url.search}`;
      return Response.redirect(destinationURL, 301);
    }
    return fetch(request);
  }
};

做域名迁移的时候,这个脚本能把旧域名的所有请求(连同查询参数)都跳转到新域名。

验证跳转是否保留了UTM参数

部署完成后,用curl验证一下:

curl -v "http://yourdomain.com/?utm_source=test&utm_medium=cpc" 2>&1 | grep Location

如果返回的Location头里包含完整的 ?utm_source=test&utm_medium=cpc,说明参数保留了。如果只有 https://yourdomain.com/,那就是参数丢了,需要回去检查配置。

也可以直接在浏览器里测试:地址栏输入带UTM参数的HTTP地址,看跳转后地址栏里参数还在不在。

Workers vs 其他方案对比

  • Workers:最灵活,能处理各种复杂场景,免费套餐每天10万次请求足够小站使用
  • Transform Rules:零代码,但免费套餐只有10条规则,复杂跳转搞不定
  • 页面规则:参数保留能力弱,而且Cloudflare已经逐步用Transform Rules替代页面规则
  • "始终使用HTTPS":最省事,但参数可能丢失,不推荐用于有UTM追踪需求的站点

常见问题

Workers和"始终使用HTTPS"能同时开吗?

可以,但不建议。两个跳转逻辑可能冲突,导致双重跳转或者参数丢失。建议关掉"始终使用HTTPS",让Worker统一处理。

Workers会影响网站性能吗?

Workers在Cloudflare的边缘节点执行,跳转响应通常在50ms以内,对用户体验几乎没有影响。而且301跳转浏览器会缓存,后续访问直接走HTTPS,不需要再经过Worker。

免费套餐够用吗?

Cloudflare Workers免费套餐每天10万次请求,对于日PV低于10万的站点完全够用。如果超了,5美元/月的付费套餐提供1000万次请求,性价比很高。

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
882文章数 0评论数
作者其它文章