react-track-hooks:一个轻量可靠的 React 埋点 Hooks 库
在前端应用中,埋点往往是产品分析、用户行为洞察和业务增长的基础能力。但在实际开发里,埋点代码很容易散落在点击事件、页面生命周期、曝光监听、表单提交等各种位置,既影响业务代码可读性,也增加了漏报、重复上报和失败丢失的风险。
react-track-hooks 正是为了解决这个问题而设计的。它是一个面向 React 项目的轻量埋点 Hooks 库,将点击、曝光、页面停留、首次渲染和自定义事件等常见场景封装成可复用 Hook,并内置批量上报、失败缓存和自动重试机制,让业务组件可以用更低成本接入稳定的埋点能力。
项目定位
react-track-hooks 的定位不是一个复杂的数据分析平台,而是一个专注于前端埋点采集层的 SDK。它不关心后端如何存储和分析数据,而是聚焦在浏览器侧如何更可靠、更优雅地采集行为事件,并把事件发送到指定接口。
这个定位让它非常适合 React 和 Next.js 项目使用。开发者只需要在项目入口配置一次全局上报地址和策略,然后在组件中使用对应 Hook,就可以完成常见埋点场景的接入。
核心能力
react-track-hooks 提供了几类最常见的埋点能力。
第一类是点击埋点。useTrackClick 会返回一个点击处理函数,业务组件可以直接绑定到按钮、卡片或任意可点击元素上。触发时,它会自动补充点击坐标,并携带自定义业务参数一起上报。
第二类是曝光埋点。useTrackExposure 基于浏览器的 IntersectionObserver 实现,返回一个 DOM ref。组件只需要把 ref 绑定到目标元素,元素达到指定可见比例后就会触发曝光事件。它支持配置曝光阈值,也支持只曝光一次,适合卡片、广告位、推荐内容等场景。
第三类是页面停留时长埋点。useTrackPageStay 会监听页面显隐、用户活跃行为和组件卸载,统计真实有效的活跃停留时间。它可以过滤过短停留,也能限制最长单次时长,避免异常数据污染分析结果。
第四类是组件首次渲染埋点。useTrackFirstRender 会在组件首次挂载后触发一次事件,适合记录关键组件是否被加载、首屏模块是否出现等场景。
第五类是自定义埋点。useTrackCustom 返回一个手动触发方法,适合表单提交、业务状态变化、流程节点完成等无法直接归类为点击或曝光的事件。
使用方式
项目入口处可以通过 useTrackInit 或手动调用配置函数完成初始化。全局配置包括单条上报地址、批量上报地址、是否启用埋点、是否启用批量上报、失败重试策略、批量队列策略、曝光策略和页面停留策略。
示例配置如下:
import { useTrackInit } from 'react-track-hooks';
function TrackProvider() {
useTrackInit({
trackUrl: '/api/track',
batchTrackUrl: '/api/track/batch',
enable: true,
enableBatch: true,
retryConfig: {
maxRetryTimes: 3,
initialDelay: 1000,
delayMultiplier: 2,
},
batchConfig: {
batchSize: 10,
batchInterval: 5000,
},
exposureConfig: {
exposureOnce: true,
exposureThreshold: 0.5,
},
pageStayConfig: {
timeout: 30 * 60 * 1000,
minDuration: 2000,
maxDuration: 60 * 60 * 1000,
checkInterval: 1000,
},
});
return null;
}
在业务组件中,点击埋点可以这样使用:
import { useTrackClick } from 'react-track-hooks';
function BuyButton() {
const handleClick = useTrackClick('buy_button_click', {
page: 'product_detail',
module: 'footer_bar',
});
return <button onClick={handleClick}>立即购买</button>;
}
曝光埋点则更适合列表卡片或推荐模块:
import { useTrackExposure } from 'react-track-hooks';
function RecommendCard() {
const ref = useTrackExposure<HTMLDivElement>('recommend_card_exposure', {
cardId: 'card_001',
});
return <div ref={ref}>推荐内容</div>;
}
这种 API 设计把埋点逻辑从业务组件中抽离出来,业务代码只需要表达“这里要记录什么事件”,而不用关心发送、批量、失败重试等底层细节。
架构设计
react-track-hooks 的源码结构非常清晰,核心位于 src/track 目录。
项目目录可以概括为:
react-track-hooks
├── src
│ ├── index.ts # 包入口,统一导出类型、配置函数、核心函数和 Hooks
│ ├── types.ts # TrackType、TrackParams、TrackConfig 等核心类型
│ ├── utils.ts # 浏览器环境判断、localStorage 安全写入、事件 ID 生成
│ ├── track
│ │ ├── config.ts # 全局配置单例和配置合并逻辑
│ │ ├── core
│ │ │ ├── sendTrack.ts # 单条埋点发送入口,决定单发或进入批量队列
│ │ │ ├── sendBatchTrack.ts # 批量队列、定时上报、页面隐藏上报
│ │ │ └── retryTrack.ts # 失败缓存、指数退避和重试逻辑
│ │ ├── hooks
│ │ │ ├── useTrack.ts # 基础埋点 Hook,所有场景 Hook 的统一触发器
│ │ │ ├── useTrackClick.ts # 点击埋点
│ │ │ ├── useTrackExposure.ts # 曝光埋点
│ │ │ ├── useTrackPageStay.ts # 页面停留时长埋点
│ │ │ ├── useTrackFirstRender.ts # 首次渲染埋点
│ │ │ ├── useTrackCustom.ts # 自定义埋点
│ │ │ └── useTrackInit.ts # 初始化全局配置、批量上报和重试监听
│ │ └── listeners
│ │ └── useTrackRetryListener.ts # 全局失败重试监听器
│ └── __tests__ # Vitest 测试用例和浏览器 API mock
├── dist # Rollup 构建后的 CJS、ESM 和类型声明产物
├── rollup.config.js # 打包配置
├── tsconfig.json # TypeScript 配置
└── package.json # npm 包信息、脚本和 peer dependencies
这个目录结构体现了项目的分层思路:hooks 面向业务场景,core 负责上报和可靠性,config 管理全局策略,listeners 负责浏览器生命周期里的补偿重试,types 和 utils 则提供跨模块复用的基础能力。
对外入口是 src/index.ts,它统一导出类型、配置函数、核心函数和所有 Hooks。类型定义集中在 src/types.ts,包括 TrackType、TrackParams、TrackGlobalConfig、TrackConfig 和 FailedTrackParams。
配置层位于 src/track/config.ts。项目使用模块级单例维护全局配置,提供 setTrackGlobalConfig 和 getTrackGlobalConfig。全局默认配置会和用户传入配置合并,嵌套配置也会保留未覆盖字段,避免局部配置导致默认策略丢失。
基础 Hook 是 useTrack。所有业务 Hook 最终都会调用它。useTrack 接收统一的埋点参数和配置,返回 triggerTrack 方法。触发时,它会合并定义时参数和运行时额外参数,并把最终事件交给 sendTrack。
发送层由 sendTrack.ts 负责。它会先判断当前是否处于浏览器环境,再检查事件名和启用状态。如果开启批量模式,事件会进入内存队列;如果关闭批量模式,则直接通过 fetch 发送到 trackUrl。
批量上报由 sendBatchTrack.ts 管理。它维护一个内存队列 BATCH_TRACK_QUEUE,并通过队列长度和定时器两种方式触发上报。当页面进入隐藏状态时,它也会尝试立即处理队列,减少页面关闭导致的数据丢失。
失败重试由 retryTrack.ts 负责。发送失败的事件会保存到 localStorage.failedTracks 中,并记录重试时间和重试次数。后续重试使用指数退避策略,避免网络异常时持续高频请求。重试支持单条模式,也支持批量模式。
全局重试监听由 useTrackRetryListener 注册。它会在首屏渲染后延迟重试一次,在页面从隐藏变为可见时重试,也会利用 requestIdleCallback 在浏览器空闲时周期性检查失败队列。
整体调用链可以概括为:
业务组件
-> useTrackClick / useTrackExposure / useTrackPageStay / useTrackCustom
-> useTrack
-> sendTrack
-> 单条 fetch 或进入批量队列
-> 失败写入 localStorage
-> useTrackRetryListener 触发 retryFailedTracks
可靠性设计
埋点系统最重要的问题之一是可靠性。用户行为一旦发生,就很难重新采集,因此 SDK 需要尽量降低丢失概率。
react-track-hooks 在这方面做了几层设计。
首先是批量上报。批量模式可以减少网络请求数量,降低高频事件对页面性能和后端接口的压力。队列达到指定大小时会立即上报,同时也有定时器兜底,避免事件长时间滞留在内存中。
其次是页面隐藏处理。当页面关闭、切换标签页或进入后台时,库会监听 visibilitychange,在页面变为隐藏时尝试处理批量队列。单条发送和批量发送都使用了 keepalive,这有助于在页面卸载阶段完成请求。
第三是失败缓存。请求失败后,事件不会直接丢弃,而是写入 localStorage。为了避免存储无限增长,工具函数会控制数据体积,并保留较新的失败事件。
第四是指数退避重试。失败事件不会被立即无限重试,而是根据 initialDelay 和 delayMultiplier 计算下一次可重试时间,并受 maxRetryTimes 限制。这种机制在弱网或服务端短暂异常时更稳健。
第五是多触发点重试。重试不仅发生在下一次成功上报后,还会在首屏延迟、页面重新可见、浏览器空闲时间等时机触发,提高失败事件被补偿上报的概率。
对 React 项目的价值
对业务开发者来说,react-track-hooks 最大的价值是把埋点从“到处写 fetch”变成了“按场景使用 Hook”。这让代码更一致,也更容易维护。
例如,点击事件统一使用 useTrackClick,曝光事件统一使用 useTrackExposure,页面停留统一使用 useTrackPageStay。团队可以围绕这些 Hook 形成统一约定,而不是每个组件各写一套埋点实现。
对基础设施维护者来说,这个库把发送、批量、重试、失败缓存和公共参数补充集中在核心层。一旦上报协议、接口地址或重试策略变化,只需要调整 SDK 或全局配置,而不需要修改大量业务组件。
对 Next.js 项目来说,库内部通过 isClient 判断浏览器环境,避免在服务端渲染阶段访问 window、document 或 localStorage。这让它更容易放进 Next.js 的客户端组件或全局 Provider 中使用。
工程化与发布
react-track-hooks 使用 TypeScript 编写,并通过 Rollup 构建。构建产物同时提供 CommonJS 和 ES Module 格式,对应 dist/index.cjs.js 和 dist/index.esm.js,类型声明则通过 dist/index.d.ts 暴露。
项目将 react 和 react-dom 声明为 peer dependencies,不会打包进库中,避免使用方项目出现重复 React 实例。
测试方面,项目使用 Vitest 和 jsdom。测试环境中 mock 了 fetch、IntersectionObserver、requestIdleCallback 和 cancelIdleCallback,从而可以覆盖点击、曝光、页面停留、发送失败和重试等核心路径。
发布前脚本会依次执行类型检查、测试和构建:
npm run typecheck
npm run test
npm run build
这套流程保证了库在发布前至少经过类型、行为和产物三方面验证。
适合的使用场景
react-track-hooks 适合需要快速接入前端埋点的 React 项目,尤其适合以下场景:
- 需要统一管理点击、曝光、页面停留等常见行为事件。
- 希望减少业务组件中的埋点样板代码。
- 希望支持批量上报,降低网络请求压力。
- 希望失败事件能缓存并自动重试,减少数据丢失。
- 项目使用 React 或 Next.js,并希望以 Hook 的方式组织埋点逻辑。
它不试图替代完整的数据分析平台,也不绑定特定后端协议。只要后端提供单条或批量接收接口,前端就可以通过配置接入。
总结
react-track-hooks 是一个小而完整的前端埋点 SDK。它把 React Hook 的易用性和埋点系统需要的可靠性结合起来,既提供了面向业务场景的简洁 API,也在底层处理了批量上报、失败缓存、指数退避和自动重试。
如果用一句话概括这个项目:react-track-hooks 让 React 项目的埋点从分散、重复、易丢失的手写逻辑,变成了一套统一、可配置、可重试的 Hook 化采集方案。