第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 个核心阶段:

  1. 下发阶段(reach.delivered):服务端返回触达内容,SDK 接收并缓存。
  2. 曝光阶段(reach.impression):组件进入视口且满足面积 / 时长阈值时触发。
  3. 交互阶段(reach.click / reach.dismiss):用户点击内容或关闭触达。
  4. 结束阶段(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 个规范:

  1. 初始化时机:SDK 必须在应用启动后 500ms 内完成初始化,否则可能导致触达下发时埋点尚未就绪。
  2. 事件去重:同一 task_id 的 impression 事件在 10s 内重复触发时,SDK 应自动丢弃(基于本地 buffer 去重表)。
  3. 字段补齐:前端埋点必须带上 device_id、task_id、strategy_id 三个关联字段,缺失任一字段的事件在服务端 join 时直接降级。
  4. 发送策略:事件先写入本地队列(上限 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 清洗及最终进入指标看板的路径:

埋点数据流架构 触达下发 (AI 决策) 服务端日志 (Avro) 前端埋点 (事件驱动) SDK 校验层 (去重/补齐) ETL 清洗 (Flink) 数据仓库 (ClickHouse) 说明:前端埋点经 SDK 校验后与服务端日志在 ETL 层按 task_id + device_id 做双流 join

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% 以内。