react-track-hooks 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 liujingmin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # react-track-hooks
2
+
3
+ React 埋点 Hooks 库,支持点击埋点、曝光埋点、页面停留时长埋点,内置失败重试机制。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install react-track-hooks --save
9
+ # 或
10
+ yarn add react-track-hooks
@@ -0,0 +1,274 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/types.ts
6
+ exports.TrackType = void 0;
7
+ (function (TrackType) {
8
+ TrackType["CLICK"] = "click";
9
+ TrackType["EXPOSURE"] = "exposure";
10
+ TrackType["PAGE_STAY"] = "page_stay";
11
+ TrackType["CUSTOM"] = "custom";
12
+ })(exports.TrackType || (exports.TrackType = {}));
13
+
14
+ // src/trackHooks.ts
15
+ // 全局配置(默认值),并提供修改全局配置的方法
16
+ let GLOBAL_TRACK_CONFIG = {
17
+ trackUrl: '/api/track', // 默认上报地址
18
+ enable: true,
19
+ retryConfig: {
20
+ maxRetryTimes: 3,
21
+ initialDelay: 1000,
22
+ delayMultiplier: 2
23
+ }
24
+ };
25
+ /**
26
+ * 设置全局埋点配置(项目初始化时调用一次即可)
27
+ * @param config 全局配置
28
+ */
29
+ const setTrackGlobalConfig = (config) => {
30
+ GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };
31
+ };
32
+ // 2. 调整默认配置,合并全局配置
33
+ const getMergedDefaultConfig = () => ({
34
+ exposureOnce: true,
35
+ exposureThreshold: 0.5,
36
+ ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)
37
+ });
38
+ // ---------------------- 埋点发送 & 重试核心逻辑 ----------------------
39
+ const getFailedTracks = () => {
40
+ try {
41
+ return JSON.parse(localStorage.getItem('failedTracks') || '[]');
42
+ }
43
+ catch (error) {
44
+ console.error('读取失败埋点数据失败:', error);
45
+ return [];
46
+ }
47
+ };
48
+ const saveFailedTracks = (tracks) => {
49
+ try {
50
+ localStorage.setItem('failedTracks', JSON.stringify(tracks));
51
+ }
52
+ catch (error) {
53
+ console.error('保存失败埋点数据失败:', error);
54
+ }
55
+ };
56
+ /**
57
+ * 重试失败的埋点(使用全局配置的 trackUrl)
58
+ */
59
+ const retryFailedTracks = async (force = false) => {
60
+ const failedTracks = getFailedTracks();
61
+ if (failedTracks.length === 0)
62
+ return;
63
+ const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;
64
+ const retryableTracks = failedTracks.filter(track => {
65
+ const currentRetryCount = track.retryCount || 0;
66
+ const timeCondition = force || Date.now() - track.retryTime >= retryConfig.initialDelay * Math.pow(retryConfig.delayMultiplier, currentRetryCount);
67
+ return currentRetryCount < retryConfig.maxRetryTimes && timeCondition;
68
+ });
69
+ if (retryableTracks.length === 0)
70
+ return;
71
+ for (const track of retryableTracks) {
72
+ try {
73
+ // 使用全局配置的 trackUrl
74
+ await fetch(trackUrl, {
75
+ method: 'POST',
76
+ headers: { 'Content-Type': 'application/json' },
77
+ body: JSON.stringify({
78
+ ...track,
79
+ timestamp: Date.now(),
80
+ userAgent: navigator.userAgent,
81
+ url: window.location.href,
82
+ referrer: document.referrer,
83
+ retryCount: (track.retryCount || 0) + 1
84
+ })
85
+ });
86
+ console.log('埋点重试成功:', track.eventName);
87
+ const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);
88
+ if (index > -1)
89
+ failedTracks.splice(index, 1);
90
+ }
91
+ catch (error) {
92
+ console.error('埋点重试失败:', track.eventName, error);
93
+ const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);
94
+ if (index > -1) {
95
+ failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;
96
+ failedTracks[index].retryTime = Date.now();
97
+ }
98
+ }
99
+ }
100
+ saveFailedTracks(failedTracks);
101
+ };
102
+ /**
103
+ * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)
104
+ * @param params 埋点参数
105
+ * @param config 单个 Hook 的配置(可覆盖 trackUrl)
106
+ */
107
+ const sendTrack = async (params, config) => {
108
+ var _a;
109
+ if (!params.eventName) {
110
+ console.warn('埋点缺少必要参数:eventName');
111
+ return;
112
+ }
113
+ // 优先级:单个 Hook 配置 > 全局配置
114
+ const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;
115
+ const isEnable = (_a = config.enable) !== null && _a !== void 0 ? _a : GLOBAL_TRACK_CONFIG.enable;
116
+ if (!isEnable)
117
+ return;
118
+ try {
119
+ // 使用最终确定的 trackUrl 发送请求
120
+ await fetch(finalTrackUrl, {
121
+ method: 'POST',
122
+ headers: { 'Content-Type': 'application/json' },
123
+ body: JSON.stringify({
124
+ ...params,
125
+ timestamp: Date.now(),
126
+ userAgent: navigator.userAgent,
127
+ url: window.location.href,
128
+ referrer: document.referrer
129
+ })
130
+ });
131
+ console.log('埋点上报成功:', params);
132
+ if (window.requestIdleCallback) {
133
+ window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });
134
+ }
135
+ else {
136
+ setTimeout(() => retryFailedTracks(), 1000);
137
+ }
138
+ }
139
+ catch (error) {
140
+ console.error('埋点上报失败:', error);
141
+ const failedTracks = getFailedTracks();
142
+ failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });
143
+ saveFailedTracks(failedTracks);
144
+ }
145
+ };
146
+ // ---------------------- 核心 Hooks 实现 ----------------------
147
+ const useTrack = (params, config = {}) => {
148
+ // 合并默认配置(含全局配置)和单个 Hook 配置
149
+ const mergedConfig = { ...getMergedDefaultConfig(), ...config };
150
+ const trackRef = react.useRef(params);
151
+ react.useEffect(() => {
152
+ trackRef.current = params;
153
+ }, [params]);
154
+ const triggerTrack = react.useCallback((customParams = {}) => {
155
+ const finalParams = {
156
+ ...trackRef.current,
157
+ ...customParams
158
+ };
159
+ // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl
160
+ sendTrack(finalParams, mergedConfig);
161
+ }, [mergedConfig]);
162
+ return { triggerTrack };
163
+ };
164
+ // 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装
165
+ const useTrackClick = (eventName, customParams = {}, config = {}) => {
166
+ const { triggerTrack } = useTrack({ eventName, type: exports.TrackType.CLICK, ...customParams }, config);
167
+ const handleClick = react.useCallback((e, extraParams = {}) => {
168
+ const clickParams = { clientX: (e === null || e === void 0 ? void 0 : e.clientX) || 0, clientY: (e === null || e === void 0 ? void 0 : e.clientY) || 0, ...extraParams };
169
+ triggerTrack(clickParams);
170
+ }, [triggerTrack]);
171
+ return handleClick;
172
+ };
173
+ const useTrackExposure = (eventName, customParams = {}, config = {}) => {
174
+ const mergedConfig = { ...getMergedDefaultConfig(), ...config };
175
+ const { triggerTrack } = useTrack({ eventName, type: exports.TrackType.EXPOSURE, ...customParams }, mergedConfig);
176
+ const targetRef = react.useRef(null);
177
+ const hasReported = react.useRef(false);
178
+ react.useEffect(() => {
179
+ if (!mergedConfig.enable)
180
+ return;
181
+ const observer = new IntersectionObserver((entries) => {
182
+ entries.forEach((entry) => {
183
+ if (entry.isIntersecting && !hasReported.current) {
184
+ const exposureParams = {
185
+ intersectionRatio: entry.intersectionRatio,
186
+ boundingClientRect: entry.boundingClientRect,
187
+ exposureTime: Date.now()
188
+ };
189
+ triggerTrack(exposureParams);
190
+ if (mergedConfig.exposureOnce) {
191
+ hasReported.current = true;
192
+ observer.unobserve(entry.target);
193
+ }
194
+ }
195
+ });
196
+ }, { threshold: mergedConfig.exposureThreshold });
197
+ const target = targetRef.current;
198
+ if (target)
199
+ observer.observe(target);
200
+ return () => {
201
+ if (target)
202
+ observer.unobserve(target);
203
+ observer.disconnect();
204
+ };
205
+ }, [mergedConfig, triggerTrack]);
206
+ return targetRef;
207
+ };
208
+ const useTrackPageStay = (eventName, customParams = {}, config = {}) => {
209
+ const { triggerTrack } = useTrack({ eventName, type: exports.TrackType.PAGE_STAY, ...customParams }, config);
210
+ const startTime = react.useRef(Date.now());
211
+ react.useEffect(() => {
212
+ const handleVisibilityChange = () => {
213
+ if (document.hidden) {
214
+ const stayTime = Date.now() - startTime.current;
215
+ triggerTrack({ stayTime });
216
+ }
217
+ else {
218
+ startTime.current = Date.now();
219
+ }
220
+ };
221
+ const handleBeforeUnload = () => {
222
+ const stayTime = Date.now() - startTime.current;
223
+ triggerTrack({ stayTime });
224
+ };
225
+ document.addEventListener('visibilitychange', handleVisibilityChange);
226
+ window.addEventListener('beforeunload', handleBeforeUnload);
227
+ return () => {
228
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
229
+ window.removeEventListener('beforeunload', handleBeforeUnload);
230
+ };
231
+ }, [triggerTrack]);
232
+ };
233
+ const useTrackCustom = (eventName, customParams = {}, config = {}) => {
234
+ const { triggerTrack } = useTrack({ eventName, type: exports.TrackType.CUSTOM, ...customParams }, config);
235
+ return triggerTrack;
236
+ };
237
+ const useTrackRetryListener = () => {
238
+ react.useEffect(() => {
239
+ const initTimer = setTimeout(() => retryFailedTracks(), 3000);
240
+ const handleVisibilityChange = () => {
241
+ if (!document.hidden) {
242
+ retryFailedTracks();
243
+ }
244
+ };
245
+ document.addEventListener('visibilitychange', handleVisibilityChange);
246
+ let idleCallbackId = null;
247
+ const checkIdleRetry = () => {
248
+ retryFailedTracks();
249
+ idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });
250
+ };
251
+ if (window.requestIdleCallback) {
252
+ idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });
253
+ }
254
+ return () => {
255
+ clearTimeout(initTimer);
256
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
257
+ if (idleCallbackId !== null && window.cancelIdleCallback) {
258
+ window.cancelIdleCallback(idleCallbackId);
259
+ }
260
+ };
261
+ }, []);
262
+ };
263
+
264
+ exports.getFailedTracks = getFailedTracks;
265
+ exports.retryFailedTracks = retryFailedTracks;
266
+ exports.saveFailedTracks = saveFailedTracks;
267
+ exports.setTrackGlobalConfig = setTrackGlobalConfig;
268
+ exports.useTrack = useTrack;
269
+ exports.useTrackClick = useTrackClick;
270
+ exports.useTrackCustom = useTrackCustom;
271
+ exports.useTrackExposure = useTrackExposure;
272
+ exports.useTrackPageStay = useTrackPageStay;
273
+ exports.useTrackRetryListener = useTrackRetryListener;
274
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\n// 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<HTMLElement>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":["TrackType","useRef","useEffect","useCallback"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import * as react from 'react';
2
+
3
+ declare enum TrackType {
4
+ CLICK = "click",
5
+ EXPOSURE = "exposure",
6
+ PAGE_STAY = "page_stay",
7
+ CUSTOM = "custom"
8
+ }
9
+ interface TrackParams {
10
+ eventName: string;
11
+ type: TrackType;
12
+ [key: string]: any;
13
+ }
14
+ interface TrackGlobalConfig {
15
+ trackUrl: string;
16
+ enable?: boolean;
17
+ retryConfig?: {
18
+ maxRetryTimes: number;
19
+ initialDelay: number;
20
+ delayMultiplier: number;
21
+ };
22
+ }
23
+ interface TrackConfig extends Partial<TrackGlobalConfig> {
24
+ exposureOnce?: boolean;
25
+ exposureThreshold?: number;
26
+ }
27
+ interface FailedTrackParams extends TrackParams {
28
+ retryTime: number;
29
+ retryCount?: number;
30
+ }
31
+
32
+ /**
33
+ * 设置全局埋点配置(项目初始化时调用一次即可)
34
+ * @param config 全局配置
35
+ */
36
+ declare const setTrackGlobalConfig: (config: Partial<TrackGlobalConfig>) => void;
37
+ declare const getFailedTracks: () => FailedTrackParams[];
38
+ declare const saveFailedTracks: (tracks: FailedTrackParams[]) => void;
39
+ /**
40
+ * 重试失败的埋点(使用全局配置的 trackUrl)
41
+ */
42
+ declare const retryFailedTracks: (force?: boolean) => Promise<void>;
43
+ declare const useTrack: (params: TrackParams, config?: TrackConfig) => {
44
+ triggerTrack: (customParams?: {}) => void;
45
+ };
46
+ declare const useTrackClick: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (e?: React.MouseEvent, extraParams?: {}) => void;
47
+ declare const useTrackExposure: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => react.RefObject<HTMLElement>;
48
+ declare const useTrackPageStay: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => void;
49
+ declare const useTrackCustom: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (customParams?: {}) => void;
50
+ declare const useTrackRetryListener: () => void;
51
+
52
+ export { TrackType, getFailedTracks, retryFailedTracks, saveFailedTracks, setTrackGlobalConfig, useTrack, useTrackClick, useTrackCustom, useTrackExposure, useTrackPageStay, useTrackRetryListener };
53
+ export type { FailedTrackParams, TrackConfig, TrackGlobalConfig, TrackParams };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG1G,OAAO,EACH,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACxB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,263 @@
1
+ import { useRef, useEffect, useCallback } from 'react';
2
+
3
+ // src/types.ts
4
+ var TrackType;
5
+ (function (TrackType) {
6
+ TrackType["CLICK"] = "click";
7
+ TrackType["EXPOSURE"] = "exposure";
8
+ TrackType["PAGE_STAY"] = "page_stay";
9
+ TrackType["CUSTOM"] = "custom";
10
+ })(TrackType || (TrackType = {}));
11
+
12
+ // src/trackHooks.ts
13
+ // 全局配置(默认值),并提供修改全局配置的方法
14
+ let GLOBAL_TRACK_CONFIG = {
15
+ trackUrl: '/api/track', // 默认上报地址
16
+ enable: true,
17
+ retryConfig: {
18
+ maxRetryTimes: 3,
19
+ initialDelay: 1000,
20
+ delayMultiplier: 2
21
+ }
22
+ };
23
+ /**
24
+ * 设置全局埋点配置(项目初始化时调用一次即可)
25
+ * @param config 全局配置
26
+ */
27
+ const setTrackGlobalConfig = (config) => {
28
+ GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };
29
+ };
30
+ // 2. 调整默认配置,合并全局配置
31
+ const getMergedDefaultConfig = () => ({
32
+ exposureOnce: true,
33
+ exposureThreshold: 0.5,
34
+ ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)
35
+ });
36
+ // ---------------------- 埋点发送 & 重试核心逻辑 ----------------------
37
+ const getFailedTracks = () => {
38
+ try {
39
+ return JSON.parse(localStorage.getItem('failedTracks') || '[]');
40
+ }
41
+ catch (error) {
42
+ console.error('读取失败埋点数据失败:', error);
43
+ return [];
44
+ }
45
+ };
46
+ const saveFailedTracks = (tracks) => {
47
+ try {
48
+ localStorage.setItem('failedTracks', JSON.stringify(tracks));
49
+ }
50
+ catch (error) {
51
+ console.error('保存失败埋点数据失败:', error);
52
+ }
53
+ };
54
+ /**
55
+ * 重试失败的埋点(使用全局配置的 trackUrl)
56
+ */
57
+ const retryFailedTracks = async (force = false) => {
58
+ const failedTracks = getFailedTracks();
59
+ if (failedTracks.length === 0)
60
+ return;
61
+ const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;
62
+ const retryableTracks = failedTracks.filter(track => {
63
+ const currentRetryCount = track.retryCount || 0;
64
+ const timeCondition = force || Date.now() - track.retryTime >= retryConfig.initialDelay * Math.pow(retryConfig.delayMultiplier, currentRetryCount);
65
+ return currentRetryCount < retryConfig.maxRetryTimes && timeCondition;
66
+ });
67
+ if (retryableTracks.length === 0)
68
+ return;
69
+ for (const track of retryableTracks) {
70
+ try {
71
+ // 使用全局配置的 trackUrl
72
+ await fetch(trackUrl, {
73
+ method: 'POST',
74
+ headers: { 'Content-Type': 'application/json' },
75
+ body: JSON.stringify({
76
+ ...track,
77
+ timestamp: Date.now(),
78
+ userAgent: navigator.userAgent,
79
+ url: window.location.href,
80
+ referrer: document.referrer,
81
+ retryCount: (track.retryCount || 0) + 1
82
+ })
83
+ });
84
+ console.log('埋点重试成功:', track.eventName);
85
+ const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);
86
+ if (index > -1)
87
+ failedTracks.splice(index, 1);
88
+ }
89
+ catch (error) {
90
+ console.error('埋点重试失败:', track.eventName, error);
91
+ const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);
92
+ if (index > -1) {
93
+ failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;
94
+ failedTracks[index].retryTime = Date.now();
95
+ }
96
+ }
97
+ }
98
+ saveFailedTracks(failedTracks);
99
+ };
100
+ /**
101
+ * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)
102
+ * @param params 埋点参数
103
+ * @param config 单个 Hook 的配置(可覆盖 trackUrl)
104
+ */
105
+ const sendTrack = async (params, config) => {
106
+ var _a;
107
+ if (!params.eventName) {
108
+ console.warn('埋点缺少必要参数:eventName');
109
+ return;
110
+ }
111
+ // 优先级:单个 Hook 配置 > 全局配置
112
+ const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;
113
+ const isEnable = (_a = config.enable) !== null && _a !== void 0 ? _a : GLOBAL_TRACK_CONFIG.enable;
114
+ if (!isEnable)
115
+ return;
116
+ try {
117
+ // 使用最终确定的 trackUrl 发送请求
118
+ await fetch(finalTrackUrl, {
119
+ method: 'POST',
120
+ headers: { 'Content-Type': 'application/json' },
121
+ body: JSON.stringify({
122
+ ...params,
123
+ timestamp: Date.now(),
124
+ userAgent: navigator.userAgent,
125
+ url: window.location.href,
126
+ referrer: document.referrer
127
+ })
128
+ });
129
+ console.log('埋点上报成功:', params);
130
+ if (window.requestIdleCallback) {
131
+ window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });
132
+ }
133
+ else {
134
+ setTimeout(() => retryFailedTracks(), 1000);
135
+ }
136
+ }
137
+ catch (error) {
138
+ console.error('埋点上报失败:', error);
139
+ const failedTracks = getFailedTracks();
140
+ failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });
141
+ saveFailedTracks(failedTracks);
142
+ }
143
+ };
144
+ // ---------------------- 核心 Hooks 实现 ----------------------
145
+ const useTrack = (params, config = {}) => {
146
+ // 合并默认配置(含全局配置)和单个 Hook 配置
147
+ const mergedConfig = { ...getMergedDefaultConfig(), ...config };
148
+ const trackRef = useRef(params);
149
+ useEffect(() => {
150
+ trackRef.current = params;
151
+ }, [params]);
152
+ const triggerTrack = useCallback((customParams = {}) => {
153
+ const finalParams = {
154
+ ...trackRef.current,
155
+ ...customParams
156
+ };
157
+ // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl
158
+ sendTrack(finalParams, mergedConfig);
159
+ }, [mergedConfig]);
160
+ return { triggerTrack };
161
+ };
162
+ // 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装
163
+ const useTrackClick = (eventName, customParams = {}, config = {}) => {
164
+ const { triggerTrack } = useTrack({ eventName, type: TrackType.CLICK, ...customParams }, config);
165
+ const handleClick = useCallback((e, extraParams = {}) => {
166
+ const clickParams = { clientX: (e === null || e === void 0 ? void 0 : e.clientX) || 0, clientY: (e === null || e === void 0 ? void 0 : e.clientY) || 0, ...extraParams };
167
+ triggerTrack(clickParams);
168
+ }, [triggerTrack]);
169
+ return handleClick;
170
+ };
171
+ const useTrackExposure = (eventName, customParams = {}, config = {}) => {
172
+ const mergedConfig = { ...getMergedDefaultConfig(), ...config };
173
+ const { triggerTrack } = useTrack({ eventName, type: TrackType.EXPOSURE, ...customParams }, mergedConfig);
174
+ const targetRef = useRef(null);
175
+ const hasReported = useRef(false);
176
+ useEffect(() => {
177
+ if (!mergedConfig.enable)
178
+ return;
179
+ const observer = new IntersectionObserver((entries) => {
180
+ entries.forEach((entry) => {
181
+ if (entry.isIntersecting && !hasReported.current) {
182
+ const exposureParams = {
183
+ intersectionRatio: entry.intersectionRatio,
184
+ boundingClientRect: entry.boundingClientRect,
185
+ exposureTime: Date.now()
186
+ };
187
+ triggerTrack(exposureParams);
188
+ if (mergedConfig.exposureOnce) {
189
+ hasReported.current = true;
190
+ observer.unobserve(entry.target);
191
+ }
192
+ }
193
+ });
194
+ }, { threshold: mergedConfig.exposureThreshold });
195
+ const target = targetRef.current;
196
+ if (target)
197
+ observer.observe(target);
198
+ return () => {
199
+ if (target)
200
+ observer.unobserve(target);
201
+ observer.disconnect();
202
+ };
203
+ }, [mergedConfig, triggerTrack]);
204
+ return targetRef;
205
+ };
206
+ const useTrackPageStay = (eventName, customParams = {}, config = {}) => {
207
+ const { triggerTrack } = useTrack({ eventName, type: TrackType.PAGE_STAY, ...customParams }, config);
208
+ const startTime = useRef(Date.now());
209
+ useEffect(() => {
210
+ const handleVisibilityChange = () => {
211
+ if (document.hidden) {
212
+ const stayTime = Date.now() - startTime.current;
213
+ triggerTrack({ stayTime });
214
+ }
215
+ else {
216
+ startTime.current = Date.now();
217
+ }
218
+ };
219
+ const handleBeforeUnload = () => {
220
+ const stayTime = Date.now() - startTime.current;
221
+ triggerTrack({ stayTime });
222
+ };
223
+ document.addEventListener('visibilitychange', handleVisibilityChange);
224
+ window.addEventListener('beforeunload', handleBeforeUnload);
225
+ return () => {
226
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
227
+ window.removeEventListener('beforeunload', handleBeforeUnload);
228
+ };
229
+ }, [triggerTrack]);
230
+ };
231
+ const useTrackCustom = (eventName, customParams = {}, config = {}) => {
232
+ const { triggerTrack } = useTrack({ eventName, type: TrackType.CUSTOM, ...customParams }, config);
233
+ return triggerTrack;
234
+ };
235
+ const useTrackRetryListener = () => {
236
+ useEffect(() => {
237
+ const initTimer = setTimeout(() => retryFailedTracks(), 3000);
238
+ const handleVisibilityChange = () => {
239
+ if (!document.hidden) {
240
+ retryFailedTracks();
241
+ }
242
+ };
243
+ document.addEventListener('visibilitychange', handleVisibilityChange);
244
+ let idleCallbackId = null;
245
+ const checkIdleRetry = () => {
246
+ retryFailedTracks();
247
+ idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });
248
+ };
249
+ if (window.requestIdleCallback) {
250
+ idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });
251
+ }
252
+ return () => {
253
+ clearTimeout(initTimer);
254
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
255
+ if (idleCallbackId !== null && window.cancelIdleCallback) {
256
+ window.cancelIdleCallback(idleCallbackId);
257
+ }
258
+ };
259
+ }, []);
260
+ };
261
+
262
+ export { TrackType, getFailedTracks, retryFailedTracks, saveFailedTracks, setTrackGlobalConfig, useTrack, useTrackClick, useTrackCustom, useTrackExposure, useTrackPageStay, useTrackRetryListener };
263
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/types.ts","../src/trackHooks.ts"],"sourcesContent":["// src/types.ts\nexport enum TrackType {\n CLICK = 'click',\n EXPOSURE = 'exposure',\n PAGE_STAY = 'page_stay',\n CUSTOM = 'custom'\n}\n\nexport interface TrackParams {\n eventName: string;\n type: TrackType;\n [key: string]: any;\n}\n\n// 新增:全局配置类型\nexport interface TrackGlobalConfig {\n // 埋点上报接口 URL\n trackUrl: string;\n // 是否开启埋点\n enable?: boolean;\n // 重试配置\n retryConfig?: {\n maxRetryTimes: number;\n initialDelay: number;\n delayMultiplier: number;\n };\n}\n\n// 调整:TrackConfig 继承并扩展全局配置,支持单个 Hook 覆盖\nexport interface TrackConfig extends Partial<TrackGlobalConfig> {\n exposureOnce?: boolean;\n exposureThreshold?: number;\n}\n\nexport interface FailedTrackParams extends TrackParams {\n retryTime: number;\n retryCount?: number;\n}","// src/trackHooks.ts\nimport { useEffect, useRef, useCallback } from 'react';\nimport { TrackType, TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';\n\n// 全局配置(默认值),并提供修改全局配置的方法\nlet GLOBAL_TRACK_CONFIG: TrackGlobalConfig = {\n trackUrl: '/api/track', // 默认上报地址\n enable: true,\n retryConfig: {\n maxRetryTimes: 3,\n initialDelay: 1000,\n delayMultiplier: 2\n }\n};\n\n/**\n * 设置全局埋点配置(项目初始化时调用一次即可)\n * @param config 全局配置\n */\nexport const setTrackGlobalConfig = (config: Partial<TrackGlobalConfig>) => {\n GLOBAL_TRACK_CONFIG = { ...GLOBAL_TRACK_CONFIG, ...config };\n};\n\n// 2. 调整默认配置,合并全局配置\nconst getMergedDefaultConfig = (): TrackConfig => ({\n exposureOnce: true,\n exposureThreshold: 0.5,\n ...GLOBAL_TRACK_CONFIG // 继承全局配置(trackUrl、enable、retryConfig)\n});\n\n// ---------------------- 埋点发送 & 重试核心逻辑 ----------------------\nexport const getFailedTracks = (): FailedTrackParams[] => {\n try {\n return JSON.parse(localStorage.getItem('failedTracks') || '[]');\n } catch (error) {\n console.error('读取失败埋点数据失败:', error);\n return [];\n }\n};\n\nexport const saveFailedTracks = (tracks: FailedTrackParams[]) => {\n try {\n localStorage.setItem('failedTracks', JSON.stringify(tracks));\n } catch (error) {\n console.error('保存失败埋点数据失败:', error);\n }\n};\n\n/**\n * 重试失败的埋点(使用全局配置的 trackUrl)\n */\nexport const retryFailedTracks = async (force = false) => {\n const failedTracks = getFailedTracks();\n if (failedTracks.length === 0) return;\n\n const { retryConfig, trackUrl } = GLOBAL_TRACK_CONFIG;\n const retryableTracks = failedTracks.filter(track => {\n const currentRetryCount = track.retryCount || 0;\n const timeCondition = force || Date.now() - track.retryTime >= retryConfig!.initialDelay * Math.pow(retryConfig!.delayMultiplier, currentRetryCount);\n return currentRetryCount < retryConfig!.maxRetryTimes && timeCondition;\n });\n\n if (retryableTracks.length === 0) return;\n\n for (const track of retryableTracks) {\n try {\n // 使用全局配置的 trackUrl\n await fetch(trackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...track,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer,\n retryCount: (track.retryCount || 0) + 1\n })\n });\n console.log('埋点重试成功:', track.eventName);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) failedTracks.splice(index, 1);\n } catch (error) {\n console.error('埋点重试失败:', track.eventName, error);\n const index = failedTracks.findIndex(t => t.retryTime === track.retryTime && t.eventName === track.eventName);\n if (index > -1) {\n failedTracks[index].retryCount = (failedTracks[index].retryCount || 0) + 1;\n failedTracks[index].retryTime = Date.now();\n }\n }\n }\n\n saveFailedTracks(failedTracks);\n};\n\n/**\n * 通用埋点发送函数(支持单个 Hook 覆盖 trackUrl)\n * @param params 埋点参数\n * @param config 单个 Hook 的配置(可覆盖 trackUrl)\n */\nconst sendTrack = async (params: TrackParams, config: TrackConfig) => {\n if (!params.eventName) {\n console.warn('埋点缺少必要参数:eventName');\n return;\n }\n\n // 优先级:单个 Hook 配置 > 全局配置\n const finalTrackUrl = config.trackUrl || GLOBAL_TRACK_CONFIG.trackUrl;\n const isEnable = config.enable ?? GLOBAL_TRACK_CONFIG.enable;\n\n if (!isEnable) return;\n\n try {\n // 使用最终确定的 trackUrl 发送请求\n await fetch(finalTrackUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...params,\n timestamp: Date.now(),\n userAgent: navigator.userAgent,\n url: window.location.href,\n referrer: document.referrer\n })\n });\n console.log('埋点上报成功:', params);\n\n if (window.requestIdleCallback) {\n window.requestIdleCallback(() => retryFailedTracks(), { timeout: 2000 });\n } else {\n setTimeout(() => retryFailedTracks(), 1000);\n }\n } catch (error) {\n console.error('埋点上报失败:', error);\n const failedTracks = getFailedTracks();\n failedTracks.push({ ...params, retryTime: Date.now(), retryCount: 0 });\n saveFailedTracks(failedTracks);\n }\n};\n\n// ---------------------- 核心 Hooks 实现 ----------------------\nexport const useTrack = (params: TrackParams, config: TrackConfig = {}) => {\n // 合并默认配置(含全局配置)和单个 Hook 配置\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const trackRef = useRef(params);\n\n useEffect(() => {\n trackRef.current = params;\n }, [params]);\n\n const triggerTrack = useCallback((customParams = {}) => {\n const finalParams = {\n ...trackRef.current,\n ...customParams\n };\n // 把 mergedConfig 传给 sendTrack,支持覆盖 trackUrl\n sendTrack(finalParams, mergedConfig);\n }, [mergedConfig]);\n\n return { triggerTrack };\n};\n\n// 以下 Hooks 代码无需修改(useTrackClick/useTrackExposure 等),因为它们基于 useTrack 封装\nexport const useTrackClick = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CLICK, ...customParams },\n config\n );\n\n const handleClick = useCallback((e?: React.MouseEvent, extraParams = {}) => {\n const clickParams = { clientX: e?.clientX || 0, clientY: e?.clientY || 0, ...extraParams };\n triggerTrack(clickParams);\n }, [triggerTrack]);\n\n return handleClick;\n};\n\nexport const useTrackExposure = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const mergedConfig = { ...getMergedDefaultConfig(), ...config };\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.EXPOSURE, ...customParams },\n mergedConfig\n );\n\n const targetRef = useRef<HTMLElement>(null);\n const hasReported = useRef(false);\n\n useEffect(() => {\n if (!mergedConfig.enable) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting && !hasReported.current) {\n const exposureParams = {\n intersectionRatio: entry.intersectionRatio,\n boundingClientRect: entry.boundingClientRect,\n exposureTime: Date.now()\n };\n triggerTrack(exposureParams);\n\n if (mergedConfig.exposureOnce) {\n hasReported.current = true;\n observer.unobserve(entry.target);\n }\n }\n });\n },\n { threshold: mergedConfig.exposureThreshold }\n );\n\n const target = targetRef.current;\n if (target) observer.observe(target);\n\n return () => {\n if (target) observer.unobserve(target);\n observer.disconnect();\n };\n }, [mergedConfig, triggerTrack]);\n\n return targetRef;\n};\n\nexport const useTrackPageStay = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.PAGE_STAY, ...customParams },\n config\n );\n\n const startTime = useRef(Date.now());\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.hidden) {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n } else {\n startTime.current = Date.now();\n }\n };\n\n const handleBeforeUnload = () => {\n const stayTime = Date.now() - startTime.current;\n triggerTrack({ stayTime });\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [triggerTrack]);\n};\n\nexport const useTrackCustom = (\n eventName: string,\n customParams: Record<string, any> = {},\n config: TrackConfig = {}\n) => {\n const { triggerTrack } = useTrack(\n { eventName, type: TrackType.CUSTOM, ...customParams },\n config\n );\n\n return triggerTrack;\n};\n\nexport const useTrackRetryListener = () => {\n useEffect(() => {\n const initTimer = setTimeout(() => retryFailedTracks(), 3000);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n retryFailedTracks();\n }\n };\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n let idleCallbackId: number | null = null;\n const checkIdleRetry = () => {\n retryFailedTracks();\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n };\n if (window.requestIdleCallback) {\n idleCallbackId = window.requestIdleCallback(checkIdleRetry, { timeout: 30000 });\n }\n\n return () => {\n clearTimeout(initTimer);\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n if (idleCallbackId !== null && window.cancelIdleCallback) {\n window.cancelIdleCallback(idleCallbackId);\n }\n };\n }, []);\n};"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { TrackParams, TrackConfig, TrackGlobalConfig, FailedTrackParams } from './types';
2
+ /**
3
+ * 设置全局埋点配置(项目初始化时调用一次即可)
4
+ * @param config 全局配置
5
+ */
6
+ export declare const setTrackGlobalConfig: (config: Partial<TrackGlobalConfig>) => void;
7
+ export declare const getFailedTracks: () => FailedTrackParams[];
8
+ export declare const saveFailedTracks: (tracks: FailedTrackParams[]) => void;
9
+ /**
10
+ * 重试失败的埋点(使用全局配置的 trackUrl)
11
+ */
12
+ export declare const retryFailedTracks: (force?: boolean) => Promise<void>;
13
+ export declare const useTrack: (params: TrackParams, config?: TrackConfig) => {
14
+ triggerTrack: (customParams?: {}) => void;
15
+ };
16
+ export declare const useTrackClick: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (e?: React.MouseEvent, extraParams?: {}) => void;
17
+ export declare const useTrackExposure: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => import("react").RefObject<HTMLElement>;
18
+ export declare const useTrackPageStay: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => void;
19
+ export declare const useTrackCustom: (eventName: string, customParams?: Record<string, any>, config?: TrackConfig) => (customParams?: {}) => void;
20
+ export declare const useTrackRetryListener: () => void;
21
+ //# sourceMappingURL=trackHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trackHooks.d.ts","sourceRoot":"","sources":["../src/trackHooks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAapG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,OAAO,CAAC,iBAAiB,CAAC,SAEtE,CAAC;AAUF,eAAO,MAAM,eAAe,QAAO,iBAAiB,EAOnD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,iBAAiB,EAAE,SAM3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAU,eAAa,kBA0CpD,CAAC;AAgDF,eAAO,MAAM,QAAQ,GAAI,QAAQ,WAAW,EAAE,SAAQ,WAAgB;;CAmBrE,CAAC;AAGF,eAAO,MAAM,aAAa,GACtB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,UAOa,KAAK,CAAC,UAAU,2BAMxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,2CA6C3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GACzB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,SAgC3B,CAAC;AAEF,eAAO,MAAM,cAAc,GACvB,WAAW,MAAM,EACjB,eAAc,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EACtC,SAAQ,WAAgB,gCAQ3B,CAAC;AAEF,eAAO,MAAM,qBAAqB,YA4BjC,CAAC"}
@@ -0,0 +1,29 @@
1
+ export declare enum TrackType {
2
+ CLICK = "click",
3
+ EXPOSURE = "exposure",
4
+ PAGE_STAY = "page_stay",
5
+ CUSTOM = "custom"
6
+ }
7
+ export interface TrackParams {
8
+ eventName: string;
9
+ type: TrackType;
10
+ [key: string]: any;
11
+ }
12
+ export interface TrackGlobalConfig {
13
+ trackUrl: string;
14
+ enable?: boolean;
15
+ retryConfig?: {
16
+ maxRetryTimes: number;
17
+ initialDelay: number;
18
+ delayMultiplier: number;
19
+ };
20
+ }
21
+ export interface TrackConfig extends Partial<TrackGlobalConfig> {
22
+ exposureOnce?: boolean;
23
+ exposureThreshold?: number;
24
+ }
25
+ export interface FailedTrackParams extends TrackParams {
26
+ retryTime: number;
27
+ retryCount?: number;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,oBAAY,SAAS;IACjB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,MAAM,WAAW;CACpB;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAGD,MAAM,WAAW,iBAAiB;IAE9B,QAAQ,EAAE,MAAM,CAAC;IAEjB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,WAAW,CAAC,EAAE;QACV,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;KAC3B,CAAC;CACL;AAGD,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,iBAAiB,CAAC;IAC3D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "react-track-hooks",
3
+ "version": "1.0.0",
4
+ "description": "React 埋点 Hooks 库,支持点击、曝光、页面停留时长埋点及失败重试",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "module",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "react",
19
+ "hooks",
20
+ "track",
21
+ "埋点",
22
+ "前端埋点"
23
+ ],
24
+ "author": "PassingTraveller111 <1220839184@qq.com>",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/PassingTraveller111/react-track-hooks.git"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=16.8.0",
32
+ "react-dom": ">=16.8.0"
33
+ },
34
+ "devDependencies": {
35
+ "@rollup/plugin-commonjs": "^25.0.7",
36
+ "@rollup/plugin-node-resolve": "^15.2.3",
37
+ "@rollup/plugin-typescript": "^11.1.6",
38
+ "@types/react": "^18.2.48",
39
+ "rollup": "^4.9.6",
40
+ "rollup-plugin-dts": "^6.1.0",
41
+ "tslib": "^2.6.2",
42
+ "typescript": "^5.3.3"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }