0

curl UTM参数丢失自动钉钉告警配置:3个实战脚本让营销追踪异常秒级推送到群里

2026.06.16 | youres | 4次围观

为什么要监控UTM参数丢失

做营销投放的同事都遇到过这种情况:花了钱推的链接,到GA4一看流量归因全是direct,UTM参数在重定向过程中被剥离了,却没人知道。等发现的时候,已经浪费了几天的预算。

手动检查不现实,链接成百上千。需要一个自动化方案:定时批量检测UTM参数是否保留,一旦发现丢失,立刻推送到钉钉群,让负责人第一时间处理。

curl检测UTM参数是否丢失的原理

核心思路很简单:用curl模拟用户请求,追踪重定向全过程,检查最终URL里是否还带着UTM参数。

# 追踪重定向并获取最终URL
curl -L -s -o /dev/null -w "%{url_effective}" "http://example.com/mkt?utm_source=baidu&utm_medium=cpc"

如果输出的url_effective里没有utm_source、utm_medium,说明参数在重定向过程中丢失了。

脚本一:基础版UTM参数丢失检测+钉钉告警

先上完整可运行的脚本。这个版本适合刚开始接入告警的团队,逻辑清晰,改改配置就能用。

#!/bin/bash
# === 配置区域 ===
WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
SECRET="YOUR_SECRET"
URL_LIST=(
  "https://www.youres.cn/promotion?utm_source=wechat&utm_medium=social"
  "https://www.youres.cn/activity?utm_source=baidu&utm_medium=cpc"
)

# === 生成钉钉签名 ===
generate_sign() {
  local timestamp=$(date +%s%3N)
  local string_to_sign="${timestamp}\n${SECRET}"
  local sign=$(echo -ne "$string_to_sign" | openssl dgst -sha256 -hmac "${SECRET}" -binary | base64 | jq -sRr @uri)
  echo "$timestamp" "$sign"
}

# === 检测UTM参数 ===
check_utm() {
  local url="$1"
  local final_url=$(curl -L -s -o /dev/null -w "%{url_effective}" "$url")
  if [[ "$final_url" != *"utm_source="* ]]; then
    echo "UTM丢失: $url"
    echo "   最终跳转: $final_url"
    return 1
  else
    echo "UTM正常: $url"
    return 0
  fi
}

# === 发送钉钉告警 ===
send_dingtalk() {
  local msg="$1"
  read -r ts sign <<< $(generate_sign)
  local webhook_url="${WEBHOOK}&timestamp=${ts}&sign=${sign}"
  curl -s -X POST "$webhook_url" \
    -H "Content-Type: application/json" \
    -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"${msg}\"}}"
}

# === 主流程 ===
main() {
  local alert_msg=""
  for url in "${URL_LIST[@]}"; do
    if ! check_utm "$url"; then
      alert_msg="${alert_msg}UTM参数丢失\nURL: ${url}\n"
    fi
  done
  if [ -n "$alert_msg" ]; then
    send_dingtalk "$alert_msg"
  fi
}
main

脚本二:生产级批量检测+详细告警信息

基础版能跑,但生产环境需要更多信息:哪个参数丢了、跳了几次、最终跳到哪里。这个版本把这些细节都加上了。

#!/bin/bash
# 生产级UTM参数丢失检测脚本
URL_FILE="/opt/utm_check/url_list.txt"
LOG_FILE="/opt/utm_check/utm_check.log"
WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
SECRET="YOUR_SECRET"

# 生成签名(同上,省略)
generate_sign() { ... }

# 详细检测单条URL
detect_utm_detail() {
  local url="$1"
  local result=$(curl -L -s -o /dev/null --max-redirs 10 \
    -w "url_effective: %{url_effective}\nnum_redirects: %{num_redirects}\nhttp_code: %{http_code}\n" "$url" 2>/dev/null)
  local final_url=$(echo "$result" | grep "url_effective" | sed 's/url_effective: //')
  local redirects=$(echo "$result" | grep "num_redirects" | awk '{print $2}')
  
  # 检查必要的UTM参数
  local missing=""
  for param in utm_source utm_medium; do
    if [[ "$final_url" != *"$param="* ]]; then
      missing="$missing $param"
    fi
  done
  
  if [ -n "$missing" ]; then
    echo "ALERT|URL:$url|FINAL:$final_url|REDIRECTS:$redirects|MISSING:$missing"
    return 1
  fi
  return 0
}

# 批量检测
batch_check() {
  local alert_count=0
  local alert_detail=""
  while IFS= read -r url || [ -n "$url" ]; do
    [ -z "$url" ] && continue
    result=$(detect_utm_detail "$url")
    if [ $? -ne 0 ]; then
      alert_count=$((alert_count + 1))
      alert_detail="${alert_detail}第${alert_count}条\n${result}\n\n"
    fi
  done < "$URL_FILE"
  
  if [ $alert_count -gt 0 ]; then
    local msg="UTM参数丢失告警\n检测时间: $(date '+%Y-%m-%d %H:%M:%S')\n异常数量: ${alert_count}\n\n${alert_detail}"
    send_dingtalk "$msg"
    echo "[$(date)] ALERT: $alert_count URLs have UTM lost" >> "$LOG_FILE"
  fi
}
batch_check

脚本三:crontab定时任务+告警去重

最后一版加上了告警去重:同一个URL连续检测3次都异常才告警,避免网络抖动导致的误报。

#!/bin/bash
# 带去重逻辑的UTM告警脚本
STATE_DIR="/opt/utm_check/state"
mkdir -p "$STATE_DIR"

check_with_dedup() {
  local url="$1"
  local state_file="$STATE_DIR/$(echo -n "$url" | md5sum | awk '{print $1}').state"
  local max_fail=3
  
  if ! detect_utm_detail "$url" > /dev/null 2>&1; then
    # 检测失败,计数+1
    local fail_count=0
    [ -f "$state_file" ] && fail_count=$(cat "$state_file")
    fail_count=$((fail_count + 1))
    echo "$fail_count" > "$state_file"
    
    if [ $fail_count -ge $max_fail ]; then
      # 达到阈值,发送告警并重置计数
      send_dingtalk "UTM参数持续丢失\nURL: $url\n已连续${max_fail}次检测异常"
      echo "0" > "$state_file"
    fi
  else
    # 检测正常,重置计数
    echo "0" > "$state_file"
  fi
}

配置crontab每10分钟跑一次:

*/10 * * * * /opt/utm_check/utm_dedup_check.sh >> /opt/utm_check/cron.log 2>&1

钉钉签名认证踩坑记录

钉钉机器人加签认证有几个坑,都是实际对接时踩过的:

  • 时间戳单位是毫秒:用date +%s%3N,不是date +%s(秒级),否则签名验证会报"timestamp is invalid"
  • 签名字符串格式:必须是${timestamp}\n${secret},中间是换行符\n,不是空格
  • Base64后需要urlencode:直接用base64输出会有换行符,必须先urlencode再拼到URL里
  • Shell里base64输出处理:用base64 -w 0禁止换行,否则签名会带换行符导致验证失败

相关文章

总结

UTM参数丢失的代价是被掩盖的真相:你不知道哪个渠道真的带来转化,优化投放只能靠猜。用上面三个脚本,从基础检测到生产级去重告警,一步步把营销追踪的监控盲点补上。10分钟配置好,后面就是它帮你盯着。

版权声明

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

发表评论