为什么UTM参数在重定向后会丢失?
很多人在做流量追踪时发现一个奇怪现象:明明在广告链接里加了完整的UTM参数,但到了Google Analytics(或GA4)后台,流量来源却显示为(direct)或者归因错误。罪魁祸首往往就是URL重定向时的参数传递机制出了问题。
UTM参数(Source、Medium、Campaign、Term、Content)是拼接在URL问号后面的查询字符串(query string)。标准的带UTM的链接长这样:
https://www.example.com/landing-page?utm_source=baidu&utm_medium=cpc&utm_campaign=spring_sale
当这个URL发生重定向(301/302/307/308)时,重定向的方式和配置决定了UTM参数能否完整传递下去。
URL重定向UTM参数传递的4种核心机制
1. 浏览器自动保留查询参数(标准301/302)
根据HTTP规范,301和302重定向默认会把原请求的查询参数带到新URL上。但注意:这只发生在重定向目标URL本身不包含问号的情况下。
举个例子:用户访问 https://example.com/offer?utm_source=wechat,Nginx配置如下:
return 301 https://www.example.com/offer;
结果:浏览器拿到301响应后,会自动把?utm_source=wechat拼到新URL后面,最终访问https://www.example.com/offer?utm_source=wechat。UTM参数完整保留。
2. 重定向目标URL带问号会清空原参数
这是最常见的UTM丢失原因。如果重定向目标URL里写了问号,即使后面不接任何参数,浏览器也会认为你要"重新定义查询字符串",原UTM参数直接被清空。
# 错误写法:会丢失UTM参数 return 301 https://www.example.com/landing?; # 正确写法:不写问号,让浏览器自动保留原参数 return 301 https://www.example.com/landing;
3. Nginx rewrite 的问号特殊含义
在Nginx rewrite规则里,问号是一个特殊符号:它表示"替换字符串到此为止,后面的内容当作查询字符串"。如果你在rewrite的替换部分写了问号,原$args(即原UTM参数)会被丢弃。
# 错误:问号会覆盖原参数 rewrite ^(.*)$ https://www.example.com$1? permanent; # 正确:不写问号,原参数自动附加 rewrite ^(.*)$ https://www.example.com$1 permanent; # 正确:显式保留原参数 rewrite ^(.*)$ https://www.example.com$1$is_args$args permanent;
4. 307/308 重定向:POST请求和参数都能保留
301和302在重定向时会把POST请求变成GET(请求体和参数都会丢)。如果你需要保留POST请求体和查询参数,应该用307(临时)或308(永久)重定向。
这也是为什么微信支付、支付宝回调通知的跳转通常用307/308——保证回调参数不丢失。
CDN层面的UTM参数丢失问题
除了Nginx/Apache配置,CDN(Cloudflare、阿里云CDN、腾讯云CDN)的HTTPS跳转规则也会截断UTM参数。
以Cloudflare为例,如果你开启了"Always Use HTTPS"(强制HTTPS跳转),默认的规则是:
http://example.com/path?utm_source=xxx → https://example.com/path
查询参数被丢弃了。解决方法有两个:
- 用Cloudflare Workers自定义跳转规则,在JS代码里读取
request.url,解析查询参数,再拼到新URL里。 - 关闭CDN的"强制HTTPS跳转",改为在源站Nginx里用
return 301 https://$host$request_uri;($request_uri包含完整路径+查询参数)。
Google Analytics(GA4)接收UTM参数的流程
UTM参数从用户点击到出现在GA4报告里,经历了以下步骤:
- 用户点击带UTM的链接 → 浏览器发起请求(带查询参数)
- 最终请求到达Web服务器,页面加载GA4追踪代码
- GA4从当前页面URL里解析UTM参数并发送
任何一步的重定向配置不当,UTM参数都会丢失。排查时建议用Chrome DevTools的Network面板,勾选"Preserve log",追踪整个重定向链,看UTM参数在哪一步消失了。
实战:Nginx正确配置UTM参数保留的完整写法
最保险的Nginx HTTP→HTTPS跳转配置(UTM参数不丢失):
server {
listen 80;
server_name www.example.com example.com;
# 关键:$request_uri 包含完整路径+查询参数
return 301 https://$host$request_uri;
}
如果要用rewrite(不推荐,return性能更好):
# 正确:用$request_uri保留完整原始请求 rewrite ^ https://$host$request_uri? permanent;
注意rewrite后面那个问号:它的作用是"告诉Nginx不要在后面再追加一次$args",因为$request_uri本身已经包含了查询参数。
内链推荐(延伸阅读)
原文首发于youres.cn,转载请注明出处。
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论