0

Nginx重定向保留UTM参数最佳实践:让你的流量追踪数据万无一失

2026.05.29 | youres | 8次围观

做网站流量分析的同学,十有八九遇到过这个问题:用户明明是通过带 UTM 参数的链接进来的,结果一跳转,数据就丢了。Google Analytics 里一看,来源直接变成了"直接访问"(Direct),所有的投放数据全部归零。

这不是 Analytics 的问题,问题出在 Nginx 重定向配置上。今天这篇文章,把保留 UTM 参数的各种方案讲透,给出每种方案的适用场景和避坑指南。

一、问题根源:Nginx 重定向为什么丢参数?

在 Nginx 里,使用 returnrewrite 做重定向时,默认行为是有区别的:

  • return 301/302/307/308:只使用 return 后面的 URL 作为跳转目标,查询字符串(Query String)不会自动携带。也就是说 return 301 https://example.com/page 会丢失 utm_source=google
  • rewrite ... redirect/permanent:rewrite 指令默认会追加原始查询字符串,但当目标 URL 尾部写了 ? 时,原参数反而会被丢弃

这是很多人踩坑的根本原因。理解了这一点,选方案就清晰了。

二、5种最佳配置方案

方案1:return 指令 + $is_args$args(最简洁)

server {
    listen 80;
    server_name example.com;
    return 301 https://example.com$request_uri$is_args$args;
}

原理$request_uri 包含协议、域名、路径和所有原始查询参数,$is_args 在有参数时返回 ?,无参数时返回空,$args 就是查询参数本身。

适用场景:简单的一对一 HTTP 跳转 HTTPS,不做参数过滤,原样保留所有参数。

效果http://example.com/page?id=1&ut

方案2:rewrite 指令(改写路径 + 保留参数)

server {
    listen 80;
    server_name example.com;
    rewrite ^/(.*)$ https://example.com/$1 permanent;
}

原理:rewrite 使用 permanent(301)或 redirect(302)做外部重定向时,Nginx 默认会把原始查询参数追加到目标 URL 后面。

适用场景:路径有规律的重写,比如把所有请求从 /old/ 目录迁移到新域名。

方案3:if 正则判断(选择性过滤)

server {
    listen 80;
    server_name example.com;

    # 有UTM参数时全部保留
    if ($args ~* "utm_") {
        return 301 https://example.com$request_uri$is_args$args;
    }

    # 无UTM参数,正常跳转
    return 301 https://example.com$request_uri;
}

原理:用正则判断查询字符串中是否包含 utm_ 前缀的参数,有的话就拼接,没有就简单跳转。

适用场景:大多数情况下只需要保留 UTM 参数,用 if 判断可以避免无参数时的多余问号。

注意:Nginx 官方文档建议 if 指令在 server 块中慎用,更复杂的场景建议用 map 指令。

方案4:map 指令(最灵活的参数过滤方案)

http {
    # 从原始查询字符串中提取UTM五件套
    map $args $utm_query {
        default                     "";
        "~*utm_source=([^&]+)"    "utm_source=$1";
        "~*utm_medium=([^&]+)"    "utm_medium=$1";
        "~*utm_campaign=([^&]+)"  "utm_campaign=$1";
        "~*utm_term=([^&]+)"      "utm_term=$1";
        "~*utm_content=([^&]+)"    "utm_content=$1";
    }

    server {
        listen 80;
        server_name example.com;
        return 301 https://example.com$request_uri$is_args$args;
    }
}

原理:利用 map 指令在请求处理之前从原始查询字符串中按需提取参数。

适用场景:需要精细控制保留哪些参数、丢弃哪些参数的复杂场景,比如只保留 UTM 五件套,去掉 session ID 等垃圾参数。

方案5:针对特定路径单独配置

server {
    listen 80;
    server_name example.com;

    # 博客文章页跳转,只保留UTM参数
    location ~* ^/article/ {
        if ($args ~* "utm_") {
            return 301 https://example.com$request_uri$is_args$args;
        }
        return 301 https://example.com$request_uri;
    }

    # 产品页保留所有参数
    location ~* ^/product/ {
        return 301 https://example.com$request_uri$is_args$args;
    }

    # 其他页面简单跳转
    location / {
        return 301 https://example.com$request_uri$is_args$args;
    }
}

原理:针对不同的 location 块写不同的重定向规则,实现精细化的参数保留策略。

适用场景:网站结构复杂,不同类型页面有不同的参数保留需求。

三、方案对比与选择建议

方案复杂度参数控制适用场景
return + $is_args$args极简原样保留全部HTTP到HTTPS简单跳转
rewrite permanent简单原样保留全部路径迁移场景
if 正则判断中等有参数时保留全部只关心UTM五件套
map 指令较高精确提取任意参数复杂参数过滤需求
location 细分较高按路径差异化控制多类型页面的差异化策略

四、用 curl 验证参数是否保留

配置完之后,记得用 curl 验证一下:

# 测试301重定向是否保留UTM参数
curl -IL "http://example.com/page?utm_source=google&ut"

# 关键看最后一行 Location 头
# 正确的应该是:
# Location: https://example.com/page?utm_source=google&ut

PowerShell 用户可以用这个:

(Invoke-WebRequest -Uri "http://example.com/page?utm_source=google" -MaximumRedirection 0 -ErrorAction SilentlyContinue).Headers["Location"]

五、常见问题

Q:使用了方案1还是有参数丢失?

检查一下是不是 CDN(Cloudflare、阿里云CDN、腾讯云CDN等)层做了 HTTPS 强制跳转,很多 CDN 默认会丢弃查询字符串,需要在 CDN 控制台单独勾选"保留查询参数"。

Q:POST 请求的 UTM 参数怎么处理?

POST 请求的参数在请求体里,不在 URL 查询字符串中,重定向本身不会影响 POST 的 body。301/302 跳转后浏览器会改成 GET 方法,如果业务上需要保留 POST 数据,换用 307/308 并配合特殊处理。

Q:多个同名参数只保留了一个?

UTM 参数通常不重复,但如果有类似 ?id=1&id=2 的情况,$args 会保留全部。如果用了 map 指令的正则方案,同名参数只匹配第一个。

六、总结

保留 UTM 参数的核心就一句话:搞清楚你的重定向是 return 还是 rewrite,然后手动拼接 $request_uri 和查询变量。

  • 大多数场景:return 301 https://example.com$request_uri$is_args$args 一行搞定。
  • 需要过滤参数:用 if 条件判断或 map 指令。
  • 配置完必做验证:用 curl 看 Location 响应头。

流量追踪数据来之不易,几十块钱的投放费用,如果因为一个重定向配置丢了归因数据,损失远比解决这个问题的精力大得多。配置一次,长期受益。


📌 相关文章:
版权声明

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

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