nginx 可通过 userid 模块实现无埋点用户留存分析:仅在目标 location 启用并配置 uid 生命周期,结合 $uid_got 与 $uid_set 区分新/回访用户,用 map 统一多路径 uid 标识,ssi 场景下改用 $cookie_uid 替代。

想在不引入埋点 SDK 或前端 JS 的前提下,对特定业务路径(比如 /order/submit、/api/v2/profile)做轻量级用户留存分析,Nginx 原生的 $uid_set 和 $uid_got 变量就能直接支撑——关键在于精准控制模块启用范围 + 合理设计日志字段。
只在目标 location 中启用 userid 模块
避免全局污染和性能开销,不要在 http 或 server 块中写 userid on。只在需分析的路径下开启:
location /order/submit {-
userid on; -
userid_name uid; -
userid_expires 365d; -
userid_domain example.com; }
这样只有访问该路径时才会生成或读取 uid Cookie,其他请求完全无额外处理。
日志格式中区分“新访”与“回访”
$uid_got 表示客户端本次请求携带的 UID(可能为空),$uid_set 表示 Nginx 本次是否新设置了 UID(值为 0 或 1)。组合使用可判断用户类型:
log_format retention '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '$uid_got $uid_set $request_time';- 当日志中出现
- 1(即$uid_got为空、$uid_set为 1),说明是首次访问该路径的新用户; - 出现
abc123 0,说明是携带已有 UID 的回访用户。
用 map 实现多路径统一 UID 标识逻辑
若多个路径(如 /login、/dashboard、/payment)需共用同一套 UID 生命周期,可在 http 块顶层用 map 统一提取:
map $cookie_uid $uid_for_log {-
default $cookie_uid; -
"" "-"; }
然后在各目标 location 中启用 userid,并在日志中直接使用 $uid_for_log。这样既保持路径粒度控制,又确保 UID 语义一致,便于后续按天/路径聚合计算次日/7 日留存率。
注意 SSI 场景下的变量不可用问题
如果业务用了 Server-Side Include(SSI),$uid_got 和 $uid_set 在 SSI 指令中无法获取——因为 SSI 模块执行早于 userid 模块。此时应改用 $cookie_uid 直接读取原始 Cookie 值,并在日志中记录,虽不反映“本次是否新设”,但足以支持基于 UID 的去重与路径流转分析。











