mineru-tracker-sdk
v1.0.4
Published
MinerU 埋点 SDK - 支持 Web 和 Electron 平台的埋点、日志监控、性能采集
Maintainers
Readme
mineru-tracker-sdk
MinerU 埋点 SDK - 支持 Web 和 Electron 平台的埋点、日志监控、性能采集。
特性
- 支持多平台:Web、Electron(主进程 + 渲染进程)
- 自动采集:PV/UV、性能指标(FCP/LCP/TTFB/FID/CLS)、JS 错误、资源加载错误
- 批量上报:支持批量合并上报,减少网络请求
- 离线缓存:Electron 环境支持离线数据缓存,网络恢复后自动上传
- 隐私合规:支持用户隐私偏好设置
- 插件化架构:灵活扩展
安装
npm install mineru-tracker-sdkpnpm add mineru-tracker-sdkyarn add mineru-tracker-sdk快速开始
第一步:初始化配置
import { Tracker } from 'mineru-tracker-sdk';
const tracker = Tracker.getInstance();
await tracker.init({
// 必填项
productName: 'my-web-app',
serverUrl: 'https://api.example.com',
// 可选项
appVersion: '1.0.0',
debug: true,
// 上报策略
batchSize: 10,
flushInterval: 10000,
// 自动采集开关
autoTrackPageView: true,
autoTrackPerformance: true,
autoTrackError: true,
autoTrackResource: true,
});第二步:注册插件(可选)
Click 插件配置注意事项
默认行为:Click 插件会自动采集所有 button、a、[data-track] 元素的点击。
如果你不希望自动采集所有按钮和链接的点击,需要自定义 autoTrackSelectors:
import { ClickPlugin } from 'mineru-tracker-sdk';
// 推荐:只采集带 data-track 属性的元素
const clickPlugin = new ClickPlugin({
autoTrackSelectors: ['[data-track]'],
throttleInterval: 300,
});
tracker.use(clickPlugin);在 HTML 中标记需要追踪的元素:
<!-- 会被采集 -->
<button data-track="add_cart" data-track-sku="SKU001">加入购物车</button>
<!-- 不会被采集 -->
<button>普通按钮</button>第三步:基础使用
React 项目
import { useEffect } from 'react';
import { Tracker, ClickPlugin } from 'mineru-tracker-sdk';
function App() {
useEffect(() => {
const tracker = Tracker.getInstance();
tracker.init({
productName: 'my-react-app',
serverUrl: 'https://api.example.com',
debug: true,
}).then(() => {
tracker.use(new ClickPlugin({
autoTrackSelectors: ['[data-track]'],
}));
});
return () => {
tracker.flush();
};
}, []);
const handleLogin = (userId: string, userInfo: { name: string }) => {
const tracker = Tracker.getInstance();
tracker.identify(userId, {
$username: userInfo.name,
}).alias();
};
return (
<div>
<button data-track="add_cart" data-track-sku="SKU001">
加入购物车
</button>
</div>
);
}原生 JavaScript
import { Tracker, ClickPlugin } from 'mineru-tracker-sdk';
const tracker = Tracker.getInstance();
await tracker.init({
productName: 'my-web-app',
serverUrl: 'https://api.example.com',
});
tracker.use(new ClickPlugin({ autoTrackSelectors: ['[data-track]'] }));
// 追踪自定义事件
tracker.track('button_click', {
button_name: 'submit',
module: 'contact-form',
});
// 用户登录后设置身份并发送关联事件
tracker.identify('user_123', {
$username: '张三',
$phone: '138****8888',
}).alias();
// 自定义日志
tracker.log('info', '用户完成了表单提交', { formId: 'contact' });
// 页面卸载前确保数据上报
window.addEventListener('beforeunload', () => {
tracker.flush();
});Electron 项目
主进程
import { mainTracker } from 'mineru-tracker-sdk/electron';
import { app } from 'electron';
app.whenReady().then(async () => {
await mainTracker.init({
productName: 'my-electron-app',
serverUrl: 'https://track.example.com/api/v1',
appVersion: app.getVersion(),
});
mainTracker.log('info', 'App started');
mainTracker.track('app_launch', { cold_start: true });
});渲染进程
import { tracker } from 'mineru-tracker-sdk';
import { ElectronRendererAdapter } from 'mineru-tracker-sdk/adapters';
await tracker.init({
productName: 'my-electron-app',
serverUrl: 'https://track.example.com/api/v1',
adapter: new ElectronRendererAdapter(),
});
tracker.track('page_loaded', { page: 'main' });Preload 脚本
import 'mineru-tracker-sdk/dist/esm/electron/preload';配置选项
| 配置项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | productName | string | 必填 | 产品名称 | | serverUrl | string | 必填 | 上报服务器地址 | | appVersion | string | - | 应用版本 | | batchSize | number | 10 | 批量上报事件数量阈值 | | flushInterval | number | 10000 | 批量上报时间间隔(毫秒) | | sendType | string | beacon | 上报方式:beacon/xhr/fetch | | sessionTimeout | number | 1800000 | 会话超时时间(毫秒),默认 30 分钟 | | autoTrackPageView | boolean | true | 自动采集 PV | | autoTrackPerformance | boolean | true | 自动采集性能 | | autoTrackError | boolean | true | 自动采集 JS 错误 | | autoTrackResource | boolean | true | 自动采集资源错误 | | trackingEnabled | boolean | true | 是否启用追踪 | | debug | boolean | false | 是否开启调试日志 |
API 参考
初始化
await tracker.init(config: TrackerConfig): Promise<void>事件追踪
// 追踪自定义事件
tracker.track(eventName: string, params?: Record<string, unknown>): void
// 追踪页面浏览
tracker.trackPageView(params?: Record<string, unknown>): void
// 追踪点击事件
tracker.trackClick(elementName: string, params?: Record<string, unknown>): void
// 追踪曝光事件
tracker.trackExposure(elementName: string, params?: Record<string, unknown>): void日志
tracker.log(level: 'debug' | 'info' | 'warn' | 'error', message: string, context?: Record<string, unknown>): void用户身份
// 设置用户身份(登录后调用),返回 this 支持链式调用
tracker.identify(userId: string, traits?: UserPortrait): this
// 发送用户标识关联事件(将 anonymousId 关联到 userId)
tracker.alias(): this
// 链式调用示例:登录时设置身份并发送关联事件
tracker.identify('user_123', { $username: '张三' }).alias();
// 获取当前匿名 ID
tracker.getAnonymousId(): string
// 设置用户画像
tracker.setUserPortrait(portrait: UserPortrait): void
// 退出登录(会重置 anonymousId)
tracker.logout(): void隐私控制
// 启用/禁用追踪
tracker.setTrackingEnabled(enabled: boolean): void
// 检查追踪状态
tracker.isTrackingEnabled(): boolean其他
// 立即上报队列中的数据
tracker.flush(): void
// 获取设备 ID
tracker.getDeviceId(): string
// 获取用户 ID
tracker.getUserId(): string | null
// 获取会话 ID
tracker.getSessionId(): string
// 销毁 SDK
tracker.destroy(): void插件
| 插件 | 说明 | 默认启用 | | --- | --- | --- | | PageViewPlugin | 自动采集 PV | 是 | | PerformancePlugin | 采集 Web Vitals | 是 | | ErrorPlugin | 捕获 JS 错误 | 是 | | ResourcePlugin | 捕获资源加载错误 | 是 | | ClickPlugin | 点击事件采集 | 否 | | ExposurePlugin | 曝光事件采集 | 否 | | LogPlugin | 结构化日志 | 否 |
ClickPlugin(点击采集插件)
配置选项
| 配置项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | autoTrackAll | boolean | false | 是否采集所有点击 | | autoTrackSelectors | string[] | ['button', 'a', '[data-track]'] | 自动采集的选择器 | | attributePrefix | string | data-track- | 属性前缀 | | throttleInterval | number | 300 | 点击防抖间隔(毫秒) |
推荐配置:只采集 data-track 标记的元素
import { ClickPlugin } from 'mineru-tracker-sdk';
const clickPlugin = new ClickPlugin({
autoTrackSelectors: ['[data-track]'],
});
tracker.use(clickPlugin);HTML 标记方式
基础用法:
<button data-track="add_cart">加入购物车</button>上报结果:
{ "$event_name": "click_add_cart", "params": { "track_id": "add_cart" } }携带自定义参数:
<button
data-track="buy_now"
data-track-sku="SKU001"
data-track-price="99.00"
>
立即购买
</button>上报结果:
{
"$event_name": "click_buy_now",
"params": {
"track_id": "buy_now",
"sku": "SKU001",
"price": "99.00"
}
}使用 JSON 格式传递复杂参数:
<button data-track='{"name": "submit", "form": "contact", "step": 3}'>
提交
</button>手动追踪点击
tracker.trackClick('custom_click', {
module: 'header',
component: 'nav',
});ExposurePlugin(曝光采集插件)
配置选项
| 配置项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | threshold | number | 0.5 | 可见比例阈值(50%可见) | | duration | number | 1000 | 最小曝光时长(毫秒) | | once | boolean | true | 是否只上报一次 |
使用示例
import { ExposurePlugin } from 'mineru-tracker-sdk';
const exposurePlugin = new ExposurePlugin({
threshold: 0.5,
duration: 1000,
});
tracker.use(exposurePlugin);
// 观察单个元素
const banner = document.querySelector('.hero-banner');
exposurePlugin.observe(banner, {
name: 'hero_banner',
module: 'homepage',
position: 'top',
});
// 观察多个元素(如商品列表)
const products = document.querySelectorAll('.product-card');
exposurePlugin.observeAll(
Array.from(products),
'product_exposure',
(el, index) => ({
productId: el.dataset.id,
position: index,
})
);
// 停止观察
exposurePlugin.unobserve(banner);LogPlugin(日志插件)
配置选项
| 配置项 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | minLevel | string | info | 最小日志级别 | | includeStack | boolean | true | 是否包含调用栈(仅 error) | | maxMessageLength | number | 1000 | 消息最大长度 | | maxContextDepth | number | 3 | 上下文对象最大深度 |
使用示例
import { LogPlugin } from 'mineru-tracker-sdk';
const logPlugin = new LogPlugin({
minLevel: 'info',
});
tracker.use(logPlugin);
// 不同级别的日志
logPlugin.debug('调试信息', { userId: '123' }); // 不上报(低于 minLevel)
logPlugin.info('用户操作', { action: 'click' });
logPlugin.warn('性能警告', { loadTime: 3000 });
logPlugin.error('请求失败', { url: '/api/data', status: 500 });
// 也可以通过 tracker 记录日志
tracker.log('info', '表单提交成功', { formId: 'contact' });自动采集插件
以下插件在初始化时根据配置自动启用:
PageViewPlugin
自动采集页面浏览,支持 SPA 路由变化检测。
PerformancePlugin
采集 Web Vitals 性能指标:FCP、LCP、FID、CLS、TTFB。
ErrorPlugin
捕获未处理的 JS 错误和 Promise rejection。
ResourcePlugin
捕获资源(图片、脚本、样式)加载失败。
数据格式
详细的数据格式说明请参阅:docs/DATA_FORMAT.md
包含:
- 事件结构(events)与事件类型
- 用户身份(identity)与关联流程
- 设备环境(environment)
- 用户画像(portrait)
- 字段命名规范($ 前缀说明)
- 完整的 JSON 示例
构建
# 安装依赖
pnpm install
# 开发模式
pnpm run dev
# 构建
pnpm run build
# 运行测试
pnpm run testLicense
MIT
