@dcl/hooks 0.0.5-20251118105707.commit-6f49aba → 0.0.6-20251118124437.commit-cdc6064

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/README.md CHANGED
@@ -66,6 +66,341 @@ function BrowserInfo() {
66
66
  }
67
67
  ```
68
68
 
69
+ ### Analytics Hooks
70
+
71
+ The package provides a set of hooks for analytics tracking using Segment. Here's how to use them:
72
+
73
+ #### Setting up the AnalyticsProvider
74
+
75
+ First, wrap your app with the AnalyticsProvider:
76
+
77
+ ```typescript
78
+ import { AnalyticsProvider } from '@dcl/hooks'
79
+
80
+ function App() {
81
+ return (
82
+ <AnalyticsProvider
83
+ writeKey="xyz1234"
84
+ userId="user-123" // Optional
85
+ traits={{ // Optional
86
+ name: 'John Doe',
87
+ email: 'john@example.com'
88
+ }}
89
+ >
90
+ <Main />
91
+ </AnalyticsProvider>
92
+ )
93
+ }
94
+ ```
95
+
96
+ #### Using the useAnalytics Hook
97
+
98
+ The `useAnalytics` hook provides access to tracking functions:
99
+
100
+ ```typescript
101
+ import { useAnalytics } from '@dcl/hooks'
102
+
103
+ function MyComponent() {
104
+ const analytics = useAnalytics()
105
+
106
+ const handleButtonClick = () => {
107
+ if (analytics.isInitialized) {
108
+ // Track an event
109
+ analytics.track('Button Clicked', {
110
+ buttonId: 'submit',
111
+ timestamp: new Date().toISOString()
112
+ })
113
+
114
+ // Identify a user
115
+ analytics.identify('user-123', {
116
+ name: 'John Doe',
117
+ email: 'john@example.com'
118
+ })
119
+ }
120
+ }
121
+
122
+ return (
123
+ <button onClick={handleButtonClick}>
124
+ Click me
125
+ </button>
126
+ )
127
+ }
128
+ ```
129
+
130
+ #### Using the usePageTracking Hook
131
+
132
+ The `usePageTracking` hook automatically tracks page views based on route changes:
133
+
134
+ ```typescript
135
+ import { usePageTracking } from '@dcl/hooks'
136
+
137
+ function MyPage() {
138
+ // Automatically tracks page view when route changes
139
+ usePageTracking()
140
+
141
+ return (
142
+ <div>
143
+ <h1>My Page</h1>
144
+ {/* Your page content */}
145
+ </div>
146
+ )
147
+ }
148
+ ```
149
+
150
+ If you need to track additional page properties, you can use the `useAnalytics` hook directly:
151
+
152
+ ```typescript
153
+ import { useAnalytics } from '@dcl/hooks'
154
+
155
+ function MyPage() {
156
+ const analytics = useAnalytics()
157
+
158
+ useEffect(() => {
159
+ if (analytics.isInitialized) {
160
+ analytics.page('My Page', {
161
+ category: 'Content',
162
+ section: 'Main',
163
+ timestamp: new Date().toISOString()
164
+ })
165
+ }
166
+ }, [analytics])
167
+
168
+ return (
169
+ <div>
170
+ <h1>My Page</h1>
171
+ {/* Your page content */}
172
+ </div>
173
+ )
174
+ }
175
+ ```
176
+
177
+ #### Complete Example
178
+
179
+ Here's a complete example showing how to use all analytics features together:
180
+
181
+ ```typescript
182
+ import { AnalyticsProvider, useAnalytics, usePageTracking } from '@dcl/hooks'
183
+
184
+ function MyPage() {
185
+ // Track page views
186
+ usePageTracking()
187
+
188
+ return (
189
+ <div>
190
+ <h1>My Page</h1>
191
+ <UserProfile />
192
+ </div>
193
+ )
194
+ }
195
+
196
+ function UserProfile() {
197
+ const analytics = useAnalytics()
198
+
199
+ const handleProfileUpdate = () => {
200
+ if (analytics.isInitialized) {
201
+ // Track profile update event
202
+ analytics.track('Profile Updated', {
203
+ timestamp: new Date().toISOString(),
204
+ updateType: 'information'
205
+ })
206
+
207
+ // Update user traits
208
+ analytics.identify('user-123', {
209
+ lastUpdated: new Date().toISOString()
210
+ })
211
+ }
212
+ }
213
+
214
+ return (
215
+ <button onClick={handleProfileUpdate}>
216
+ Update Profile
217
+ </button>
218
+ )
219
+ }
220
+
221
+ function App() {
222
+ return (
223
+ <AnalyticsProvider
224
+ writeKey="xyz1234"
225
+ userId="user-123"
226
+ traits={{
227
+ name: 'John Doe',
228
+ email: 'john@example.com'
229
+ }}
230
+ >
231
+ <MyPage />
232
+ </AnalyticsProvider>
233
+ )
234
+ }
235
+ ```
236
+
237
+ ### Analytics Hooks
238
+
239
+ The package provides a set of hooks for analytics tracking using Segment. Here's how to use them:
240
+
241
+ #### Setting up the AnalyticsProvider
242
+
243
+ First, wrap your app with the AnalyticsProvider:
244
+
245
+ ```typescript
246
+ import { AnalyticsProvider } from '@dcl/hooks'
247
+
248
+ function App() {
249
+ return (
250
+ <AnalyticsProvider
251
+ writeKey="xyz1234"
252
+ userId="user-123" // Optional
253
+ traits={{ // Optional
254
+ name: 'John Doe',
255
+ email: 'john@example.com'
256
+ }}
257
+ >
258
+ <Main />
259
+ </AnalyticsProvider>
260
+ )
261
+ }
262
+ ```
263
+
264
+ #### Using the useAnalytics Hook
265
+
266
+ The `useAnalytics` hook provides access to tracking functions:
267
+
268
+ ```typescript
269
+ import { useAnalytics } from '@dcl/hooks'
270
+
271
+ function MyComponent() {
272
+ const analytics = useAnalytics()
273
+
274
+ const handleButtonClick = () => {
275
+ if (analytics.isInitialized) {
276
+ // Track an event
277
+ analytics.track('Button Clicked', {
278
+ buttonId: 'submit',
279
+ timestamp: new Date().toISOString()
280
+ })
281
+
282
+ // Identify a user
283
+ analytics.identify('user-123', {
284
+ name: 'John Doe',
285
+ email: 'john@example.com'
286
+ })
287
+ }
288
+ }
289
+
290
+ return (
291
+ <button onClick={handleButtonClick}>
292
+ Click me
293
+ </button>
294
+ )
295
+ }
296
+ ```
297
+
298
+ #### Using the usePageTracking Hook
299
+
300
+ The `usePageTracking` hook automatically tracks page views based on route changes:
301
+
302
+ ```typescript
303
+ import { usePageTracking } from '@dcl/hooks'
304
+
305
+ function MyPage() {
306
+ // Automatically tracks page view when route changes
307
+ usePageTracking()
308
+
309
+ return (
310
+ <div>
311
+ <h1>My Page</h1>
312
+ {/* Your page content */}
313
+ </div>
314
+ )
315
+ }
316
+ ```
317
+
318
+ If you need to track additional page properties, you can use the `useAnalytics` hook directly:
319
+
320
+ ```typescript
321
+ import { useAnalytics } from '@dcl/hooks'
322
+
323
+ function MyPage() {
324
+ const analytics = useAnalytics()
325
+
326
+ useEffect(() => {
327
+ if (analytics.isInitialized) {
328
+ analytics.page('My Page', {
329
+ category: 'Content',
330
+ section: 'Main',
331
+ timestamp: new Date().toISOString()
332
+ })
333
+ }
334
+ }, [analytics])
335
+
336
+ return (
337
+ <div>
338
+ <h1>My Page</h1>
339
+ {/* Your page content */}
340
+ </div>
341
+ )
342
+ }
343
+ ```
344
+
345
+ #### Complete Example
346
+
347
+ Here's a complete example showing how to use all analytics features together:
348
+
349
+ ```typescript
350
+ import { AnalyticsProvider, useAnalytics, usePageTracking } from '@dcl/hooks'
351
+
352
+ function MyPage() {
353
+ // Track page views
354
+ usePageTracking()
355
+
356
+ return (
357
+ <div>
358
+ <h1>My Page</h1>
359
+ <UserProfile />
360
+ </div>
361
+ )
362
+ }
363
+
364
+ function UserProfile() {
365
+ const analytics = useAnalytics()
366
+
367
+ const handleProfileUpdate = () => {
368
+ if (analytics.isInitialized) {
369
+ // Track profile update event
370
+ analytics.track('Profile Updated', {
371
+ timestamp: new Date().toISOString(),
372
+ updateType: 'information'
373
+ })
374
+
375
+ // Update user traits
376
+ analytics.identify('user-123', {
377
+ lastUpdated: new Date().toISOString()
378
+ })
379
+ }
380
+ }
381
+
382
+ return (
383
+ <button onClick={handleProfileUpdate}>
384
+ Update Profile
385
+ </button>
386
+ )
387
+ }
388
+
389
+ function App() {
390
+ return (
391
+ <AnalyticsProvider
392
+ writeKey="xyz1234"
393
+ userId="user-123"
394
+ traits={{
395
+ name: 'John Doe',
396
+ email: 'john@example.com'
397
+ }}
398
+ >
399
+ <MyPage />
400
+ </AnalyticsProvider>
401
+ )
402
+ }
403
+ ```
69
404
 
70
405
  ## License
71
406
 
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ import type { AnalyticsContextType, AnalyticsProviderProps } from "./types";
3
+ declare const AnalyticsContext: React.Context<AnalyticsContextType | null>;
4
+ declare const AnalyticsProvider: React.FC<AnalyticsProviderProps>;
5
+ export { AnalyticsContext, AnalyticsProvider };
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalyticsProvider = exports.AnalyticsContext = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importStar(require("react"));
6
+ const isbot_1 = require("isbot");
7
+ const useAsyncEffect_1 = require("../../hooks/useAsyncEffect");
8
+ const AnalyticsContext = (0, react_1.createContext)(null);
9
+ exports.AnalyticsContext = AnalyticsContext;
10
+ const AnalyticsProvider = (props) => {
11
+ const { writeKey, userId, traits, children } = props;
12
+ const analyticsRef = (0, react_1.useRef)(null);
13
+ const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
14
+ (0, useAsyncEffect_1.useAsyncEffect)(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
15
+ if (!writeKey) {
16
+ console.log("[Analytics] No writeKey provided");
17
+ return;
18
+ }
19
+ const userAgent = navigator.userAgent;
20
+ const isBot = (0, isbot_1.isbot)(userAgent);
21
+ if (isBot) {
22
+ console.log("[Analytics] Skipping load: bot detected");
23
+ return;
24
+ }
25
+ try {
26
+ // eslint-disable-next-line @typescript-eslint/naming-convention
27
+ const { AnalyticsBrowser } = yield Promise.resolve().then(() => tslib_1.__importStar(require("@segment/analytics-next")));
28
+ analyticsRef.current = AnalyticsBrowser.load({ writeKey });
29
+ if (userId) {
30
+ analyticsRef.current.identify(userId, traits);
31
+ }
32
+ setIsInitialized(true);
33
+ }
34
+ catch (error) {
35
+ console.error("[Analytics] Failed to initialize:", error);
36
+ analyticsRef.current = null;
37
+ }
38
+ }), [writeKey, userId, traits]);
39
+ const contextValue = (0, react_1.useMemo)(() => {
40
+ if (!analyticsRef.current || !isInitialized) {
41
+ return {
42
+ isInitialized: false,
43
+ track: () => { },
44
+ identify: () => { },
45
+ page: () => { },
46
+ };
47
+ }
48
+ return {
49
+ isInitialized: true,
50
+ track: (event, payload) => {
51
+ var _a;
52
+ (_a = analyticsRef.current) === null || _a === void 0 ? void 0 : _a.track(event, payload);
53
+ },
54
+ identify: (id, traits) => {
55
+ var _a;
56
+ (_a = analyticsRef.current) === null || _a === void 0 ? void 0 : _a.identify(id, traits);
57
+ },
58
+ page: (name, props) => {
59
+ var _a;
60
+ (_a = analyticsRef.current) === null || _a === void 0 ? void 0 : _a.page(name, props);
61
+ },
62
+ };
63
+ }, [isInitialized]);
64
+ return (react_1.default.createElement(AnalyticsContext.Provider, { value: contextValue }, children));
65
+ };
66
+ exports.AnalyticsProvider = AnalyticsProvider;
67
+ //# sourceMappingURL=AnalyticsProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsProvider.js","sourceRoot":"","sources":["../../../src/contexts/analytics/AnalyticsProvider.tsx"],"names":[],"mappings":";;;;AAAA,uDAAuE;AAEvE,iCAA6B;AAC7B,+DAA2D;AAO3D,MAAM,gBAAgB,GAAG,IAAA,qBAAa,EAA8B,IAAI,CAAC,CAAA;AAsEhE,4CAAgB;AApEzB,MAAM,iBAAiB,GAAqC,CAC1D,KAA6B,EAC7B,EAAE;IACF,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IACpD,MAAM,YAAY,GAAG,IAAA,cAAM,EAA0B,IAAI,CAAC,CAAA;IAC1D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAA;IAEzD,IAAA,+BAAc,EAAC,GAAS,EAAE;QACxB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAA;QACrC,MAAM,KAAK,GAAG,IAAA,aAAK,EAAC,SAAS,CAAC,CAAA;QAE9B,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAA;YACtD,OAAM;QACR,CAAC;QAED,IAAI,CAAC;YACH,gEAAgE;YAChE,MAAM,EAAE,gBAAgB,EAAE,GAAG,gEAAa,yBAAyB,GAAC,CAAA;YACpE,YAAY,CAAC,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;YAE1D,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC/C,CAAC;YAED,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;YACzD,YAAY,CAAC,OAAO,GAAG,IAAI,CAAA;QAC7B,CAAC;IACH,CAAC,CAAA,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAE9B,MAAM,YAAY,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE;QAChC,IAAI,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,aAAa,EAAE,CAAC;YAC5C,OAAO;gBACL,aAAa,EAAE,KAAK;gBACpB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;gBACf,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;gBAClB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;aACf,CAAA;QACH,CAAC;QAED,OAAO;YACL,aAAa,EAAE,IAAI;YACnB,KAAK,EAAE,CAAC,KAAa,EAAE,OAAsB,EAAE,EAAE;;gBAC/C,MAAA,YAAY,CAAC,OAAO,0CAAE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;YAC7C,CAAC;YACD,QAAQ,EAAE,CAAC,EAAU,EAAE,MAAgC,EAAE,EAAE;;gBACzD,MAAA,YAAY,CAAC,OAAO,0CAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YAC5C,CAAC;YACD,IAAI,EAAE,CAAC,IAAY,EAAE,KAA+B,EAAE,EAAE;;gBACtD,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YACzC,CAAC;SACF,CAAA;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;IAEnB,OAAO,CACL,8BAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,YAAY,IAC3C,QAAQ,CACiB,CAC7B,CAAA;AACH,CAAC,CAAA;AAE0B,8CAAiB"}
@@ -0,0 +1,15 @@
1
+ import type { EventProperties } from "@segment/analytics-next";
2
+ type AnalyticsProviderProps = {
3
+ writeKey: string;
4
+ userId?: string;
5
+ traits?: Record<string, unknown>;
6
+ children: React.ReactNode;
7
+ };
8
+ type TrackPayload = EventProperties;
9
+ type AnalyticsContextType = {
10
+ isInitialized: boolean;
11
+ track: (event: string, payload?: TrackPayload) => void;
12
+ identify: (userId: string, traits?: Record<string, unknown>) => void;
13
+ page: (name: string, props?: Record<string, unknown>) => void;
14
+ };
15
+ export { type AnalyticsProviderProps, type TrackPayload, type AnalyticsContextType, };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/contexts/analytics/types.ts"],"names":[],"mappings":""}
@@ -8,3 +8,5 @@ export { useAsyncTasks } from "./useAsyncTasks";
8
8
  export { usePatchState } from "./usePatchState";
9
9
  export { useAsyncEffect } from "./useAsyncEffect";
10
10
  export { useAsyncMemo, createAsyncMemoState } from "./useAsyncMemo";
11
+ export { useAnalytics } from "./useAnalytics";
12
+ export { usePageTracking } from "./usePageTracking";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createAsyncMemoState = exports.useAsyncMemo = exports.useAsyncEffect = exports.usePatchState = exports.useAsyncTasks = exports.useAsyncTask = exports.createAsyncStateState = exports.useAsyncState = exports.useAdvancedUserAgentData = void 0;
3
+ exports.usePageTracking = exports.useAnalytics = exports.createAsyncMemoState = exports.useAsyncMemo = exports.useAsyncEffect = exports.usePatchState = exports.useAsyncTasks = exports.useAsyncTask = exports.createAsyncStateState = exports.useAsyncState = exports.useAdvancedUserAgentData = void 0;
4
4
  // Hooks
5
5
  var useAdvancedUserAgentData_1 = require("./useAdvancedUserAgentData");
6
6
  Object.defineProperty(exports, "useAdvancedUserAgentData", { enumerable: true, get: function () { return useAdvancedUserAgentData_1.useAdvancedUserAgentData; } });
@@ -18,4 +18,8 @@ Object.defineProperty(exports, "useAsyncEffect", { enumerable: true, get: functi
18
18
  var useAsyncMemo_1 = require("./useAsyncMemo");
19
19
  Object.defineProperty(exports, "useAsyncMemo", { enumerable: true, get: function () { return useAsyncMemo_1.useAsyncMemo; } });
20
20
  Object.defineProperty(exports, "createAsyncMemoState", { enumerable: true, get: function () { return useAsyncMemo_1.createAsyncMemoState; } });
21
+ var useAnalytics_1 = require("./useAnalytics");
22
+ Object.defineProperty(exports, "useAnalytics", { enumerable: true, get: function () { return useAnalytics_1.useAnalytics; } });
23
+ var usePageTracking_1 = require("./usePageTracking");
24
+ Object.defineProperty(exports, "usePageTracking", { enumerable: true, get: function () { return usePageTracking_1.usePageTracking; } });
21
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;AAKA,QAAQ;AACR,uEAAqE;AAA5D,oIAAA,wBAAwB,OAAA;AACjC,iDAAsE;AAA7D,8GAAA,aAAa,OAAA;AAAE,sHAAA,qBAAqB,OAAA;AAC7C,+CAA6C;AAApC,4GAAA,YAAY,OAAA;AACrB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,+CAAmE;AAA1D,4GAAA,YAAY,OAAA;AAAE,oHAAA,oBAAoB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;AAKA,QAAQ;AACR,uEAAqE;AAA5D,oIAAA,wBAAwB,OAAA;AACjC,iDAAsE;AAA7D,8GAAA,aAAa,OAAA;AAAE,sHAAA,qBAAqB,OAAA;AAC7C,+CAA6C;AAApC,4GAAA,YAAY,OAAA;AACrB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,mDAAiD;AAAxC,gHAAA,cAAc,OAAA;AACvB,+CAAmE;AAA1D,4GAAA,YAAY,OAAA;AAAE,oHAAA,oBAAoB,OAAA;AAC3C,+CAA6C;AAApC,4GAAA,YAAY,OAAA;AACrB,qDAAmD;AAA1C,kHAAA,eAAe,OAAA"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyticsContextType } from "../contexts/analytics/types";
2
+ declare const useAnalytics: () => AnalyticsContextType;
3
+ export { useAnalytics };
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAnalytics = void 0;
4
+ const react_1 = require("react");
5
+ const AnalyticsProvider_1 = require("../contexts/analytics/AnalyticsProvider");
6
+ const useAnalytics = () => {
7
+ const analyticsContext = (0, react_1.useContext)(AnalyticsProvider_1.AnalyticsContext);
8
+ if (!analyticsContext) {
9
+ throw new Error("useAnalytics must be used within AnalyticsProvider");
10
+ }
11
+ if (!analyticsContext.isInitialized) {
12
+ return {
13
+ isInitialized: false,
14
+ track: () => { },
15
+ identify: () => { },
16
+ page: () => { },
17
+ };
18
+ }
19
+ return {
20
+ isInitialized: true,
21
+ track: analyticsContext.track,
22
+ identify: analyticsContext.identify,
23
+ page: analyticsContext.page,
24
+ };
25
+ };
26
+ exports.useAnalytics = useAnalytics;
27
+ //# sourceMappingURL=useAnalytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnalytics.js","sourceRoot":"","sources":["../../src/hooks/useAnalytics.ts"],"names":[],"mappings":";;;AAAA,iCAAkC;AAClC,+EAA0E;AAG1E,MAAM,YAAY,GAAG,GAAyB,EAAE;IAC9C,MAAM,gBAAgB,GAAG,IAAA,kBAAU,EAAC,oCAAgB,CAAC,CAAA;IACrD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO;YACL,aAAa,EAAE,KAAK;YACpB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;YACf,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;YAClB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;SACf,CAAA;IACH,CAAC;IAED,OAAO;QACL,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,gBAAgB,CAAC,KAAK;QAC7B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ;QACnC,IAAI,EAAE,gBAAgB,CAAC,IAAI;KAC5B,CAAA;AACH,CAAC,CAAA;AAEQ,oCAAY"}
@@ -0,0 +1,2 @@
1
+ declare const usePageTracking: () => void;
2
+ export { usePageTracking };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePageTracking = void 0;
4
+ const react_1 = require("react");
5
+ const react_router_1 = require("react-router");
6
+ const useAnalytics_1 = require("./useAnalytics");
7
+ const usePageTracking = () => {
8
+ const location = (0, react_router_1.useLocation)();
9
+ const { page } = (0, useAnalytics_1.useAnalytics)();
10
+ (0, react_1.useEffect)(() => {
11
+ page(location.pathname);
12
+ }, [location, page]);
13
+ };
14
+ exports.usePageTracking = usePageTracking;
15
+ //# sourceMappingURL=usePageTracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePageTracking.js","sourceRoot":"","sources":["../../src/hooks/usePageTracking.ts"],"names":[],"mappings":";;;AAAA,iCAAiC;AACjC,+CAA0C;AAC1C,iDAA6C;AAE7C,MAAM,eAAe,GAAG,GAAG,EAAE;IAC3B,MAAM,QAAQ,GAAG,IAAA,0BAAW,GAAE,CAAA;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,2BAAY,GAAE,CAAA;IAE/B,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;AACtB,CAAC,CAAA;AAEQ,0CAAe"}
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ import type { AnalyticsContextType, AnalyticsProviderProps } from "./types";
3
+ declare const AnalyticsContext: React.Context<AnalyticsContextType | null>;
4
+ declare const AnalyticsProvider: React.FC<AnalyticsProviderProps>;
5
+ export { AnalyticsContext, AnalyticsProvider };
@@ -0,0 +1,59 @@
1
+ import React, { createContext, useMemo, useRef, useState } from "react";
2
+ import { isbot } from "isbot";
3
+ import { useAsyncEffect } from "../../hooks/useAsyncEffect";
4
+ const AnalyticsContext = createContext(null);
5
+ const AnalyticsProvider = (props) => {
6
+ const { writeKey, userId, traits, children } = props;
7
+ const analyticsRef = useRef(null);
8
+ const [isInitialized, setIsInitialized] = useState(false);
9
+ useAsyncEffect(async () => {
10
+ if (!writeKey) {
11
+ console.log("[Analytics] No writeKey provided");
12
+ return;
13
+ }
14
+ const userAgent = navigator.userAgent;
15
+ const isBot = isbot(userAgent);
16
+ if (isBot) {
17
+ console.log("[Analytics] Skipping load: bot detected");
18
+ return;
19
+ }
20
+ try {
21
+ // eslint-disable-next-line @typescript-eslint/naming-convention
22
+ const { AnalyticsBrowser } = await import("@segment/analytics-next");
23
+ analyticsRef.current = AnalyticsBrowser.load({ writeKey });
24
+ if (userId) {
25
+ analyticsRef.current.identify(userId, traits);
26
+ }
27
+ setIsInitialized(true);
28
+ }
29
+ catch (error) {
30
+ console.error("[Analytics] Failed to initialize:", error);
31
+ analyticsRef.current = null;
32
+ }
33
+ }, [writeKey, userId, traits]);
34
+ const contextValue = useMemo(() => {
35
+ if (!analyticsRef.current || !isInitialized) {
36
+ return {
37
+ isInitialized: false,
38
+ track: () => { },
39
+ identify: () => { },
40
+ page: () => { },
41
+ };
42
+ }
43
+ return {
44
+ isInitialized: true,
45
+ track: (event, payload) => {
46
+ analyticsRef.current?.track(event, payload);
47
+ },
48
+ identify: (id, traits) => {
49
+ analyticsRef.current?.identify(id, traits);
50
+ },
51
+ page: (name, props) => {
52
+ analyticsRef.current?.page(name, props);
53
+ },
54
+ };
55
+ }, [isInitialized]);
56
+ return (React.createElement(AnalyticsContext.Provider, { value: contextValue }, children));
57
+ };
58
+ export { AnalyticsContext, AnalyticsProvider };
59
+ //# sourceMappingURL=AnalyticsProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsProvider.js","sourceRoot":"","sources":["../../../src/contexts/analytics/AnalyticsProvider.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { EventProperties } from "@segment/analytics-next";
2
+ type AnalyticsProviderProps = {
3
+ writeKey: string;
4
+ userId?: string;
5
+ traits?: Record<string, unknown>;
6
+ children: React.ReactNode;
7
+ };
8
+ type TrackPayload = EventProperties;
9
+ type AnalyticsContextType = {
10
+ isInitialized: boolean;
11
+ track: (event: string, payload?: TrackPayload) => void;
12
+ identify: (userId: string, traits?: Record<string, unknown>) => void;
13
+ page: (name: string, props?: Record<string, unknown>) => void;
14
+ };
15
+ export { type AnalyticsProviderProps, type TrackPayload, type AnalyticsContextType, };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/contexts/analytics/types.ts"],"names":[],"mappings":""}
@@ -8,3 +8,5 @@ export { useAsyncTasks } from "./useAsyncTasks";
8
8
  export { usePatchState } from "./usePatchState";
9
9
  export { useAsyncEffect } from "./useAsyncEffect";
10
10
  export { useAsyncMemo, createAsyncMemoState } from "./useAsyncMemo";
11
+ export { useAnalytics } from "./useAnalytics";
12
+ export { usePageTracking } from "./usePageTracking";
@@ -6,4 +6,6 @@ export { useAsyncTasks } from "./useAsyncTasks";
6
6
  export { usePatchState } from "./usePatchState";
7
7
  export { useAsyncEffect } from "./useAsyncEffect";
8
8
  export { useAsyncMemo, createAsyncMemoState } from "./useAsyncMemo";
9
+ export { useAnalytics } from "./useAnalytics";
10
+ export { usePageTracking } from "./usePageTracking";
9
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAKA,QAAQ;AACR,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAKA,QAAQ;AACR,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyticsContextType } from "../contexts/analytics/types";
2
+ declare const useAnalytics: () => AnalyticsContextType;
3
+ export { useAnalytics };
@@ -0,0 +1,24 @@
1
+ import { useContext } from "react";
2
+ import { AnalyticsContext } from "../contexts/analytics/AnalyticsProvider";
3
+ const useAnalytics = () => {
4
+ const analyticsContext = useContext(AnalyticsContext);
5
+ if (!analyticsContext) {
6
+ throw new Error("useAnalytics must be used within AnalyticsProvider");
7
+ }
8
+ if (!analyticsContext.isInitialized) {
9
+ return {
10
+ isInitialized: false,
11
+ track: () => { },
12
+ identify: () => { },
13
+ page: () => { },
14
+ };
15
+ }
16
+ return {
17
+ isInitialized: true,
18
+ track: analyticsContext.track,
19
+ identify: analyticsContext.identify,
20
+ page: analyticsContext.page,
21
+ };
22
+ };
23
+ export { useAnalytics };
24
+ //# sourceMappingURL=useAnalytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnalytics.js","sourceRoot":"","sources":["../../src/hooks/useAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAA;AAG1E,MAAM,YAAY,GAAG,GAAyB,EAAE;IAC9C,MAAM,gBAAgB,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAA;IACrD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO;YACL,aAAa,EAAE,KAAK;YACpB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;YACf,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;YAClB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;SACf,CAAA;IACH,CAAC;IAED,OAAO;QACL,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,gBAAgB,CAAC,KAAK;QAC7B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ;QACnC,IAAI,EAAE,gBAAgB,CAAC,IAAI;KAC5B,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ declare const usePageTracking: () => void;
2
+ export { usePageTracking };
@@ -0,0 +1,12 @@
1
+ import { useEffect } from "react";
2
+ import { useLocation } from "react-router";
3
+ import { useAnalytics } from "./useAnalytics";
4
+ const usePageTracking = () => {
5
+ const location = useLocation();
6
+ const { page } = useAnalytics();
7
+ useEffect(() => {
8
+ page(location.pathname);
9
+ }, [location, page]);
10
+ };
11
+ export { usePageTracking };
12
+ //# sourceMappingURL=usePageTracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePageTracking.js","sourceRoot":"","sources":["../../src/hooks/usePageTracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,MAAM,eAAe,GAAG,GAAG,EAAE;IAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,CAAA;IAE/B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;AACtB,CAAC,CAAA;AAED,OAAO,EAAE,eAAe,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcl/hooks",
3
- "version": "0.0.5-20251118105707.commit-6f49aba",
3
+ "version": "0.0.6-20251118124437.commit-cdc6064",
4
4
  "main": "cjs/index.js",
5
5
  "module": "esm/index.js",
6
6
  "exports": {
@@ -49,12 +49,15 @@
49
49
  "prettier": "^3.5.0",
50
50
  "react": "^18.0.0",
51
51
  "react-dom": "^18.0.0",
52
+ "react-router": "^7.4.0",
52
53
  "ts-jest": "^29.2.5",
53
54
  "typescript": "^5.0.0",
54
55
  "typescript-eslint": "^7.15.0"
55
56
  },
56
57
  "dependencies": {
58
+ "@segment/analytics-next": "^1.79.0",
57
59
  "@sentry/browser": "^9.0.0",
60
+ "isbot": "^5.1.25",
58
61
  "ua-parser-js": "^2.0.2"
59
62
  },
60
63
  "keywords": [
@@ -76,7 +79,10 @@
76
79
  "moduleNameMapper": {
77
80
  "^test/(.*)$": "<rootDir>/test/$1",
78
81
  "^src/(.*)$": "<rootDir>/src/$1"
79
- }
82
+ },
83
+ "setupFilesAfterEnv": [
84
+ "<rootDir>/test/setup.ts"
85
+ ]
80
86
  },
81
- "commit": "6f49aba696711d27f587dd39f07c6a12fb36a19c"
87
+ "commit": "cdc6064be83eb9bce906f852766e5e832147465f"
82
88
  }