埋点不是"想埋就埋"。
没有规范的埋点,3个月后你自己都不知道
btn_click和button_click有什么区别。这篇文章,我会给你一套可落地的埋点设计规范。
一、为什么需要埋点规范?
没有规范的埋点会怎样?
| 问题 | 后果 |
|---|---|
| 命名不统一 | click_btn vs btn_click vs button_click,数据无法聚合 |
| 参数不一致 | 同一个事件,A传page,B传page_path,C传path |
| 重复埋点 | 同一个按钮埋了3次,PV虚高3倍 |
| 遗漏埋点 | 核心功能没有埋点,关键数据缺失 |
| 无法下线 | 不知道哪些事件还在用,不敢删除 |
一句话:没有规范的埋点,数据就是垃圾。
二、埋点命名规范
2.1 事件命名规范
格式:对象_动作
code复制
bash
{object}_{action}
对象命名规则:
| 对象类型 | 前缀 | 示例 |
|---|---|---|
| 页面 | page |
page_view, page_stay |
| 按钮 | btn |
btn_click, btn_longpress |
| 列表 | list |
list_scroll, list_loadmore |
| 表单 | form |
form_submit, form_reset |
| 弹窗 | modal |
modal_show, modal_close |
| 分享 | share |
share_click, share_success |
| 支付 | pay |
pay_click, pay_success, pay_fail |
| 搜索 | search |
search_submit, search_result_click |
动作命名规则:
| 动作 | 说明 | 示例 |
|---|---|---|
view |
查看 | page_view |
click |
点击 | btn_click |
show |
展示 | modal_show |
close |
关闭 | modal_close |
submit |
提交 | form_submit |
success |
成功 | pay_success |
fail |
失败 | pay_fail |
scroll |
滚动 | list_scroll |
loadmore |
加载更多 | list_loadmore |
2.2 参数命名规范
格式:小写 + 下划线
code复制
bash
{category}_{name}
| 参数分类 | 前缀 | 示例 |
|---|---|---|
| 页面相关 | page_ |
page_path, page_title, page_from |
| 按钮相关 | btn_ |
btn_id, btn_text, btn_position |
| 列表相关 | list_ |
list_id, list_index, list_total |
| 搜索相关 | search_ |
search_keyword, search_result_count |
| 用户相关 | user_ |
user_id, user_level, user_type |
| 商品相关 | item_ |
item_id, item_name, item_price |
| 订单相关 | order_ |
order_id, order_amount, order_status |
2.3 参数值规范
| 参数类型 | 格式 | 示例 |
|---|---|---|
| 字符串 | 小写 + 下划线 | page_path: "/pages/index/index" |
| 数字 | 纯数字 | item_price: 99.9 |
| 布尔 | true/false | is_new_user: true |
| 枚举 | 预定义枚举值 | pay_method: "wechat" |
| 数组 | JSON数组 | item_ids: ["id1", "id2"] |
禁止的参数值:
| 禁止 | 原因 |
|---|---|
| 中文 | 编码问题,查询困难 |
| 大写字母 | 不统一,容易混淆 |
| 空格 | 查询困难 |
| 特殊字符 | 编码问题 |
三、埋点分类规范
3.1 三类埋点
| 类型 | 说明 | 示例 |
|---|---|---|
| 页面级埋点 | 自动采集,无需手动埋点 | page_view, page_stay |
| 操作级埋点 | 用户交互,需要手动埋点 | btn_click, form_submit |
| 业务级埋点 | 业务事件,需要手动埋点 | pay_success, share_complete |
3.2 页面级埋点(自动采集)
javascript复制
bash
// 页面级自动埋点
function setupAutoTrack() {
const originalPage = Page;
Page = function(config) {
const originalOnShow = config.onShow;
const originalOnHide = config.onHide;
config.onShow = function() {
tracker.track('page_view', {
page_path: this.route,
page_title: this.data.pageTitle || '',
});
if (originalOnShow) originalOnShow.call(this);
};
config.onHide = function() {
tracker.track('page_stay', {
page_path: this.route,
stay_duration: Date.now() - this._showTime,
});
if (originalOnHide) originalOnHide.call(this);
};
originalPage(config);
};
}
3.3 操作级埋点(手动埋点)
javascript复制
bash
// 按钮点击
tracker.track('btn_click', {
btn_id: 'submit_order',
btn_text: '提交订单',
page_path: '/pages/order/order',
btn_position: 'bottom',
});
// 表单提交
tracker.track('form_submit', {
form_id: 'login_form',
form_fields: Object.keys(formData).join(','),
form_result: 'success',
page_path: '/pages/login/login',
});
3.4 业务级埋点(手动埋点)
javascript复制
bash
// 支付流程
tracker.track('pay_click', {
order_id: this.data.orderId,
order_amount: this.data.orderAmount,
pay_method: 'wechat',
page_path: '/pages/order/order',
});
// 支付成功
tracker.track('pay_success', {
order_id: this.data.orderId,
order_amount: this.data.orderAmount,
pay_method: 'wechat',
});
// 支付失败
tracker.track('pay_fail', {
order_id: this.data.orderId,
order_amount: this.data.orderAmount,
pay_method: 'wechat',
fail_reason: err.errMsg,
});
四、埋点注册管理
4.1 埋点注册表
javascript复制
bash
const EVENT_REGISTRY = {
'page_view': {
description: '页面浏览',
category: 'page',
auto: true,
properties: {
page_path: { type: 'string', required: true, description: '页面路径' },
page_title: { type: 'string', required: false, description: '页面标题' },
page_from: { type: 'string', required: false, description: '来源页面' },
}
},
'page_stay': {
description: '页面停留',
category: 'page',
auto: true,
properties: {
page_path: { type: 'string', required: true, description: '页面路径' },
stay_duration: { type: 'number', required: true, description: '停留时长(ms)' },
}
},
'btn_click': {
description: '按钮点击',
category: 'interaction',
auto: false,
properties: {
btn_id: { type: 'string', required: true, description: '按钮ID' },
btn_text: { type: 'string', required: false, description: '按钮文案' },
page_path: { type: 'string', required: true, description: '页面路径' },
btn_position: { type: 'string', required: false, description: '按钮位置' },
}
},
'pay_click': {
description: '支付点击',
category: 'business',
auto: false,
properties: {
order_id: { type: 'string', required: true, description: '订单ID' },
order_amount: { type: 'number', required: true, description: '订单金额' },
pay_method: { type: 'string', required: true, description: '支付方式' },
page_path: { type: 'string', required: true, description: '页面路径' },
}
},
};
4.2 埋点校验
javascript复制
bash
class EventValidator {
constructor(registry) { this.registry = registry; }
validate(eventName, properties) {
const errors = [];
const schema = this.registry[eventName];
if (!schema) {
errors.push(`未注册的事件: ${eventName}`);
return errors;
}
for (const [name, prop] of Object.entries(schema.properties)) {
if (prop.required && !properties[name]) {
errors.push(`缺少必填参数: ${name}`);
}
}
for (const [name, value] of Object.entries(properties)) {
const prop = schema.properties[name];
if (prop && value !== undefined && typeof value !== prop.type) {
errors.push(`参数类型错误: ${name} 期望 ${prop.type},实际 ${typeof value}`);
}
}
return errors;
}
}
五、埋点文档管理
5.1 埋点文档模板
markdown复制
bash
## 事件名:btn_click
| 字段 | 内容 |
|------|------|
| **事件名** | btn_click |
| **事件描述** | 用户点击按钮 |
| **事件分类** | 操作级 |
| **触发时机** | 用户点击任何按钮时 |
| **是否自动采集** | 否 |
| **负责人** | 张三 |
| **创建时间** | 2026-06-17 |
### 参数列表
| 参数名 | 类型 | 必填 | 描述 | 示例值 |
|--------|------|------|------|--------|
| btn_id | string | 是 | 按钮唯一标识 | submit_order |
| btn_text | string | 否 | 按钮文案 | 提交订单 |
| page_path | string | 是 | 页面路径 | /pages/order/order |
| btn_position | string | 否 | 按钮位置 | bottom |
5.2 埋点变更流程
code复制
bash
提出变更 → 评审 → 开发 → 测试 → 上线 → 文档更新
| 步骤 | 说明 | 负责人 |
|---|---|---|
| 提出变更 | 提交埋点变更申请 | 产品/运营 |
| 评审 | 评估埋点合理性 | 数据分析师 |
| 开发 | 按规范实现埋点代码 | 开发 |
| 测试 | 验证埋点数据是否正确 | 测试 |
| 上线 | 发布埋点代码 | 开发 |
| 文档更新 | 更新埋点文档 | 数据分析师 |
六、埋点质量控制
6.1 埋点监控规则
javascript复制
bash
const monitorRules = [
// 未注册事件
(event) => {
if (!EVENT_REGISTRY[event.event_name]) {
return `未注册事件: ${event.event_name}`;
}
},
// 缺少必填参数
(event) => {
const schema = EVENT_REGISTRY[event.event_name];
if (!schema) return null;
const missing = [];
for (const [name, prop] of Object.entries(schema.properties)) {
if (prop.required && !event.properties[name]) missing.push(name);
}
if (missing.length > 0) return `${event.event_name} 缺少必填参数: ${missing.join(', ')}`;
},
// 事件时间是未来
(event) => {
if (event.event_time > Date.now() + 60000) {
return `${event.event_name} 事件时间是未来: ${event.event_time}`;
}
},
// 参数值超过255字符
(event) => {
for (const [name, value] of Object.entries(event.properties || {})) {
if (typeof value === 'string' && value.length > 255) {
return `${event.event_name} 参数 ${name} 超过255字符`;
}
}
},
];
七、埋点扩展性设计
7.1 插件化架构
javascript复制
bash
class PluginTracker extends Tracker {
constructor(options) {
super(options);
this.plugins = [];
}
use(plugin) {
this.plugins.push(plugin);
if (plugin.install) plugin.install(this);
return this;
}
track(eventName, properties = {}) {
let enhancedProps = { ...properties };
for (const plugin of this.plugins) {
if (plugin.beforeTrack) {
enhancedProps = plugin.beforeTrack(eventName, enhancedProps) || enhancedProps;
}
}
super.track(eventName, enhancedProps);
for (const plugin of this.plugins) {
if (plugin.afterTrack) plugin.afterTrack(eventName, enhancedProps);
}
}
}
7.2 常用插件
性能监控插件: 自动注入内存、页面加载时间等性能数据。
用户属性插件: 自动注入用户等级、类型等属性数据。
AB实验插件: 自动注入实验分组数据。
八、埋点规范总结
8.1 命名规范
| 规则 | 格式 | 示例 |
|---|---|---|
| 事件名 | 对象_动作 |
btn_click |
| 参数名 | 分类_名称 |
page_path |
| 参数值 | 小写+下划线 | submit_order |
8.2 埋点分类
| 类型 | 采集方式 | 示例 |
|---|---|---|
| 页面级 | 自动 | page_view, page_stay |
| 操作级 | 手动 | btn_click, form_submit |
| 业务级 | 手动 | pay_success, share_complete |
8.3 管理规范
| 规范 | 说明 |
|---|---|
| 注册制度 | 每个埋点必须在注册表中登记 |
| 文档制度 | 每个埋点必须有文档 |
| 变更流程 | 提出→评审→开发→测试→上线→文档更新 |
| 校验机制 | 开发环境自动校验 |
| 监控机制 | 线上自动监控异常数据 |
| 扩展性 | 插件化架构,方便扩展 |
写在最后
埋点规范,不是"增加工作量",而是"减少返工"。
没有规范的埋点,3个月后:
- 你不知道
btn_click和button_click有什么区别 - 你不知道
page是页面路径还是页面名称 - 你不知道哪些埋点还在用,哪些可以删除
有了规范的埋点:
- 任何人看到
btn_click,就知道是"按钮点击"事件 - 任何人看到
page_path,就知道是"页面路径"参数 - 你可以放心删除不再使用的埋点,因为文档记录了一切
埋点规范,是数据质量的基础。
