@yunlideyang/analytics-sdk
v0.1.4
Published
Lightweight, framework-agnostic browser analytics SDK for personal-website-analytics.
Maintainers
Readme
@yunlideyang/analytics-sdk
浏览器端 Analytics 采集 SDK。用于在前端应用中上报页面访问、自定义事件和 Core Web Vitals,并发送到配置的 HTTP 接收地址。
用途
- 采集浏览器页面访问和自定义事件。
- 自动补充并清洗页面上下文:路径、路由信息、UTM、语言、时区、设备类型、屏幕尺寸和视口尺寸。
- 基于
web-vitals包采集 LCP、INP、CLS。 - 处理匿名标识、内存队列、失败重试和页面退出时的 Beacon 发送。
默认行为
- 无框架绑定,不内置 React/Vue/Svelte 适配层。
- 默认遵守 Do Not Track。
- 默认清洗 query value 和 URL hash。
- 页面访问自动上报和路由变化自动上报都需要显式开启。
取舍
- 这是浏览器采集 SDK,不是看板或数据存储。
- Core Web Vitals 能力取决于浏览器支持和底层
web-vitals实现。 - 通用 SDK 无法自动推断框架路由 pattern;需要路由维度统计时由应用传入路由元数据。
- 浏览器端配置都是公开信息,不要在 SDK 配置中放入任何秘密。
安装
npm install @yunlideyang/analytics-sdk快速开始
import { initAnalytics } from '@yunlideyang/analytics-sdk';
const analytics = initAnalytics({
siteId: 'personal-website',
endpoint: '/api/analytics',
});
analytics.trackPageView();
analytics.track('resume_download', {
targetId: 'resume',
});大部分配置都有安全默认值。路由自动采集、保留 query value、Web Vitals 都按需再加。
endpoint 是基地址,SDK 会追加:
POST {endpoint}/visits
POST {endpoint}/events
POST {endpoint}/web-vitals传 /api/analytics,不要传 /api/analytics/events。
配置
| 配置 | 默认值 | 说明 |
| --- | --- | --- |
| siteId | 必填 | 统计接收地址接受的站点 ID。 |
| endpoint | 必填 | Analytics 接收基地址,不能包含 query/hash。 |
| autoTrackPageView | false | 初始化后发送一次页面访问。 |
| autoTrackRouteChanges | false | 监听 History API pathname 变化。HashRouter 不支持。 |
| sanitizeQueryValues | true | 清洗 visit.path 的 query value;接收端也需允许 query value 才会保存。hash 始终丢弃。 |
| getPageContext | 未设置 | 补充 routePattern、routeName、title、path 或白名单属性,适合 React Router。 |
| debug | false | 输出传输警告。 |
| respectDoNotTrack | true | 浏览器开启 DNT 时停止采集。 |
| requestTimeoutMs | 5000 | fetch 超时,范围 1-120000。 |
| webVitals | 未启用 | 启用 LCP、INP、CLS 采集。 |
| webVitals.writeKey | 启用时必填 | Web Vitals 的浏览器公开写入 key;从项目配置读取,不要硬编码示例值。 |
| webVitals.releaseVersion | "" | 通常不用填;需要按发布版本对比性能时,传项目已有版本号。 |
| webVitals.routeName | "" | 首次文档导航的路由名。 |
| webVitals.sendDelayMs | 3000 | Web Vitals 发送等待时间,范围 0-120000。 |
| webVitals.reportSoftNavigations | false | 浏览器支持时启用原生 SPA 软导航样本。 |
页面访问
analytics.trackPageView({
path: '/blog/hello',
routeName: 'blog-detail',
routePattern: '/blog/:slug',
title: document.title,
});每次页面访问会发送:
- 一条 visit 到
{endpoint}/visits - 一条
page_viewevent 到{endpoint}/events
page_view 自动包含白名单上下文:fullPath、previousPath、UTM、landing UTM、语言、时区、设备、屏幕和视口。
Query 口径:
- 默认只保留 path 和 query key
sanitizeQueryValues: false时 SDK 可在visit.path发送 query value- 接收端也必须允许 query value
- event
path和路径类 event properties 仍清洗
路由采集
History 路由:
const analytics = initAnalytics({
siteId: 'personal-website',
endpoint: '/api/analytics',
autoTrackPageView: true,
autoTrackRouteChanges: true,
getPageContext: () => ({
routePattern: currentRoutePattern,
routeName: currentRouteName,
}),
});SDK 监听 pushState、replaceState 和前进/后退,只在 pathname 变化时上报。query-only、hash-only 不产生页面访问。框架路由元数据通过 getPageContext 传入,例如 React Router 的 route pattern。
手动路由:
router.afterEach((to) => {
analytics.trackPageView({
path: to.path,
routeName: String(to.name ?? ''),
routePattern: String(to.matched?.at(-1)?.path ?? ''),
title: document.title,
});
});同一次导航只用自动或手动其中一种方式。
事件
analytics.track('article_share', {
articleId: 'article-123',
targetType: 'social-platform',
targetId: 'wechat',
});事件名必须以字母开头,可包含字母、数字、下划线、冒号和连字符,最长 64。
常用白名单属性:
- 页面:
title、routeName、routePattern、fullPath、previousPath、entryPath - 来源:
utmSource、utmMedium、utmCampaign、landingUtmSource、landingUtmMedium、landingUtmCampaign - 设备:
deviceType、language、timezone、screenWidth、screenHeight、viewportWidth、viewportHeight - 业务:
targetType、targetId、articleId、conversionType、conversionTarget - 性能/错误:
loadTimeMs、lcpMs、inpMs、cls、durationMs、errorType、errorCode、apiPath
不要发送密码、Token、Cookie、表单值、邮箱、手机号或其他个人数据。
Web Vitals
配置 webVitals 后,SDK 使用 web-vitals v6 采集 LCP、INP、CLS。
const analytics = initAnalytics({
siteId: 'personal-website',
endpoint: '/api/analytics',
webVitals: {
writeKey: import.meta.env.VITE_ANALYTICS_WEB_VITALS_WRITE_KEY,
},
});webVitals.sendDelayMs后发送最新快照。- 晚到的真实 LCP 会继续发送。
- 无交互页面不会伪造
INP: 0。 - 页面隐藏/离开时尽量使用 Beacon。
- 软导航样本需要浏览器支持,并设置
webVitals.reportSoftNavigations: true。
生命周期
await analytics.flush();
analytics.destroy();flush() 发送队列。destroy() 移除监听、取消定时器,并停止该客户端继续采集。
匿名标识按站点隔离,优先存入 localStorage/sessionStorage。发送失败不会影响页面业务。
