10 KiB
10 KiB
Quick Start: 声明式埋点上报系统
Feature: 005-declarative-tracking Audience: 开发者 Time: 5-10 分钟
Overview
本指南帮助您快速上手使用声明式埋点系统,从基础的手动埋点到高级的自动埋点功能。
Prerequisites
- Node.js 18+
- 项目已集成 Umami Analytics
- 了解基本的 React 和 TypeScript
Installation
1. 确认 Umami 已配置
检查 apps/web/index.html 或应用入口是否有 Umami 脚本:
<!-- 应该已存在 -->
<script
defer
src="https://your-umami-domain/script.js"
data-website-id="your-website-id"
></script>
2. 安装依赖
# 项目依赖已包含,无需额外安装
npm install
Basic Usage (基础埋点)
Step 1: 在 Drawnix 中启用埋点插件
修改 packages/drawnix/src/drawnix.tsx:
import { withTracking } from './plugins/tracking';
// 在其他插件后添加 withTracking
const editor = withMind(
withDraw(
withFreehand(
withTracking(
// 其他插件...
)
)
)
);
Step 2: 添加手动埋点属性
在任意 React 组件中使用 track 属性:
// 示例: UnifiedToolbar.tsx
export const UnifiedToolbar = () => {
return (
<div className="toolbar">
{/* 基础埋点 */}
<Button track="toolbar_click_pen">
<PenIcon />
</Button>
{/* 带参数的埋点 */}
<Button
track="toolbar_click_shape"
track-params='{"shape": "rectangle"}'
>
<RectIcon />
</Button>
{/* 不埋点 */}
<Button>
Normal Button
</Button>
</div>
);
};
Step 3: 验证埋点
- 启动开发服务器:
npm start - 打开浏览器控制台(F12)
- 点击添加了
track属性的按钮 - 查看控制台日志(开发模式下会输出):
[Tracking] Event tracked: toolbar_click_pen [Tracking] Batching event (1/10) - 等待 5 秒或点击 10 个事件后,检查网络请求:
POST https://your-umami-domain/api/send Payload: { name: "toolbar_click_pen", data: { version: "1.2.3", url: "..." } }
Advanced Usage (高级功能)
1. 自动埋点模式
启用自动埋点,无需手动添加 track 属性:
// packages/drawnix/src/drawnix.tsx
const editor = withTracking(
// ... other plugins
{
autoTrack: true // 启用自动埋点
}
);
效果:
- 所有
<button>,<a>,<input type="button">等交互元素自动埋点 - 事件名自动生成,基于元素特征(如按钮文本、ID、aria-label)
- 排除导航栏、页脚、工具栏等区域
示例:
// 无需 track 属性
<Button id="save-btn">保存</Button>
// 自动生成事件名: auto_click_save-btn 或 auto_click_保存
2. 排除特定元素
使用 data-track-ignore 属性排除埋点:
<nav data-track-ignore>
<Button>导航按钮</Button> {/* 不会自动埋点 */}
</nav>
<Button data-track-ignore>
临时不埋点的按钮
</Button>
3. 支持其他事件类型
除了 click,还支持 hover、focus 等事件:
// Hover 埋点
<Card track-hover="card_hover_features">
Feature Card
</Card>
// Focus 埋点
<Input track-focus="input_focus_search" />
// 同时支持多种事件
<Element
track="element_click"
track-hover="element_hover"
track-focus="element_focus"
/>
Configuration (配置)
全局配置
创建 packages/drawnix/src/config/tracking.config.ts:
import type { TrackConfig } from '../types/tracking.types';
export const trackingConfig: Partial<TrackConfig> = {
autoTrack: false, // 默认关闭自动埋点
debounceTime: 500, // 防抖 500ms
logLevel: 'error', // 生产环境只记录错误
batchConfig: {
enabled: true,
batchSize: 10, // 10 个事件批量上报
batchTimeout: 5000 // 或 5 秒超时
},
excludedSelectors: [
'nav',
'header',
'footer',
'[data-track-ignore]',
'.no-track' // 自定义排除类
]
};
应用配置:
// drawnix.tsx
import { trackingConfig } from './config/tracking.config';
const editor = withTracking(
// ... plugins
trackingConfig
);
环境变量配置
在 vite.config.ts 中注入版本号:
// vite.config.ts
import { defineConfig } from 'vite';
import packageJson from './package.json';
export default defineConfig({
define: {
'import.meta.env.VITE_APP_VERSION': JSON.stringify(packageJson.version)
}
});
Testing (测试)
开发环境测试
启用调试模式:
const editor = withTracking(
// ... plugins
{
devMode: true, // 启用开发模式
logLevel: 'debug' // 输出详细日志
}
);
控制台输出示例:
[Tracking] Service initialized
[Tracking] Event captured: button_click_save
[Tracking] Debounce check passed
[Tracking] Event queued (1/10)
[Tracking] Batch timeout started (5s)
[Tracking] Batch uploading (10 events)
[Tracking] Upload successful
单元测试
// packages/drawnix/src/services/tracking/__tests__/tracking-service.test.ts
import { TrackingService } from '../tracking-service';
describe('TrackingService', () => {
let service: TrackingService;
beforeEach(() => {
service = new TrackingService(mockConfig);
});
it('should track event', async () => {
await service.track('test_event', { param: 'value' });
expect(service.getStats().totalEvents).toBe(1);
});
it('should debounce duplicate events', async () => {
const element = document.createElement('button');
await service.track('test_event', {}, element);
await service.track('test_event', {}, element); // 应被防抖
expect(service.getStats().totalEvents).toBe(1);
});
});
E2E 测试
// tests/e2e/tracking/declarative-tracking.spec.ts
import { test, expect } from '@playwright/test';
test('should track button click', async ({ page }) => {
// 监听网络请求
const requests: any[] = [];
page.on('request', request => {
if (request.url().includes('/api/send')) {
requests.push(request.postDataJSON());
}
});
// 访问页面
await page.goto('http://localhost:7200');
// 点击埋点按钮
await page.click('[track="button_click_save"]');
// 等待批量上报(最多 5 秒)
await page.waitForTimeout(5500);
// 验证请求
expect(requests.length).toBeGreaterThan(0);
expect(requests[0].name).toBe('button_click_save');
expect(requests[0].data.version).toBeDefined();
expect(requests[0].data.url).toContain('localhost:7200');
});
Troubleshooting (问题排查)
1. 埋点不生效
症状: 点击元素后没有上报事件
排查步骤:
- 检查 Umami SDK 是否加载:
console.log(window.umami); // 应该是一个对象 - 检查插件是否启用:
// drawnix.tsx 中是否调用了 withTracking - 检查元素是否被排除:
// 元素是否在 nav/header/footer 内? // 元素是否有 data-track-ignore 属性? - 检查防抖:
// 是否在 500ms 内重复点击?
2. 批量上报不触发
症状: 事件队列一直累积,不上报
排查步骤:
- 检查批量配置:
batchConfig: { enabled: true // 是否启用? } - 检查网络连接:
curl https://your-umami-domain/api/send - 查看控制台错误:
// 是否有 CORS 错误? // 是否有 401/403 认证错误?
3. 缓存不工作
症状: 离线时事件丢失,未缓存
排查步骤:
- 检查 IndexedDB 是否可用:
console.log(window.indexedDB); // 应该存在 - 检查 localforage 初始化:
import localforage from 'localforage'; const cache = await localforage.getItem('tracking_cache'); console.log(cache);
4. 版本号不显示
症状: Umami 面板中 version 字段为空
排查步骤:
- 检查环境变量:
console.log(import.meta.env.VITE_APP_VERSION); - 检查 vite.config.ts 配置
- 重新构建项目:
npm run build
Best Practices (最佳实践)
1. 事件命名规范
推荐:
// 使用 snake_case,包含动作和对象
track="button_click_save"
track="card_hover_feature"
track="input_focus_search"
不推荐:
// 太简短,不明确
track="click"
track="save"
// 太长,冗余
track="user_clicked_the_save_button_in_the_toolbar"
2. 参数设计
推荐:
<!-- 有意义的结构化参数 -->
<Button
track="toolbar_click_shape"
track-params='{"shape": "rectangle", "color": "red"}'
/>
不推荐:
<!-- 参数过多或无用 -->
<Button
track="click"
track-params='{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, ...}'
/>
3. 性能优化
- ✅ 使用批量上报(减少网络请求)
- ✅ 启用防抖(避免重复上报)
- ✅ 合理配置排除区域(减少无用埋点)
- ❌ 不要在高频事件上埋点(如 mousemove)
4. 隐私保护
- ✅ 不在
track-params中包含敏感信息(密码、信用卡号) - ✅ 过滤用户输入的文本内容
- ✅ 遵守 GDPR/CCPA 合规要求
Next Steps
- 📖 阅读 data-model.md 了解数据结构
- 📖 阅读 contracts/umami-api.md 了解 API 集成
- 🛠️ 查看 tasks.md 了解实现细节(待生成)
- 🧪 运行测试:
npm test packages/drawnix/src/services/tracking
FAQ
Q: 自动埋点会影响性能吗? A: 性能开销 <2%,使用事件委托和防抖机制优化。
Q: 可以在生产环境禁用埋点吗?
A: 可以,设置 logLevel: 'silent' 并在配置中禁用所有埋点。
Q: 支持移动端吗? A: 支持,touch 事件会映射到 click 事件。
Q: 如何自定义事件名生成规则?
A: 修改 tracking-utils.ts 中的 generateAutoEventName() 函数。
Happy Tracking! 🎉