资讯文章 资讯 · NEWS
埋点为什么总对不上数:目录站的事件模型、会话口径和重复上报
2026-10-24 约 1,521 字 预计阅读 4 分钟 yiyunkj
埋
「昨天有多少人访问」这个看似简单的问题,在没文档的情况下至少有三种答案:第三方统计按会话算、服务端日志按请求算、数据库里记录的又是另一套。三方数字不一致时,团队最常见的反应是争论哪个对,而不是先问它们各自的口径是什么。
所以第一件事不是接更多工具,是写文档。

图片来源:网络,版权归原作者所有,侵权请联系删除
先把四件事写死
| 口径 | 要写清什么 | 典型默认值 |
|---|---|---|
| 会话 | 多久无活动算结束 | GA4 默认 30 分钟无活动 |
| 去重 | 什么算重复事件 | 事件 ID + 时间窗 |
| 归属 | 跨天的会话算哪天 | 按会话开始时间 |
| 保留 | 原始事件存多久 | GA4 标准版默认偏短,可调至 14 个月 |
会话定义是最容易出偏差的一处。相邻两次交互间隔多久算同一个会话?跨零点怎么办?同一用户换个设备算几个?没有统一定论,但必须有统一答案。第三方工具的默认值(如 GA4 的 30 分钟无活动)可以直接采用,前提是所有人知道它是这个数。
事件该怎么命名
目录站的埋点不需要几十个事件,把常用的收成一个小表:
| 事件 | 触发时机 | 关键参数 |
|---|---|---|
| view_category | 分类页渲染完成 | cat_id, page_no |
| view_item | 条目详情页可见 | item_id, source |
| outbound_click | 点击出站链接 | item_id, target_host |
| search | 提交搜索 | query_len, result_count |
| submit_item | 提交收录表单 | validation_result |
三条命名原则:动词开头、用下划线、参数值统一用 ID 而不是中文名。最后一条特别重要——分类名改一次,历史数据就断一次。
三种真实的少记与多记
页面关闭那一刻丢的数据
用户点了出站链接,新窗口打开,本页即将卸载。这个时候发的请求很可能被浏览器取消。可靠的做法是改用 sendBeacon 或 fetch keepalive:
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/collect', JSON.stringify(payload));
}
});
顺带一句:把发送逻辑挂在 unload 事件上是老写法,它在移动端本来就不可靠,还会让页面失去往返缓存资格——这点前面那篇专门讲过。
重复上报
单页应用路由变化被重复触发、前端重试机制重发了成功但超时的请求、用户快速双击,都会导致同一个行为被记两次。解法是给每个事件生成一次的 event_id,服务端按「事件 ID + 时间窗」去重。这条做了,数字往往立刻收敛一截。
机器人与拦截器
第三方工具依赖 JS,被广告拦截插件拦掉的比例在部分受众里能到两位数;而服务端日志不执行 JS,会把大量爬虫请求也记成访问。两边相差的那部分,通常就是这两坨。
两边都要写,用途不同
不要指望一套数据满足所有需求。合理的分工是:
| 来源 | 长处 | 短处 |
|---|---|---|
| 前端埋点 | 识别用户行为、滚动、点击 | 会被拦截,受 JS 环境影响 |
| 服务端日志 | 视野完整,包含爬虫 | 看不到纯前端交互 |
| 业务数据库 | 结果最准(如真实提交数) | 无法反映漏斗过程 |
关键指标(如真实收到的提交数)以业务库为准;行为指标(如从列表到详情的点击率)以埋点为准;抓取相关的口径以日志为准。三条线各管一段,比强行对齐成一个数字更结实。
最后两条约束
一是最小必要。个人信息保护法要求收集个人信息限于实现处理目的的最小范围。填写查询词这类可能识别到个人的字段,能存哈希就别存原文,能聚合就别留明细,并设定明确的删除周期。
二是标识符要慎重。别把自增主键当公开的用户 ID 用(会泄露注册量),用随机生成的 UID。这一条和站点安全那部分是同一件事。
加起来就一句:把口径写成一页文档放在团队看得见的地方,比买任何工具都管用。