4. 埋点属性设计规范:通用属性、业务属性、事件属性、用户属性的定义与约束
属性设计,说白了就是给每个埋点事件贴上「标签」。标签贴得乱,后面分析全抓瞎。我见过太多团队,埋点上了几百个,最后问「用户从哪个渠道来的?」——答不上来,因为渠道字段有的叫 channel,有的叫 utm_source,有的干脆没传。
这一章,咱们就把属性的四大家族理清楚:通用属性、业务属性、事件属性、用户属性。每个家族该管什么、不该管什么,边界在哪,约束条件是什么。嗯,这都是我踩过坑之后才总结出来的。
4.1 四类属性的核心定位
先看一张图,把四类属性的关系搞清楚。
你看,通用属性和用户属性是「基础设施」,每条事件都自动带上。事件属性和业务属性是「业务表达」,按需设计。四者泾渭分明,不能混用。
4.2 通用属性:全局统一的「身份证」
通用属性是什么?就是不管什么事件,都必须携带的那几个字段。我习惯叫它「埋点身份证」。
通用属性清单(强制)
| 属性名 | 类型 | 示例值 | 说明 |
|---|---|---|---|
| device_id | string | a1b2c3d4-... | 设备唯一标识,IDFA/IMEI/OAID |
| platform | string | ios / android / web | 操作系统或平台 |
| app_version | string | 3.2.1 | App 版本号,Web 可传空 |
| network_type | string | wifi / 4g / 5g | 网络环境 |
| event_time | long | 1712563200000 | 事件触发时间戳(毫秒) |
| session_id | string | sess_abc123 | 会话 ID,用于归因 |
这里有个坑。我遇到过团队把 app_version 写成 version,另一个团队写成 appVersion。最后做版本分析时,两个字段对不上,数据直接废了。所以通用属性必须统一命名,大小写、下划线、类型都得定死。
通用属性约束
- 所有事件必须携带,缺失则丢弃该条事件
- 字段名全局唯一,不允许重名
- 类型固定,不允许同一字段在不同事件中类型不一致
- 由 SDK 自动采集,业务方无需手动传入
4.3 业务属性:灵活扩展的「业务语言」
业务属性是最灵活、也最容易失控的部分。说白了,业务方想加什么就加什么,但加多了就变成垃圾场。
我举个例子。电商的「下单」事件,业务属性可能包括:
order_id— 订单号total_amount— 订单总金额coupon_id— 使用的优惠券 IDsku_list— 商品 SKU 列表pay_channel— 支付渠道
看起来没问题对吧?但实际项目中,我见过有人把 user_name 也塞进业务属性里。这就错了——用户信息应该走用户属性,不是业务属性。
我的经验法则
业务属性只放「这个事件特有的业务数据」。如果某个字段在多个事件中都出现,且描述的是同一个业务对象,那就应该抽成公共属性或者用户属性。
4.4 事件属性:描述「发生了什么」
事件属性是每个事件自带的元信息。它不关心业务细节,只关心事件本身。
标准的事件属性包括:
| 属性名 | 类型 | 说明 |
|---|---|---|
| event_name | string | 事件名称,如 view_item、add_to_cart |
| page_url | string | 当前页面 URL |
| page_title | string | 页面标题 |
| referrer | string | 来源页面 |
| screen_width | int | 屏幕宽度 |
| screen_height | int | 屏幕高度 |
你可能会问:page_url 和 referrer 算不算通用属性?我个人习惯把它们归到事件属性,因为不同事件可能在不同页面触发,page_url 是跟着事件走的。通用属性是「无论在哪都一样的」,事件属性是「跟着事件变的」。
4.5 用户属性:用户维度的「画像标签」
用户属性描述的是「这个用户是谁」。它不随事件变化,而是随用户状态变化。
常见的用户属性:
user_id— 登录用户 IDuser_level— 会员等级register_channel— 注册渠道register_time— 注册时间last_login_time— 最后登录时间
用户属性更新规则
用户属性是「缓慢变化维度」。不要每条事件都去更新用户属性,那样会浪费大量存储和计算资源。我建议:
- 用户属性只在登录、注册、信息修改时更新
- 每次更新带上时间戳,方便回溯
- 用户属性变更要记录变更日志,便于排查
4.6 属性命名与类型约束
这一节是硬规矩。命名不规范,后面全是坑。
命名规范
- 全部小写 + 下划线:
user_level,不是userLevel或UserLevel - 不超过 64 个字符
- 以字母开头,只包含字母、数字、下划线
- 禁止使用保留关键字(如
event、user、time)
类型约束
| 类型 | 示例 | 约束 |
|---|---|---|
| string | "ios" | 长度不超过 1024 字符 |
| int | 100 | 32 位有符号整数 |
| long | 1712563200000 | 64 位有符号整数,时间戳专用 |
| float | 99.99 | 保留 2 位小数 |
| boolean | true | 不允许传 0/1 |
| array | ["a","b"] | 元素类型必须一致 |
我曾经遇到一个项目,total_amount 在 iOS 端传的是 float,在 Android 端传的是 string。结果做聚合分析时,Android 的数据全被当成字符串拼接了。嗯,从那以后我强制要求类型校验必须在 SDK 层做掉。
4.7 属性治理的「三不」原则
最后,分享一个我总结的「三不」原则:
- 不重复:同一个业务含义,只用一个属性名。比如「商品价格」要么统一用
price,要么统一用product_price,不能混用。 - 不滥用:不要把业务属性当通用属性用。比如
coupon_id只在「领券」和「下单」事件中出现,就不要加到所有事件里。 - 不缺失:通用属性和事件属性必须非空。业务属性如果为空,要明确是「没有值」还是「值未知」,用
null还是""要提前约定好。
总结一下
属性设计是埋点治理的基石。通用属性管「全局统一」,业务属性管「业务表达」,事件属性管「事件描述」,用户属性管「用户画像」。四者各司其职,互不干扰。命名和类型约束是硬规矩,谁都不能破。做到这些,你的埋点数据至少能保证「可用」。