1. 埋点数据模型设计:事件类型定义、属性字段、用户标识、时间戳规范
埋点数据模型是数据采集的基石,决定了后续分析的维度、准确性与扩展性。本章定义统一的数据契约,涵盖事件类型、属性字段、用户标识与时间戳四大要素。
1.1 事件类型定义
事件类型用于区分用户行为的业务含义,采用枚举式分层结构:
- 页面事件 —
page_view(页面浏览)、page_leave(页面离开) - 交互事件 —
click(点击)、long_press(长按)、swipe(滑动) - 业务事件 —
purchase(购买)、login(登录)、share(分享) - 性能事件 —
cold_start(冷启动耗时)、frame_drop(丢帧)
1.2 属性字段规范
每个事件携带公共属性与事件特有属性,采用扁平化 JSON 对象传输。
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
event_name | String | 事件名称 | "click" |
screen_name | String | 当前页面路由 | "home" |
component_id | String | Composable 组件唯一标识 | "btn_login" |
extra | Map<String,Any> | 自定义扩展属性 | {"item_id": "1001"} |
1.3 用户标识策略
采用设备 ID + 登录用户 ID 双标识体系,保证设备级与账号级归因。
- device_id:首次安装时通过 Android ID + UUID 生成,存储于 EncryptedSharedPreferences。
- user_id:登录成功后写入,登出时清除;未登录时置空。
- session_id:每次冷启动重新生成,关联事件序列。
1.4 时间戳规范
统一使用毫秒级 Unix 时间戳,由客户端在事件发生瞬间采集,避免服务器时间偏差。
// 时间戳生成示例(Kotlin)
val timestamp = System.currentTimeMillis() // 毫秒
val event = Event(
eventName = "click",
componentId = "btn_pay",
timestamp = timestamp,
deviceId = deviceId,
userId = userId
)
1.5 完整数据模型结构
注意:事件序列必须保证
timestamp 严格递增;同一会话内 session_id 保持不变;服务器端拒绝接收 timestamp 与接收时间差超过 10 分钟的事件。
1.6 代码实现:Kotlin 数据类
data class Event(
val eventName: String,
val screenName: String?,
val componentId: String?,
val extra: Map<String, Any> = emptyMap(),
val deviceId: String,
val userId: String?,
val sessionId: String,
val timestamp: Long
)
// 使用示例
val loginClick = Event(
eventName = "click",
screenName = "login",
componentId = "btn_login_confirm",
extra = mapOf("click_source" to "button"),
deviceId = deviceId,
userId = null,
sessionId = sessionId,
timestamp = System.currentTimeMillis()
)
1.7 属性字段扩展原则
最佳实践:避免在
extra 中嵌套过深对象,保持扁平结构;对于频繁出现的自定义属性(如 item_id、category),建议提升为顶级字段,减少解析开销。
1.8 数据校验清单
- 事件名称符合枚举范围,非空且长度 ≤ 64
- device_id 不可为空,userId 可为空但需用
null而非空字符串 - timestamp 为 13 位毫秒级数字,范围在 1970-01-01 之后
- extra 中键值对的键名使用 camelCase,值类型为 String / Number / Boolean