第3章:数据埋点规范
Reach 触达指标的可信度完全建立在埋点数据的质量上。本章围绕前端埋点事件设计、服务端日志字段规范、SDK 接入要点与校验方法展开,定义统一的数据采集口径,确保触达量、送达率、展示时长等核心指标可量化、可复现、可归因。
3.1 埋点指标体系与口径
| 指标名称 | 埋点来源 | 口径定义 | 事件类型 |
|---|---|---|---|
| 触达请求量 | 服务端日志 | AI 产品向客户端下发触达指令的总次数,去重按 device_id + task_id | server.reach.request |
| 前端展示量 | 前端埋点 | 触达组件成功渲染并进入视口的次数,曝光面积 ≥ 50% 且持续 ≥ 300ms | client.reach.impression |
| 送达率 | 服务端 + 前端 | 前端展示量 ÷ 触达请求量 × 100%,排除预加载未展示场景 | 计算指标 |
| 触达点击量 | 前端埋点 | 用户点击触达组件的总次数,含关闭按钮以外的任意交互 | client.reach.click |
| 展示时长 | 前端埋点 | 触达组件从首次曝光到离开视口的累计时长, session 内合并 | client.reach.duration |
3.2 前端埋点事件设计
前端埋点采用事件驱动 + 生命周期模型,每个触达组件从创建到销毁经历 4 个核心阶段:
- 下发阶段(reach.delivered):服务端返回触达内容,SDK 接收并缓存。
- 曝光阶段(reach.impression):组件进入视口且满足面积 / 时长阈值时触发。
- 交互阶段(reach.click / reach.dismiss):用户点击内容或关闭触达。
- 结束阶段(reach.completed / reach.timeout):触达流程自然结束或被新触达覆盖。
埋点事件结构规范(示例 JSON)
{
"event": "client.reach.impression",
"timestamp": 1711584000123,
"user": {
"device_id": "d7a9f2e1b3c4",
"user_id": "u_20240301_abc"
},
"reach": {
"task_id": "task_1711584000",
"template_id": "tpl_banner_v3",
"strategy_id": "strategy_rank_01",
"channel": "in_app_popup",
"render_duration_ms": 45,
"area_percent": 0.67,
"session_seq": 2
},
"device": {
"os": "iOS 17.3",
"screen_w": 390,
"screen_h": 844
},
"extra": {
"ab_test_group": "treatment_A"
}
}
3.3 服务端日志字段规范
服务端日志以 Apache Avro 格式序列化,保证字段类型严格一致。每个触达指令下发出时记录一条日志,关键字段如下:
| 字段名 | 类型 | 说明 | 是否必填 |
|---|---|---|---|
log_id |
string | 全局唯一日志ID,格式: yyyyMMddHHmmssSSS + 6位随机数 | 是 |
event_type |
string | 固定为 server.reach.request |
是 |
device_id |
string | 设备指纹,优先取 IDFA/OAID | 是 |
user_id |
string | 登录用户 ID,未登录为 null |
否 |
task_id |
string | 触达任务 ID,用于关联前端埋点 | 是 |
strategy_name |
string | 触达策略名称,如 rank_based_v2 |
是 |
server_timestamp |
long | 服务端下发时刻的 Unix 毫秒时间戳 | 是 |
3.4 SDK 接入要点
SDK 作为前端埋点与服务端日志的桥梁,接入时需重点校验 4 个规范:
- 初始化时机:SDK 必须在应用启动后 500ms 内完成初始化,否则可能导致触达下发时埋点尚未就绪。
- 事件去重:同一
task_id的 impression 事件在 10s 内重复触发时,SDK 应自动丢弃(基于本地 buffer 去重表)。 - 字段补齐:前端埋点必须带上
device_id、task_id、strategy_id三个关联字段,缺失任一字段的事件在服务端 join 时直接降级。 - 发送策略:事件先写入本地队列(上限 500 条),每 5s 批量上报一次;网络恢复后优先补发失败事件。
接入避坑: 服务端日志与前端埋点的
task_id 必须使用同一生成规则。曾因前端对 task_id 做了 URL 编码而服务端未编码,导致 join 匹配率从 97% 骤降到 62%。建议在 SDK 初始化时注入统一的 ID 生成器。
3.5 校验方法与验收标准
在埋点上线前,需通过以下 3 层校验才能放量:
| 校验层级 | 校验方法 | 阈值标准 | 工具 |
|---|---|---|---|
| L1 字段完整性 | 每条事件 JSON Schema 校验,必填字段缺失即告警 | 缺失率 < 0.1% | JSON Schema Validator |
| L2 时序一致性 | 服务端 server_timestamp 与前端 timestamp 差值 ≤ 3s |
一致率 ≥ 99% | Flink 实时对齐作业 |
| L3 指标还原度 | 选取 1 万条样本,人工标注前端展示与后台日志的匹配结果 | 准确率 ≥ 99.5% | 标注平台 + 差异分析脚本 |
3.6 埋点数据流架构
下图展示从触达下发到事件入库的完整数据流,包含前端埋点、服务端日志、SDK 校验层、ETL 清洗及最终进入指标看板的路径:
3.7 异常场景与业务动作
| 异常现象 | 常见原因 | 诊断方法 | 业务动作 |
|---|---|---|---|
| 送达率 < 50% | 前端曝光阈值过于严格(面积/时长要求过高) | 检查 area_percent 分布与 render_duration_ms 直方图 |
降低阈值至 30% / 200ms,观察 2 天后对比 |
| task_id 匹配率 < 90% | 前后端 task_id 编码规则不一致或截断 | 抽样比对原始日志中的 task_id 字符串长度 | 统一使用 SDK 提供的 ReachIdGenerator 生成 |
| 事件延迟 > 10s | 前端上报队列积压或服务端写入瓶颈 | 查看 SDK 本地队列剩余条数 + 服务端写入耗时 P99 | 缩短批量上报周期至 3s,扩容写入节点 |
| 点击率突降 > 40% | 埋点事件被浏览器广告拦截器屏蔽 | 检查 client.reach.click 上报量与 DOM 事件监听日志 |
改用私有域名上报,或增加 navigator.sendBeacon 兜底 |
3.8 复盘分析要点
每次触达活动结束后,需从埋点质量维度完成以下复盘:
- 字段完整率:必填字段缺失是否在 0.1% 以内,若超标需回溯是 SDK 版本未升级还是网络断连导致。
- 事件重复率:同一个
task_id+event_type在 30s 内重复计数占比,超过 5% 说明去重逻辑失效。 - 端到端延迟:服务端下发到前端曝光的时间差 P95,应 ≤ 3s;若劣化需检查 CDN 预热或渲染性能。
- 看板数据置信度:将看板中的触达展示量与第三方监测(如 AppsFlyer 回传)对比,偏差 ≤ 2% 视为可信。
经验沉淀: 在一次触达量 5000 万的大促活动中,发现前端 impression 事件比服务端 request 日志多出 12%。根因是预加载模式下组件在不可见时也触发了曝光。修复方案:在曝光判定中增加
isVisible 检测,将预加载场景单独标记为 reach.preloaded 事件,不参与送达率计算。此后指标偏差稳定在 0.5% 以内。