做营销的人最怕什么?辛辛苦苦投放了广告,用户也点击了链接,结果后台显示流量来源是「direct」,所有UTM参数在跳转过程中全部丢失。这种问题单靠人工一个个去点、去查根本不现实,今天介绍用Shell脚本配合curl批量检测UTM参数的完整方案。
为什么需要批量检测UTM参数
UTM参数(Urchin Tracking Module)是营销活动的命根子。utm_source、utm_medium、utm_campaign这些参数用来标记流量从哪来、走的什么渠道、属于哪个活动。但凡中间经过一次重定向,参数就可能被服务器吃掉。
常见的坑包括:短链平台跳转后参数丢失、Nginx 301跳转把问号后的内容清空、CDN强制HTTPS跳转时参数被剥离。单条检测可以用浏览器开发者工具,但几十上百条链接只能靠脚本批量跑。
核心原理:curl url_effective 拿到最终地址
做批量检测依赖curl的两个参数:-L让curl跟随所有重定向,-w url_effective输出最终请求的实际URL(即重定向之后的地址)。如果UTM参数还在最终URL里,就说明跳转链路保留了参数;如果参数消失了,就说明某一级跳转出了问题。
单条检测命令长这样:
curl -sL -w "\\n%{url_effective}" -o /dev/null "https://your-domain.com/redirect?utm_source=test&utm_medium=blog&utm_campaign=q1"
输出结果就是重定向后的完整URL,直接grep看有没有utm_开头的参数即可。
方案一:基础while循环脚本
最入门的写法,从文件读取URL列表,逐行处理:
#!/bin/bash
INPUT="urls.txt"
OUTPUT="utm_check_result.txt"
echo "原始URL,最终URL,UTM参数状态" > "$OUTPUT"
while IFS= read -r url; do
[[ -z "$url" || "$url" =~ ^# ]] && continue
final_url=$(curl -sL -w "%{url_effective}" -o /dev/null --max-time 10 "$url")
if echo "$final_url" | grep -q "utm_"; then
status="保留"
else
status="丢失"
fi
echo "\\"$url\\",\\"$final_url\\",\\"$status\\"" >> "$OUTPUT"
echo "[$status] $url -> $final_url"
done < "$INPUT"
echo "检测完成,结果已保存到 $OUTPUT"
用法很简单,新建urls.txt,每行一个营销链接,然后执行脚本。结果输出到CSV文件,用Excel或Numbers可以直接打开查看。
方案二:xargs并行加速脚本
方案一虽然能跑,但几十个链接串行检测速度太慢。换成xargs并行处理,速度直接翻几倍:
#!/bin/bash
INPUT="urls.txt"
OUTPUT="utm_check_result.csv"
MAX_JOBS=5
echo "原始URL,最终URL,跳转次数,UTM状态,检测时间" > "$OUTPUT"
check_utm() {
url="$1"
result=$(curl -sL -w ":::|||%{url_effective}:::|||%{num_redirects}" -o /dev/null --max-time 15 "$url")
final_url=$(echo "$result" | awk -F':::' '{print $2}')
redirect_count=$(echo "$result" | awk -F':::' '{print $3}')
if echo "$final_url" | grep -qE "utm_source|utm_medium|utm_campaign"; then
status="保留"
else
status="丢失"
fi
check_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "\\"$url\\",\\"$final_url\\",\\"$redirect_count\\",\\"$status\\",\\"$check_time\\""
}
export -f check_utm
cat "$INPUT" | grep -v "^#" | grep -v "^$" | xargs -n1 -P"$MAX_JOBS" bash -c 'check_utm "$@"' _
echo "并行检测完成,结果在 $OUTPUT"
这个脚本的亮点是:加了并发数控制(MAX_JOBS=5),避免同时发太多请求把目标服务器打爆;多了跳转次数统计字段,方便排查是不是因为跳转层级太多导致参数丢失。
方案三:带CSV报告和异常标记的完整脚本
实际工作中巡检脚本跑完了,还需要导出报告、标注异常项。这个方案把结果直接整理成带状态标注的CSV:
#!/bin/bash
INPUT="urls.txt"
REPORT="utm_audit_$(date +%Y%m%d_%H%M%S).csv"
echo "序号,原始URL,最终URL,跳转次数,UTM来源,UTM介质,UTM活动,参数状态,异常原因,检测时间" > "$REPORT"
seq=1
while IFS= read -r url; do
[[ -z "$url" || "$url" =~ ^# ]] && continue
result=$(curl -sL -w ":::|||%{url_effective}:::|||%{num_redirects}" -o /dev/null --max-time 15 "$url")
final_url=$(echo "$result" | awk -F':::' '{print $2}')
redirect_count=$(echo "$result" | awk -F':::' '{print $3}')
utm_source=$(echo "$final_url" | grep -oP 'utm_source=\\K[^&?]+' || echo "")
utm_medium=$(echo "$final_url" | grep -oP 'utm_medium=\\K[^&?]+' || echo "")
utm_campaign=$(echo "$final_url" | grep -oP 'utm_campaign=\\K[^&?]+' || echo "")
if [[ -n "$utm_source" || -n "$utm_medium" || -n "$utm_campaign" ]]; then
status="正常"
reason=""
else
status="异常"
reason="重定向后UTM参数全部丢失"
fi
check_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "$seq,\\"$url\\",\\"$final_url\\",\\"$redirect_count\\",\\"$utm_source\\",\\"$utm_medium\\",\\"$utm_campaign\\",\\"$status\\",\\"$reason\\",\\"$check_time\\"" >> "$REPORT"
[[ "$status" == "异常" ]] && echo "异常: 第${seq}条链接UTM参数丢失: $url"
((seq++))
done < "$INPUT"
normal_count=$(grep -c ",正常," "$REPORT")
error_count=$(grep -c ",异常," "$REPORT")
echo "===== 巡检报告汇总 ====="
echo "总检测数: $((normal_count + error_count))"
echo "正常: $normal_count"
echo "异常: $error_count"
echo "报告文件: $REPORT"
这个脚本跑完之后会输出汇总:检测了多少条、正常多少条、异常多少条。异常行在CSV里标记为「异常」状态,配合Excel的条件格式可以直接高亮出来,递给运营同事一目了然。
常见坑和排查思路
脚本跑起来发现大量参数丢失,先别急着怪服务器。从这几个方向查:
- 重定向次数过多:有些短链经过三四跳才到落地页,中间某一跳的参数处理逻辑有问题。用curl -v看每一步的Location头,定位到具体哪一跳参数消失。
- 问号被当成路径分隔符:Nginx rewrite里如果写成了
return 301 /newpage?$request_uri,原来的查询参数会变成路径的一部分,导致UTM丢失。正确做法是return 301 /newpage$is_args$args。 - CDN层面强制跳转:Cloudflare开启「始终使用HTTPS」后,如果原链接是HTTP+查询参数,跳转过程中参数可能被CDN层的规则剥离。检查CDN页面规则里有没有配置参数处理策略。
- URL编码问题:有些短链服务会对URL参数做编码,如果编码格式和落地页解析预期不一致,参数看起来存在但实际解析不出来。用
curl -v看请求头的完整URL原始格式。
定时任务自动巡检
手动跑一次脚本还不够,营销链接越来越多,需要定时自动跑。把脚本扔进crontab,每天早上9点自动检测一遍,有异常就发邮件告警:
0 9 * * * /path/to/check_utm.sh >> /var/log/utm_audit.log 2>&1
如果想加邮件通知,可以在脚本末尾加一行判断异常数量大于0时调用SendMail或者调用钉钉Webhook推送告警消息。
总结
Shell脚本配合curl批量检测UTM参数,本质上就是利用curl -L跟随重定向、-w url_effective输出最终地址这两个核心能力。方案一适合快速验证几条链接,方案二适合几十条链接的高效巡检,方案三适合正式环境里的日常监控和报告导出。
关键就一句话:先把单条命令跑通,再写循环;先看日志排查问题,再上并发;先有报告,再接告警。一步一步来,脚本稳了之后每天省下的手动操作时间相当可观。
相关阅读:
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论