onerway-analytics
v1.1.0
Published
Onrway Analytics SDK
Readme
onerway-analytics
客户端埋点 SDK,支持双发:自建数据服务 + Google Tag Manager(GTM)。
安装
npm
npm install onerway-analyticsCDN / 本地文件
<script src="./dist/bundle/index.js"></script>
<!-- 全局变量:window.OnrwayAnalytics -->快速开始
import { createAnalytics } from 'onerway-analytics';
const analytics = createAnalytics({
appKey: 'your-app-key',
serverUrl: 'https://your-server.com/collect',
env: 'prod',
debug: true,
});上报模式
双发(自建服务 + GTM)
const analytics = createAnalytics({
appKey: 'your-app-key',
serverUrl: 'https://your-server.com/collect',
env: 'prod',
gtm: {
containerId: 'GTM-XXXXXXX',
enabled: true,
},
});只发自建服务
不配置 gtm,或设置 gtm.enabled: false:
const analytics = createAnalytics({
appKey: 'your-app-key',
serverUrl: 'https://your-server.com/collect',
env: 'prod',
});只发 GTM
设置 disableServer: true,serverUrl 可留空,所有事件只推入 dataLayer:
const analytics = createAnalytics({
appKey: 'your-app-key',
serverUrl: '',
disableServer: true,
gtm: {
containerId: 'GTM-XXXXXXX',
enabled: true,
},
});
disableServer: true时,analytics.flush()和重试机制均不生效。
API
事件埋点
// 普通事件(进入缓冲区,定时批量发送)
analytics.track('button_click', { target_id: 'buy_btn', scene: 'product' });
// 关键事件(立即发送,不等缓冲区)
analytics.track('payment_success', { order_id: '456' }, { keyEvent: true });用户标识
// 设置用户 ID 与属性
analytics.identify('user-123', { plan: 'pro', email: '[email protected]' });
// 获取用户信息
const profile = analytics.getUserProfile();
// { userId: 'user-123', anonymousId: 'uuid...', attributes: { plan: 'pro' } }
// 重置用户身份
analytics.reset();GTM 编程式控制
// 直接推送自定义数据到 dataLayer
analytics.gtm.push({ event: 'custom_event', key: 'value' });
// 推送带事件名的数据
analytics.gtm.track('checkout_start', { step: 1 });
// 设置用户 ID
analytics.gtm.setUserId('user-123');
// 设置用户属性
analytics.gtm.setUserProperties({ plan: 'pro' });其他方法
analytics.flush(); // 立即刷新缓冲区
analytics.getSessionId(); // 获取当前 session ID
analytics.getClientId(); // 获取匿名客户端 ID
analytics.setClientType('MINI_PROGRAM'); // 设置客户端类型
analytics.setMerchantLanguage('zh'); // 设置商户语言
analytics.destroy(); // 销毁实例,移除事件监听(SPA 路由切换时使用)自动埋点
默认开启,通过 data-track-* 属性声明式配置:
<!-- 自定义事件名 -->
<button data-track-name="subscribe_click">订阅</button>
<!-- 带 JSON 属性 -->
<button data-track-name="buy_now"
data-track-properties='{"product":"shoes","price":299}'>
立即购买
</button>
<!-- 任意 data-track-* 前缀自动成为属性键 -->
<a data-track-name="share"
data-track-platform="wechat"
data-track-position="top">分享</a>
<!-- 忽略该元素 -->
<div data-track-ignore>不追踪</div>限定追踪范围:
createAnalytics({
serverUrl: '...',
autoTrackSelector: '#app', // 只追踪 #app 内的点击
});关闭自动埋点:
createAnalytics({ serverUrl: '...', autoTrack: false });采样控制
通过 sampleRate 控制上报比例,降低高流量场景的服务器压力。决策在每次页面加载时独立进行——命中采样的会话全量上报,未命中的会话全部丢弃(包括 GTM)。
// 只上报约 10% 的页面会话
const analytics = createAnalytics({
appKey: 'your-app-key',
serverUrl: 'https://your-server.com/collect',
sampleRate: 0.1,
});sampleRate: 1(默认)— 全量上报sampleRate: 0— 全部丢弃,可用于临时关闭上报sampleRate: 0.1— 约 10% 的页面会话上报,每次刷新重新决策
采样决策作用于整个会话:同一次页面加载内,所有
track()要么全部上报,要么全部丢弃,不会出现部分事件缺失的碎片数据。
配置项
| 配置 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| appKey | string | — | 应用标识 |
| serverUrl | string | — | 数据接收端点(disableServer: true 时可留空) |
| apiKey | string | — | API Key(不填则按 env 自动解析) |
| env | string | — | 环境:beta | test | uat | prod |
| debug | boolean | false | 开启控制台日志 |
| autoTrack | boolean | true | 自动点击追踪 |
| autoTrackPageView | boolean | true | 初始化时自动发送 page_view;设为 false 可手动控制 |
| autoTrackSelector | string | — | 自动埋点的 CSS 选择器范围 |
| sampleRate | number | 1 | 采样率 0~1;每次页面加载独立掷骰,0.1 表示约 10% 的页面会话上报,0 全不报,1 全量报 |
| system | string | — | 系统标识,写入每条事件 |
| domain | string | — | 业务域标识,写入每条事件 |
| keyEvents | string[] | — | 关键事件名单,命中的事件立即发送 |
| bufferFlushInterval | number | 5000 | 缓冲区定时刷新间隔(ms) |
| bufferMaxSize | number | 25 | 缓冲区达到此数量立即刷新 |
| maxRetryCount | number | 3 | 发送失败最大重试次数(指数退避) |
| sessionTimeout | number | 1800000 | 会话超时(ms),默认 30 分钟 |
| performance.enabled | boolean | true | Core Web Vitals 采集开关 |
| gtm.enabled | boolean | — | GTM 双发开关 |
| gtm.containerId | string | — | GTM 容器 ID(GTM-XXXXXXX 格式) |
| gtm.dataLayerName | string | 'dataLayer' | 自定义 dataLayer 变量名 |
| disableServer | boolean | false | 关闭自建服务上报,只推 GTM |
上报数据结构
自建服务(批量 POST)
{
"client_id": "uuid",
"user_id": "user-123",
"session_id": "uuid",
"user_properties": { "plan": "pro" },
"context": {
"sdk_version": "1.0.0",
"app_key": "your-app-key",
"browser": { "name": "Chrome", "version": "135" },
"operating_system": { "name": "Windows", "version": "10" },
"device_type": "desktop",
"country": "CN",
"language": "zh-CN",
"timezone": "Asia/Shanghai"
},
"marketing": {
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"landing_page": "https://example.com/?utm_source=google",
"referrer_url": "https://google.com"
},
"events": [
{
"event_id": "uuid",
"event_name": "button_click",
"timestamp": 1700000000000,
"key_event": false,
"batch_event_index": 0,
"batch_ordering_id": "1700000000000-1",
"batch_page_id": "abc-xyz",
"event_properties": {
"system": "web",
"domain": "payment",
"scene": "product",
"action": "click",
"target_type": "button",
"target_id": "buy_btn",
"page_url": "https://example.com/product"
}
}
]
}GTM dataLayer
每个 track() 调用推入一条:
{
"event": "button_click",
"action": "click",
"target_id": "buy_btn",
"session_id": "uuid",
"page_url": "https://example.com/product",
"referrer": ""
}identify() 推入:
{ "userId": "user-123" }
{ "plan": "pro", "email": "[email protected]" }采集能力
| 采集项 | 说明 |
|---|---|
| 点击事件 | 自动埋点(data-track-*)+ 手动 analytics.track() |
| 页面浏览 | 初始化时自动发送 page_view(可通过 autoTrackPageView: false 关闭) |
| JS 错误 | 全局 window.error / unhandledrejection 自动捕获 |
| Core Web Vitals | LCP / FCP / CLS / INP / TTFB(web_vital 事件) |
| 设备上下文 | 浏览器、OS、屏幕分辨率、语言、时区、设备类型 |
| 营销归因 | UTM 参数持久化、落地页、来源 URL(SPA 路由切换后仍保留) |
可靠性机制
- 缓冲区 + 批量发送:事件先入缓冲区,满
bufferMaxSize或到bufferFlushInterval后批量发送 - 指数退避重试:发送失败最多重试
maxRetryCount次,间隔 1s / 2s / 4s… - 本地持久化:超出重试次数的事件写入 localStorage,下次页面加载时自动恢复补发(24 小时内有效)
- 页面关闭兜底:
beforeunload/pagehide时用sendBeacon发送缓冲区剩余事件 - 采样控制:
sampleRate在客户端决定是否上报,降低高流量场景的服务器压力
SPA 使用建议
路由切换时销毁旧实例,重建新实例以正确发送新页面的 page_view:
// 路由离开时
analytics.destroy();
// 路由进入时
analytics = createAnalytics({ ... });
// 或手动控制
analytics = createAnalytics({ ..., autoTrackPageView: false });
analytics.track('page_view', { page_url: location.href });