@akson/cortex-analytics-react 2.0.0 → 2.0.1
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 +91 -73
- package/dist/index.d.mts +304 -0
- package/dist/index.d.ts +304 -0
- package/dist/index.js +574 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +544 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -61
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
import { createContext, useState, useMemo, useEffect, useCallback, useContext } from 'react';
|
|
2
|
+
import { LEAD_SCORES } from '@akson/cortex-utilities/events';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
export { ECOMMERCE_EVENTS, LEAD_GENERATION_EVENTS, LEAD_SCORES } from '@akson/cortex-utilities';
|
|
5
|
+
|
|
6
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
7
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
8
|
+
}) : x)(function(x) {
|
|
9
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
10
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// src/adapters/gtm.ts
|
|
14
|
+
var GTMAdapterImpl = class {
|
|
15
|
+
get dataLayer() {
|
|
16
|
+
if (typeof window !== "undefined") {
|
|
17
|
+
window.dataLayer = window.dataLayer || [];
|
|
18
|
+
return window.dataLayer;
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
isReady() {
|
|
23
|
+
return typeof window !== "undefined" && Array.isArray(window.dataLayer);
|
|
24
|
+
}
|
|
25
|
+
track(eventName, parameters) {
|
|
26
|
+
if (!this.isReady()) return;
|
|
27
|
+
const eventData = {
|
|
28
|
+
event: eventName,
|
|
29
|
+
...parameters,
|
|
30
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
31
|
+
};
|
|
32
|
+
this.dataLayer.push(eventData);
|
|
33
|
+
if (typeof window !== "undefined" && (process.env.NODE_ENV === "development" || window.location.hostname === "localhost")) {
|
|
34
|
+
console.log(`\u{1F4CA} GTM Event: ${eventName}`, {
|
|
35
|
+
event: eventName,
|
|
36
|
+
parameters,
|
|
37
|
+
dataLayerLength: this.dataLayer.length
|
|
38
|
+
});
|
|
39
|
+
if (eventName.includes("conversion") || eventName.includes("google_ads")) {
|
|
40
|
+
console.log("\u{1F3AF} CONVERSION EVENT:", {
|
|
41
|
+
eventName,
|
|
42
|
+
fullEventData: eventData,
|
|
43
|
+
recentEvents: this.dataLayer.slice(-3)
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
identify(userId, traits) {
|
|
49
|
+
this.track("identify_user", {
|
|
50
|
+
user_id: userId,
|
|
51
|
+
user_traits: traits
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
reset() {
|
|
55
|
+
this.track("user_logout", {});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var gtmAdapter = null;
|
|
59
|
+
function getGTMAdapter() {
|
|
60
|
+
if (!gtmAdapter) {
|
|
61
|
+
gtmAdapter = new GTMAdapterImpl();
|
|
62
|
+
}
|
|
63
|
+
return gtmAdapter;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/adapters/posthog.ts
|
|
67
|
+
var PostHogAdapterImpl = class {
|
|
68
|
+
get posthog() {
|
|
69
|
+
if (typeof window !== "undefined") {
|
|
70
|
+
if (window.posthog && typeof window.posthog.capture === "function") {
|
|
71
|
+
return window.posthog;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const posthog = __require("posthog-js").default;
|
|
75
|
+
if (posthog && typeof posthog.capture === "function") {
|
|
76
|
+
return posthog;
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
isReady() {
|
|
84
|
+
return this.posthog !== null;
|
|
85
|
+
}
|
|
86
|
+
track(eventName, properties) {
|
|
87
|
+
const ph = this.posthog;
|
|
88
|
+
if (!ph) return;
|
|
89
|
+
ph.capture(eventName, properties);
|
|
90
|
+
if (typeof window !== "undefined" && (process.env.NODE_ENV === "development" || window.location.hostname === "localhost")) {
|
|
91
|
+
console.log(`\u{1F4CA} PostHog Event: ${eventName}`, properties);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
identify(userId, traits) {
|
|
95
|
+
const ph = this.posthog;
|
|
96
|
+
if (!ph) return;
|
|
97
|
+
ph.identify(userId, traits);
|
|
98
|
+
}
|
|
99
|
+
reset() {
|
|
100
|
+
const ph = this.posthog;
|
|
101
|
+
if (!ph) return;
|
|
102
|
+
ph.reset();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var posthogAdapter = null;
|
|
106
|
+
function getPostHogAdapter() {
|
|
107
|
+
if (!posthogAdapter) {
|
|
108
|
+
posthogAdapter = new PostHogAdapterImpl();
|
|
109
|
+
}
|
|
110
|
+
return posthogAdapter;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/utils/storage.ts
|
|
114
|
+
var safeGetStorage = (storageType, key) => {
|
|
115
|
+
try {
|
|
116
|
+
if (typeof window !== "undefined") {
|
|
117
|
+
const storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
|
|
118
|
+
return storage?.getItem(key) || null;
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.warn(`Failed to access ${storageType} for key: ${key}`, error);
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
var safeSetStorage = (storageType, key, value) => {
|
|
126
|
+
try {
|
|
127
|
+
if (typeof window !== "undefined") {
|
|
128
|
+
const storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
|
|
129
|
+
storage?.setItem(key, value);
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.warn(`Failed to set ${storageType} for key: ${key}`, error);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
var safeRemoveStorage = (storageType, key) => {
|
|
136
|
+
try {
|
|
137
|
+
if (typeof window !== "undefined") {
|
|
138
|
+
const storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
|
|
139
|
+
storage?.removeItem(key);
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.warn(`Failed to remove ${storageType} for key: ${key}`, error);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/utils/session.ts
|
|
147
|
+
var SESSION_ID_KEY = "analytics_session_id";
|
|
148
|
+
var FUNNEL_PATH_KEY = "analytics_funnel_path";
|
|
149
|
+
var FUNNEL_START_KEY = "analytics_funnel_start";
|
|
150
|
+
var CURRENT_STAGE_KEY = "analytics_current_stage";
|
|
151
|
+
function generateSessionId() {
|
|
152
|
+
return `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
153
|
+
}
|
|
154
|
+
function getSessionId() {
|
|
155
|
+
let sessionId = safeGetStorage("sessionStorage", SESSION_ID_KEY);
|
|
156
|
+
if (!sessionId) {
|
|
157
|
+
sessionId = generateSessionId();
|
|
158
|
+
safeSetStorage("sessionStorage", SESSION_ID_KEY, sessionId);
|
|
159
|
+
}
|
|
160
|
+
return sessionId;
|
|
161
|
+
}
|
|
162
|
+
function storeFunnelState(stage) {
|
|
163
|
+
const state = {
|
|
164
|
+
stage,
|
|
165
|
+
timestamp: Date.now()
|
|
166
|
+
};
|
|
167
|
+
safeSetStorage("sessionStorage", CURRENT_STAGE_KEY, JSON.stringify(state));
|
|
168
|
+
const pathData = safeGetStorage("sessionStorage", FUNNEL_PATH_KEY);
|
|
169
|
+
const path = pathData ? JSON.parse(pathData) : [];
|
|
170
|
+
path.push({ stage, timestamp: Date.now() });
|
|
171
|
+
safeSetStorage("sessionStorage", FUNNEL_PATH_KEY, JSON.stringify(path));
|
|
172
|
+
}
|
|
173
|
+
function getFunnelPath() {
|
|
174
|
+
const pathData = safeGetStorage("sessionStorage", FUNNEL_PATH_KEY);
|
|
175
|
+
if (!pathData) return [];
|
|
176
|
+
const path = JSON.parse(pathData);
|
|
177
|
+
return path.map((item) => item.stage);
|
|
178
|
+
}
|
|
179
|
+
function getTimeInFunnel() {
|
|
180
|
+
const pathData = safeGetStorage("sessionStorage", FUNNEL_PATH_KEY);
|
|
181
|
+
if (!pathData) return 0;
|
|
182
|
+
const path = JSON.parse(pathData);
|
|
183
|
+
if (path.length === 0) return 0;
|
|
184
|
+
const firstStage = path[0];
|
|
185
|
+
const timeDiff = Date.now() - firstStage.timestamp;
|
|
186
|
+
return Math.floor(timeDiff / 1e3);
|
|
187
|
+
}
|
|
188
|
+
function getPreviousStage() {
|
|
189
|
+
const pathData = safeGetStorage("sessionStorage", FUNNEL_PATH_KEY);
|
|
190
|
+
if (!pathData) return void 0;
|
|
191
|
+
const path = JSON.parse(pathData);
|
|
192
|
+
return path.length > 1 ? path[path.length - 2].stage : void 0;
|
|
193
|
+
}
|
|
194
|
+
function getPreviousStageTime() {
|
|
195
|
+
const currentData = safeGetStorage("sessionStorage", CURRENT_STAGE_KEY);
|
|
196
|
+
if (!currentData) return void 0;
|
|
197
|
+
const state = JSON.parse(currentData);
|
|
198
|
+
const timeDiff = Date.now() - state.timestamp;
|
|
199
|
+
return Math.floor(timeDiff / 1e3);
|
|
200
|
+
}
|
|
201
|
+
function clearSession() {
|
|
202
|
+
safeRemoveStorage("sessionStorage", SESSION_ID_KEY);
|
|
203
|
+
safeRemoveStorage("sessionStorage", FUNNEL_PATH_KEY);
|
|
204
|
+
safeRemoveStorage("sessionStorage", FUNNEL_START_KEY);
|
|
205
|
+
safeRemoveStorage("sessionStorage", CURRENT_STAGE_KEY);
|
|
206
|
+
safeRemoveStorage("sessionStorage", "scroll_25_tracked");
|
|
207
|
+
safeRemoveStorage("sessionStorage", "scroll_50_tracked");
|
|
208
|
+
safeRemoveStorage("sessionStorage", "scroll_75_tracked");
|
|
209
|
+
}
|
|
210
|
+
function getDeviceType() {
|
|
211
|
+
if (typeof window === "undefined") return "desktop";
|
|
212
|
+
const width = window.innerWidth;
|
|
213
|
+
if (width < 768) return "mobile";
|
|
214
|
+
if (width < 1024) return "tablet";
|
|
215
|
+
return "desktop";
|
|
216
|
+
}
|
|
217
|
+
function getPerformanceData() {
|
|
218
|
+
if (typeof window === "undefined" || !window.performance) return void 0;
|
|
219
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
220
|
+
if (!navigation) return void 0;
|
|
221
|
+
return {
|
|
222
|
+
pageLoadTime: Math.round(navigation.loadEventEnd - navigation.fetchStart),
|
|
223
|
+
timeToInteraction: navigation.domInteractive - navigation.fetchStart,
|
|
224
|
+
dns: navigation.domainLookupEnd - navigation.domainLookupStart,
|
|
225
|
+
tcp: navigation.connectEnd - navigation.connectStart,
|
|
226
|
+
ttfb: navigation.responseStart - navigation.requestStart
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
var AnalyticsContext = createContext(
|
|
230
|
+
null
|
|
231
|
+
);
|
|
232
|
+
function AnalyticsProvider({
|
|
233
|
+
config,
|
|
234
|
+
children
|
|
235
|
+
}) {
|
|
236
|
+
const [isReady, setIsReady] = useState(false);
|
|
237
|
+
const gtm = useMemo(() => getGTMAdapter(), []);
|
|
238
|
+
const posthog = useMemo(() => getPostHogAdapter(), []);
|
|
239
|
+
useEffect(() => {
|
|
240
|
+
const checkReady = () => {
|
|
241
|
+
const ready = gtm.isReady();
|
|
242
|
+
setIsReady(ready);
|
|
243
|
+
};
|
|
244
|
+
checkReady();
|
|
245
|
+
const interval = setInterval(checkReady, 100);
|
|
246
|
+
const timeout = setTimeout(() => clearInterval(interval), 5e3);
|
|
247
|
+
return () => {
|
|
248
|
+
clearInterval(interval);
|
|
249
|
+
clearTimeout(timeout);
|
|
250
|
+
};
|
|
251
|
+
}, [gtm]);
|
|
252
|
+
const track = useCallback(
|
|
253
|
+
(event, properties) => {
|
|
254
|
+
if (!isReady) return;
|
|
255
|
+
const enhancedProps = {
|
|
256
|
+
...properties,
|
|
257
|
+
sessionId: getSessionId(),
|
|
258
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
259
|
+
device: getDeviceType(),
|
|
260
|
+
language: typeof document !== "undefined" ? document.documentElement.lang : void 0
|
|
261
|
+
};
|
|
262
|
+
gtm.track(event, enhancedProps);
|
|
263
|
+
if (posthog.isReady()) {
|
|
264
|
+
posthog.track(event, enhancedProps);
|
|
265
|
+
}
|
|
266
|
+
if (config.debug) {
|
|
267
|
+
console.group(`\u{1F3AF} Analytics Track: ${event}`);
|
|
268
|
+
console.log("Properties:", enhancedProps);
|
|
269
|
+
console.groupEnd();
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
[isReady, gtm, posthog, config.debug]
|
|
273
|
+
);
|
|
274
|
+
const trackPageView = useCallback(
|
|
275
|
+
(pagePath, pageTitle) => {
|
|
276
|
+
track("page_view", {
|
|
277
|
+
page_path: pagePath,
|
|
278
|
+
page_title: pageTitle || (typeof document !== "undefined" ? document.title : void 0),
|
|
279
|
+
page_location: typeof window !== "undefined" ? window.location.href : void 0
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
[track]
|
|
283
|
+
);
|
|
284
|
+
const trackInteraction = useCallback(
|
|
285
|
+
(category, action, label, value) => {
|
|
286
|
+
track("user_interaction", {
|
|
287
|
+
event_category: category,
|
|
288
|
+
event_action: action,
|
|
289
|
+
event_label: label,
|
|
290
|
+
event_value: value
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
[track]
|
|
294
|
+
);
|
|
295
|
+
const trackLead = useCallback(
|
|
296
|
+
(event, data) => {
|
|
297
|
+
const leadScore = LEAD_SCORES[event] || 0;
|
|
298
|
+
track(event, {
|
|
299
|
+
...data,
|
|
300
|
+
lead_score: leadScore,
|
|
301
|
+
event_category: "lead_generation",
|
|
302
|
+
standardized_event: true
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
[track]
|
|
306
|
+
);
|
|
307
|
+
const trackEcommerce = useCallback(
|
|
308
|
+
(event, data) => {
|
|
309
|
+
track(event, {
|
|
310
|
+
...data,
|
|
311
|
+
event_category: "ecommerce",
|
|
312
|
+
standardized_event: true
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
[track]
|
|
316
|
+
);
|
|
317
|
+
const trackFunnelStage = useCallback(
|
|
318
|
+
(stage, data) => {
|
|
319
|
+
const previousStage = getPreviousStage();
|
|
320
|
+
const timeOnStage = getPreviousStageTime();
|
|
321
|
+
const totalTimeInFunnel = getTimeInFunnel();
|
|
322
|
+
const performanceData = getPerformanceData();
|
|
323
|
+
const eventData = {
|
|
324
|
+
...data,
|
|
325
|
+
stage,
|
|
326
|
+
previousStage,
|
|
327
|
+
timeOnStage,
|
|
328
|
+
totalTimeInFunnel,
|
|
329
|
+
sessionId: getSessionId(),
|
|
330
|
+
device: getDeviceType(),
|
|
331
|
+
performanceData,
|
|
332
|
+
language: data?.language || (typeof document !== "undefined" ? document.documentElement.lang : void 0),
|
|
333
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
334
|
+
viewport: typeof window !== "undefined" ? `${window.innerWidth}x${window.innerHeight}` : void 0,
|
|
335
|
+
screenResolution: typeof window !== "undefined" ? `${window.screen.width}x${window.screen.height}` : void 0
|
|
336
|
+
};
|
|
337
|
+
storeFunnelState(stage);
|
|
338
|
+
track("funnel_stage", eventData);
|
|
339
|
+
if (config.conversions && config.conversions[stage]) {
|
|
340
|
+
track("conversion", {
|
|
341
|
+
...eventData,
|
|
342
|
+
conversion_label: config.conversions[stage],
|
|
343
|
+
conversion_type: stage
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
[track, config.conversions]
|
|
348
|
+
);
|
|
349
|
+
const trackFunnelAbandonment = useCallback(
|
|
350
|
+
(lastStage, reason, data) => {
|
|
351
|
+
const timeInFunnel = getTimeInFunnel();
|
|
352
|
+
const funnelPath = getFunnelPath();
|
|
353
|
+
track("funnel_abandonment", {
|
|
354
|
+
stage: lastStage,
|
|
355
|
+
reason,
|
|
356
|
+
timeInFunnel,
|
|
357
|
+
stagesCompleted: funnelPath.length,
|
|
358
|
+
funnelPath: funnelPath.join(" \u2192 "),
|
|
359
|
+
...data
|
|
360
|
+
});
|
|
361
|
+
},
|
|
362
|
+
[track]
|
|
363
|
+
);
|
|
364
|
+
const trackFunnelConversion = useCallback(
|
|
365
|
+
(type, value, data) => {
|
|
366
|
+
const timeInFunnel = getTimeInFunnel();
|
|
367
|
+
const funnelPath = getFunnelPath();
|
|
368
|
+
const conversionData = {
|
|
369
|
+
conversionType: type,
|
|
370
|
+
value: value || 100,
|
|
371
|
+
currency: "CHF",
|
|
372
|
+
timeInFunnel,
|
|
373
|
+
funnelPath: funnelPath.join(" \u2192 "),
|
|
374
|
+
stagesCompleted: funnelPath.length,
|
|
375
|
+
...data
|
|
376
|
+
};
|
|
377
|
+
track("funnel_conversion", conversionData);
|
|
378
|
+
clearSession();
|
|
379
|
+
},
|
|
380
|
+
[track]
|
|
381
|
+
);
|
|
382
|
+
const trackExperiment = useCallback(
|
|
383
|
+
(experimentName, variant, userId) => {
|
|
384
|
+
track("experiment_exposure", {
|
|
385
|
+
experiment_name: experimentName,
|
|
386
|
+
experiment_variant: variant,
|
|
387
|
+
user_id: userId
|
|
388
|
+
});
|
|
389
|
+
},
|
|
390
|
+
[track]
|
|
391
|
+
);
|
|
392
|
+
const trackFeatureFlag = useCallback(
|
|
393
|
+
(flagName, value, userId) => {
|
|
394
|
+
track("feature_flag_evaluation", {
|
|
395
|
+
flag_name: flagName,
|
|
396
|
+
flag_value: value,
|
|
397
|
+
user_id: userId
|
|
398
|
+
});
|
|
399
|
+
},
|
|
400
|
+
[track]
|
|
401
|
+
);
|
|
402
|
+
const identify = useCallback(
|
|
403
|
+
(userId, traits) => {
|
|
404
|
+
gtm.identify(userId, traits);
|
|
405
|
+
if (posthog.isReady()) {
|
|
406
|
+
posthog.identify(userId, traits);
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
[gtm, posthog]
|
|
410
|
+
);
|
|
411
|
+
const sendUserData = useCallback(
|
|
412
|
+
(userData) => {
|
|
413
|
+
if (!config.enableEnhancedConversions) return;
|
|
414
|
+
const cleanedData = {};
|
|
415
|
+
if (userData.email) cleanedData.email = userData.email;
|
|
416
|
+
if (userData.phone) cleanedData.phone = userData.phone;
|
|
417
|
+
if (userData.firstName) cleanedData.first_name = userData.firstName;
|
|
418
|
+
if (userData.lastName) cleanedData.last_name = userData.lastName;
|
|
419
|
+
if (userData.street) cleanedData.street = userData.street;
|
|
420
|
+
if (userData.city) cleanedData.city = userData.city;
|
|
421
|
+
if (userData.postalCode) cleanedData.postal_code = userData.postalCode;
|
|
422
|
+
if (cleanedData.email || cleanedData.phone) {
|
|
423
|
+
track("user_data_available", {
|
|
424
|
+
user_data: cleanedData
|
|
425
|
+
});
|
|
426
|
+
if (config.debug) {
|
|
427
|
+
console.log("\u{1F510} Enhanced Conversions: User data sent", {
|
|
428
|
+
hasEmail: !!cleanedData.email,
|
|
429
|
+
hasPhone: !!cleanedData.phone
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
[track, config.enableEnhancedConversions, config.debug]
|
|
435
|
+
);
|
|
436
|
+
const contextValue = useMemo(
|
|
437
|
+
() => ({
|
|
438
|
+
config,
|
|
439
|
+
isReady,
|
|
440
|
+
track,
|
|
441
|
+
trackPageView,
|
|
442
|
+
trackInteraction,
|
|
443
|
+
trackLead,
|
|
444
|
+
trackEcommerce,
|
|
445
|
+
trackFunnelStage,
|
|
446
|
+
trackFunnelAbandonment,
|
|
447
|
+
trackFunnelConversion,
|
|
448
|
+
trackExperiment,
|
|
449
|
+
trackFeatureFlag,
|
|
450
|
+
identify,
|
|
451
|
+
sendUserData,
|
|
452
|
+
getSessionId,
|
|
453
|
+
getFunnelPath,
|
|
454
|
+
getTimeInFunnel,
|
|
455
|
+
clearSession
|
|
456
|
+
}),
|
|
457
|
+
[
|
|
458
|
+
config,
|
|
459
|
+
isReady,
|
|
460
|
+
track,
|
|
461
|
+
trackPageView,
|
|
462
|
+
trackInteraction,
|
|
463
|
+
trackLead,
|
|
464
|
+
trackEcommerce,
|
|
465
|
+
trackFunnelStage,
|
|
466
|
+
trackFunnelAbandonment,
|
|
467
|
+
trackFunnelConversion,
|
|
468
|
+
trackExperiment,
|
|
469
|
+
trackFeatureFlag,
|
|
470
|
+
identify,
|
|
471
|
+
sendUserData
|
|
472
|
+
]
|
|
473
|
+
);
|
|
474
|
+
return /* @__PURE__ */ jsx(AnalyticsContext.Provider, { value: contextValue, children });
|
|
475
|
+
}
|
|
476
|
+
function useAnalytics() {
|
|
477
|
+
const context = useContext(AnalyticsContext);
|
|
478
|
+
if (!context) {
|
|
479
|
+
throw new Error("useAnalytics must be used within an AnalyticsProvider");
|
|
480
|
+
}
|
|
481
|
+
return context;
|
|
482
|
+
}
|
|
483
|
+
function useTrack() {
|
|
484
|
+
const { track, isReady } = useAnalytics();
|
|
485
|
+
return useMemo(() => ({
|
|
486
|
+
track,
|
|
487
|
+
isReady
|
|
488
|
+
}), [track, isReady]);
|
|
489
|
+
}
|
|
490
|
+
function useFunnelTracking() {
|
|
491
|
+
const {
|
|
492
|
+
trackFunnelStage,
|
|
493
|
+
trackFunnelAbandonment,
|
|
494
|
+
trackFunnelConversion,
|
|
495
|
+
getFunnelPath: getFunnelPath2,
|
|
496
|
+
getTimeInFunnel: getTimeInFunnel2,
|
|
497
|
+
clearSession: clearSession2,
|
|
498
|
+
isReady
|
|
499
|
+
} = useAnalytics();
|
|
500
|
+
return useMemo(() => ({
|
|
501
|
+
trackStage: trackFunnelStage,
|
|
502
|
+
trackAbandonment: trackFunnelAbandonment,
|
|
503
|
+
trackConversion: trackFunnelConversion,
|
|
504
|
+
getFunnelPath: getFunnelPath2,
|
|
505
|
+
getTimeInFunnel: getTimeInFunnel2,
|
|
506
|
+
clearSession: clearSession2,
|
|
507
|
+
isReady
|
|
508
|
+
}), [
|
|
509
|
+
trackFunnelStage,
|
|
510
|
+
trackFunnelAbandonment,
|
|
511
|
+
trackFunnelConversion,
|
|
512
|
+
getFunnelPath2,
|
|
513
|
+
getTimeInFunnel2,
|
|
514
|
+
clearSession2,
|
|
515
|
+
isReady
|
|
516
|
+
]);
|
|
517
|
+
}
|
|
518
|
+
function useLeadTracking() {
|
|
519
|
+
const { trackLead, sendUserData, isReady } = useAnalytics();
|
|
520
|
+
return useMemo(() => ({
|
|
521
|
+
trackLead,
|
|
522
|
+
sendUserData,
|
|
523
|
+
isReady
|
|
524
|
+
}), [trackLead, sendUserData, isReady]);
|
|
525
|
+
}
|
|
526
|
+
function useEcommerceTracking() {
|
|
527
|
+
const { trackEcommerce, isReady } = useAnalytics();
|
|
528
|
+
return useMemo(() => ({
|
|
529
|
+
trackEcommerce,
|
|
530
|
+
isReady
|
|
531
|
+
}), [trackEcommerce, isReady]);
|
|
532
|
+
}
|
|
533
|
+
function useExperimentTracking() {
|
|
534
|
+
const { trackExperiment, trackFeatureFlag, isReady } = useAnalytics();
|
|
535
|
+
return useMemo(() => ({
|
|
536
|
+
trackExperiment,
|
|
537
|
+
trackFeatureFlag,
|
|
538
|
+
isReady
|
|
539
|
+
}), [trackExperiment, trackFeatureFlag, isReady]);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export { AnalyticsContext, AnalyticsProvider, clearSession, getDeviceType, getFunnelPath, getPerformanceData, getSessionId, getTimeInFunnel, safeGetStorage, safeRemoveStorage, safeSetStorage, useAnalytics, useEcommerceTracking, useExperimentTracking, useFunnelTracking, useLeadTracking, useTrack };
|
|
543
|
+
//# sourceMappingURL=index.mjs.map
|
|
544
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/gtm.ts","../src/adapters/posthog.ts","../src/utils/storage.ts","../src/utils/session.ts","../src/providers/analytics-provider.tsx","../src/hooks/use-analytics.ts"],"names":["useMemo","getFunnelPath","getTimeInFunnel","clearSession"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * GTM (Google Tag Manager) adapter\n */\n\nimport type { GTMAdapter } from '../types';\n\ndeclare global {\n interface Window {\n dataLayer?: any[];\n }\n}\n\nexport class GTMAdapterImpl implements GTMAdapter {\n get dataLayer() {\n if (typeof window !== 'undefined') {\n window.dataLayer = window.dataLayer || [];\n return window.dataLayer;\n }\n return [];\n }\n\n isReady(): boolean {\n return typeof window !== 'undefined' && Array.isArray(window.dataLayer);\n }\n\n track(eventName: string, parameters?: Record<string, any>): void {\n if (!this.isReady()) return;\n\n const eventData = {\n event: eventName,\n ...parameters,\n timestamp: new Date().toISOString(),\n };\n\n this.dataLayer.push(eventData);\n\n // Debug logging\n if (typeof window !== 'undefined' && \n (process.env.NODE_ENV === 'development' || window.location.hostname === 'localhost')) {\n console.log(`📊 GTM Event: ${eventName}`, {\n event: eventName,\n parameters,\n dataLayerLength: this.dataLayer.length,\n });\n\n // Extra logging for conversion events\n if (eventName.includes('conversion') || eventName.includes('google_ads')) {\n console.log('🎯 CONVERSION EVENT:', {\n eventName,\n fullEventData: eventData,\n recentEvents: this.dataLayer.slice(-3),\n });\n }\n }\n }\n\n identify(userId: string, traits?: Record<string, any>): void {\n this.track('identify_user', {\n user_id: userId,\n user_traits: traits,\n });\n }\n\n reset(): void {\n // GTM doesn't need reset, but we can clear user data\n this.track('user_logout', {});\n }\n}\n\n// Singleton instance\nlet gtmAdapter: GTMAdapterImpl | null = null;\n\nexport function getGTMAdapter(): GTMAdapterImpl {\n if (!gtmAdapter) {\n gtmAdapter = new GTMAdapterImpl();\n }\n return gtmAdapter;\n}","/**\n * PostHog adapter\n */\n\nimport type { PostHogAdapter } from '../types';\n\ndeclare global {\n interface Window {\n posthog?: any;\n }\n}\n\nexport class PostHogAdapterImpl implements PostHogAdapter {\n get posthog() {\n if (typeof window !== 'undefined') {\n // Try window.posthog first (set by our provider)\n if (window.posthog && typeof window.posthog.capture === 'function') {\n return window.posthog;\n }\n // Try the imported posthog-js instance as fallback\n try {\n const posthog = require('posthog-js').default;\n if (posthog && typeof posthog.capture === 'function') {\n return posthog;\n }\n } catch {\n // posthog-js not available\n }\n }\n return null;\n }\n\n isReady(): boolean {\n return this.posthog !== null;\n }\n\n track(eventName: string, properties?: Record<string, any>): void {\n const ph = this.posthog;\n if (!ph) return; // Silent fail - PostHog might be blocked\n\n ph.capture(eventName, properties);\n\n // Debug logging\n if (typeof window !== 'undefined' && \n (process.env.NODE_ENV === 'development' || window.location.hostname === 'localhost')) {\n console.log(`📊 PostHog Event: ${eventName}`, properties);\n }\n }\n\n identify(userId: string, traits?: Record<string, any>): void {\n const ph = this.posthog;\n if (!ph) return;\n\n ph.identify(userId, traits);\n }\n\n reset(): void {\n const ph = this.posthog;\n if (!ph) return;\n\n ph.reset();\n }\n}\n\n// Singleton instance\nlet posthogAdapter: PostHogAdapterImpl | null = null;\n\nexport function getPostHogAdapter(): PostHogAdapterImpl {\n if (!posthogAdapter) {\n posthogAdapter = new PostHogAdapterImpl();\n }\n return posthogAdapter;\n}","/**\n * Safe storage utilities for browser environments\n * Handles storage access errors gracefully\n */\n\nimport type { StorageUtils } from '../types';\n\n/**\n * Safely get value from storage\n */\nexport const safeGetStorage: StorageUtils['safeGetStorage'] = (storageType, key) => {\n try {\n if (typeof window !== 'undefined') {\n const storage = storageType === 'localStorage' ? window.localStorage : window.sessionStorage;\n return storage?.getItem(key) || null;\n }\n } catch (error) {\n console.warn(`Failed to access ${storageType} for key: ${key}`, error);\n }\n return null;\n};\n\n/**\n * Safely set value in storage\n */\nexport const safeSetStorage: StorageUtils['safeSetStorage'] = (storageType, key, value) => {\n try {\n if (typeof window !== 'undefined') {\n const storage = storageType === 'localStorage' ? window.localStorage : window.sessionStorage;\n storage?.setItem(key, value);\n }\n } catch (error) {\n console.warn(`Failed to set ${storageType} for key: ${key}`, error);\n }\n};\n\n/**\n * Safely remove value from storage\n */\nexport const safeRemoveStorage: StorageUtils['safeRemoveStorage'] = (storageType, key) => {\n try {\n if (typeof window !== 'undefined') {\n const storage = storageType === 'localStorage' ? window.localStorage : window.sessionStorage;\n storage?.removeItem(key);\n }\n } catch (error) {\n console.warn(`Failed to remove ${storageType} for key: ${key}`, error);\n }\n};\n\nexport const storageUtils: StorageUtils = {\n safeGetStorage,\n safeSetStorage,\n safeRemoveStorage,\n};","/**\n * Session management utilities\n */\n\nimport { safeGetStorage, safeSetStorage, safeRemoveStorage } from './storage';\n\nconst SESSION_ID_KEY = 'analytics_session_id';\nconst FUNNEL_PATH_KEY = 'analytics_funnel_path';\nconst FUNNEL_START_KEY = 'analytics_funnel_start';\nconst CURRENT_STAGE_KEY = 'analytics_current_stage';\n\n/**\n * Generate a unique session ID\n */\nexport function generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n}\n\n/**\n * Get or create session ID\n */\nexport function getSessionId(): string {\n let sessionId = safeGetStorage('sessionStorage', SESSION_ID_KEY);\n if (!sessionId) {\n sessionId = generateSessionId();\n safeSetStorage('sessionStorage', SESSION_ID_KEY, sessionId);\n }\n return sessionId;\n}\n\n/**\n * Store funnel state\n */\nexport function storeFunnelState(stage: string): void {\n const state = {\n stage,\n timestamp: Date.now(),\n };\n safeSetStorage('sessionStorage', CURRENT_STAGE_KEY, JSON.stringify(state));\n\n // Add to funnel path\n const pathData = safeGetStorage('sessionStorage', FUNNEL_PATH_KEY);\n const path = pathData ? JSON.parse(pathData) : [];\n path.push({ stage, timestamp: Date.now() });\n safeSetStorage('sessionStorage', FUNNEL_PATH_KEY, JSON.stringify(path));\n}\n\n/**\n * Get funnel path\n */\nexport function getFunnelPath(): string[] {\n const pathData = safeGetStorage('sessionStorage', FUNNEL_PATH_KEY);\n if (!pathData) return [];\n \n const path = JSON.parse(pathData);\n return path.map((item: any) => item.stage);\n}\n\n/**\n * Get time in funnel (seconds)\n */\nexport function getTimeInFunnel(): number {\n const pathData = safeGetStorage('sessionStorage', FUNNEL_PATH_KEY);\n if (!pathData) return 0;\n \n const path = JSON.parse(pathData);\n if (path.length === 0) return 0;\n \n const firstStage = path[0];\n const timeDiff = Date.now() - firstStage.timestamp;\n return Math.floor(timeDiff / 1000);\n}\n\n/**\n * Get previous stage\n */\nexport function getPreviousStage(): string | undefined {\n const pathData = safeGetStorage('sessionStorage', FUNNEL_PATH_KEY);\n if (!pathData) return undefined;\n \n const path = JSON.parse(pathData);\n return path.length > 1 ? path[path.length - 2].stage : undefined;\n}\n\n/**\n * Get time on previous stage (seconds)\n */\nexport function getPreviousStageTime(): number | undefined {\n const currentData = safeGetStorage('sessionStorage', CURRENT_STAGE_KEY);\n if (!currentData) return undefined;\n \n const state = JSON.parse(currentData);\n const timeDiff = Date.now() - state.timestamp;\n return Math.floor(timeDiff / 1000);\n}\n\n/**\n * Clear session data\n */\nexport function clearSession(): void {\n safeRemoveStorage('sessionStorage', SESSION_ID_KEY);\n safeRemoveStorage('sessionStorage', FUNNEL_PATH_KEY);\n safeRemoveStorage('sessionStorage', FUNNEL_START_KEY);\n safeRemoveStorage('sessionStorage', CURRENT_STAGE_KEY);\n \n // Clear scroll tracking\n safeRemoveStorage('sessionStorage', 'scroll_25_tracked');\n safeRemoveStorage('sessionStorage', 'scroll_50_tracked');\n safeRemoveStorage('sessionStorage', 'scroll_75_tracked');\n}\n\n/**\n * Get device type based on viewport\n */\nexport function getDeviceType(): 'mobile' | 'desktop' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop';\n const width = window.innerWidth;\n if (width < 768) return 'mobile';\n if (width < 1024) return 'tablet';\n return 'desktop';\n}\n\n/**\n * Get performance data\n */\nexport function getPerformanceData() {\n if (typeof window === 'undefined' || !window.performance) return undefined;\n \n const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;\n if (!navigation) return undefined;\n \n return {\n pageLoadTime: Math.round(navigation.loadEventEnd - navigation.fetchStart),\n timeToInteraction: navigation.domInteractive - navigation.fetchStart,\n dns: navigation.domainLookupEnd - navigation.domainLookupStart,\n tcp: navigation.connectEnd - navigation.connectStart,\n ttfb: navigation.responseStart - navigation.requestStart,\n };\n}","/**\n * Analytics Provider for React applications\n */\n\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { LEAD_SCORES } from \"@akson/cortex-utilities/events\";\nimport type {\n AnalyticsConfig,\n AnalyticsContextValue,\n EventData,\n LeadEventData,\n EcommerceEventData,\n FunnelStageData,\n UserData,\n} from \"../types\";\n\nimport { getGTMAdapter } from \"../adapters/gtm\";\nimport { getPostHogAdapter } from \"../adapters/posthog\";\nimport {\n getSessionId,\n storeFunnelState,\n getFunnelPath,\n getTimeInFunnel,\n getPreviousStage,\n getPreviousStageTime,\n clearSession,\n getDeviceType,\n getPerformanceData,\n} from \"../utils/session\";\nimport { safeGetStorage } from \"../utils/storage\";\n\nexport const AnalyticsContext = createContext<AnalyticsContextValue | null>(\n null\n);\n\ninterface AnalyticsProviderProps {\n config: AnalyticsConfig;\n children: React.ReactNode;\n}\n\nexport function AnalyticsProvider({\n config,\n children,\n}: AnalyticsProviderProps) {\n const [isReady, setIsReady] = useState(false);\n\n // Get adapters\n const gtm = useMemo(() => getGTMAdapter(), []);\n const posthog = useMemo(() => getPostHogAdapter(), []);\n\n useEffect(() => {\n // Check if adapters are ready\n const checkReady = () => {\n const ready = gtm.isReady();\n setIsReady(ready);\n };\n\n checkReady();\n\n // Check periodically for GTM to be ready\n const interval = setInterval(checkReady, 100);\n const timeout = setTimeout(() => clearInterval(interval), 5000); // Stop after 5 seconds\n\n return () => {\n clearInterval(interval);\n clearTimeout(timeout);\n };\n }, [gtm]);\n\n // Core track function\n const track = useCallback(\n (event: string, properties?: EventData) => {\n if (!isReady) return;\n\n const enhancedProps = {\n ...properties,\n sessionId: getSessionId(),\n timestamp: new Date().toISOString(),\n device: getDeviceType(),\n language:\n typeof document !== \"undefined\"\n ? document.documentElement.lang\n : undefined,\n };\n\n // Send to GTM\n gtm.track(event, enhancedProps);\n\n // Send to PostHog if available\n if (posthog.isReady()) {\n posthog.track(event, enhancedProps);\n }\n\n // Debug mode\n if (config.debug) {\n console.group(`🎯 Analytics Track: ${event}`);\n console.log(\"Properties:\", enhancedProps);\n console.groupEnd();\n }\n },\n [isReady, gtm, posthog, config.debug]\n );\n\n // Track page view\n const trackPageView = useCallback(\n (pagePath: string, pageTitle?: string) => {\n track(\"page_view\", {\n page_path: pagePath,\n page_title:\n pageTitle ||\n (typeof document !== \"undefined\" ? document.title : undefined),\n page_location:\n typeof window !== \"undefined\" ? window.location.href : undefined,\n });\n },\n [track]\n );\n\n // Track interaction\n const trackInteraction = useCallback(\n (category: string, action: string, label?: string, value?: number) => {\n track(\"user_interaction\", {\n event_category: category,\n event_action: action,\n event_label: label,\n event_value: value,\n });\n },\n [track]\n );\n\n // Track lead event\n const trackLead = useCallback(\n (event: string, data?: Partial<LeadEventData>) => {\n const leadScore = LEAD_SCORES[event as keyof typeof LEAD_SCORES] || 0;\n\n track(event, {\n ...data,\n lead_score: leadScore,\n event_category: \"lead_generation\",\n standardized_event: true,\n });\n },\n [track]\n );\n\n // Track e-commerce event\n const trackEcommerce = useCallback(\n (event: string, data: Partial<EcommerceEventData>) => {\n track(event, {\n ...data,\n event_category: \"ecommerce\",\n standardized_event: true,\n });\n },\n [track]\n );\n\n // Track funnel stage\n const trackFunnelStage = useCallback(\n (stage: string, data?: Partial<FunnelStageData>) => {\n const previousStage = getPreviousStage();\n const timeOnStage = getPreviousStageTime();\n const totalTimeInFunnel = getTimeInFunnel();\n const performanceData = getPerformanceData();\n\n const eventData: FunnelStageData = {\n ...data,\n stage,\n previousStage,\n timeOnStage,\n totalTimeInFunnel,\n sessionId: getSessionId(),\n device: getDeviceType(),\n performanceData,\n language:\n data?.language ||\n (typeof document !== \"undefined\"\n ? document.documentElement.lang\n : undefined),\n userAgent:\n typeof navigator !== \"undefined\" ? navigator.userAgent : undefined,\n viewport:\n typeof window !== \"undefined\"\n ? `${window.innerWidth}x${window.innerHeight}`\n : undefined,\n screenResolution:\n typeof window !== \"undefined\"\n ? `${window.screen.width}x${window.screen.height}`\n : undefined,\n };\n\n // Store funnel state\n storeFunnelState(stage);\n\n // Track the event\n track(\"funnel_stage\", eventData);\n\n // If it's a conversion, track that too\n if (config.conversions && config.conversions[stage]) {\n track(\"conversion\", {\n ...eventData,\n conversion_label: config.conversions[stage],\n conversion_type: stage,\n });\n }\n },\n [track, config.conversions]\n );\n\n // Track funnel abandonment\n const trackFunnelAbandonment = useCallback(\n (lastStage: string, reason?: string, data?: Record<string, any>) => {\n const timeInFunnel = getTimeInFunnel();\n const funnelPath = getFunnelPath();\n\n track(\"funnel_abandonment\", {\n stage: lastStage,\n reason,\n timeInFunnel,\n stagesCompleted: funnelPath.length,\n funnelPath: funnelPath.join(\" → \"),\n ...data,\n });\n },\n [track]\n );\n\n // Track funnel conversion\n const trackFunnelConversion = useCallback(\n (type: string, value?: number, data?: Record<string, any>) => {\n const timeInFunnel = getTimeInFunnel();\n const funnelPath = getFunnelPath();\n\n const conversionData = {\n conversionType: type,\n value: value || 100,\n currency: \"CHF\",\n timeInFunnel,\n funnelPath: funnelPath.join(\" → \"),\n stagesCompleted: funnelPath.length,\n ...data,\n };\n\n track(\"funnel_conversion\", conversionData);\n\n // Clear funnel state after conversion\n clearSession();\n },\n [track]\n );\n\n // Track experiment\n const trackExperiment = useCallback(\n (experimentName: string, variant: string, userId?: string) => {\n track(\"experiment_exposure\", {\n experiment_name: experimentName,\n experiment_variant: variant,\n user_id: userId,\n });\n },\n [track]\n );\n\n // Track feature flag\n const trackFeatureFlag = useCallback(\n (flagName: string, value: boolean | string, userId?: string) => {\n track(\"feature_flag_evaluation\", {\n flag_name: flagName,\n flag_value: value,\n user_id: userId,\n });\n },\n [track]\n );\n\n // Identify user\n const identify = useCallback(\n (userId: string, traits?: Record<string, any>) => {\n gtm.identify(userId, traits);\n if (posthog.isReady()) {\n posthog.identify(userId, traits);\n }\n },\n [gtm, posthog]\n );\n\n // Send user data for enhanced conversions\n const sendUserData = useCallback(\n (userData: UserData) => {\n if (!config.enableEnhancedConversions) return;\n\n const cleanedData: any = {};\n if (userData.email) cleanedData.email = userData.email;\n if (userData.phone) cleanedData.phone = userData.phone;\n if (userData.firstName) cleanedData.first_name = userData.firstName;\n if (userData.lastName) cleanedData.last_name = userData.lastName;\n if (userData.street) cleanedData.street = userData.street;\n if (userData.city) cleanedData.city = userData.city;\n if (userData.postalCode) cleanedData.postal_code = userData.postalCode;\n\n // Only send if we have at least email or phone\n if (cleanedData.email || cleanedData.phone) {\n track(\"user_data_available\", {\n user_data: cleanedData,\n });\n\n if (config.debug) {\n console.log(\"🔐 Enhanced Conversions: User data sent\", {\n hasEmail: !!cleanedData.email,\n hasPhone: !!cleanedData.phone,\n });\n }\n }\n },\n [track, config.enableEnhancedConversions, config.debug]\n );\n\n // Create context value\n const contextValue = useMemo<AnalyticsContextValue>(\n () => ({\n config,\n isReady,\n track,\n trackPageView,\n trackInteraction,\n trackLead,\n trackEcommerce,\n trackFunnelStage,\n trackFunnelAbandonment,\n trackFunnelConversion,\n trackExperiment,\n trackFeatureFlag,\n identify,\n sendUserData,\n getSessionId,\n getFunnelPath,\n getTimeInFunnel,\n clearSession,\n }),\n [\n config,\n isReady,\n track,\n trackPageView,\n trackInteraction,\n trackLead,\n trackEcommerce,\n trackFunnelStage,\n trackFunnelAbandonment,\n trackFunnelConversion,\n trackExperiment,\n trackFeatureFlag,\n identify,\n sendUserData,\n ]\n );\n\n return (\n <AnalyticsContext.Provider value={contextValue}>\n {children}\n </AnalyticsContext.Provider>\n );\n}\n","/**\n * Core analytics hook\n */\n\nimport { useContext, useMemo } from 'react';\nimport { AnalyticsContext } from '../providers/analytics-provider';\nimport type { AnalyticsContextValue } from '../types';\n\n/**\n * Hook to access analytics functionality\n * @throws Error if used outside of AnalyticsProvider\n */\nexport function useAnalytics(): AnalyticsContextValue {\n const context = useContext(AnalyticsContext);\n \n if (!context) {\n throw new Error('useAnalytics must be used within an AnalyticsProvider');\n }\n \n return context;\n}\n\n/**\n * Hook for simplified tracking\n */\nexport function useTrack() {\n const { track, isReady } = useAnalytics();\n \n return useMemo(() => ({\n track,\n isReady,\n }), [track, isReady]);\n}\n\n/**\n * Hook for funnel tracking\n */\nexport function useFunnelTracking() {\n const { \n trackFunnelStage, \n trackFunnelAbandonment, \n trackFunnelConversion,\n getFunnelPath,\n getTimeInFunnel,\n clearSession,\n isReady \n } = useAnalytics();\n \n return useMemo(() => ({\n trackStage: trackFunnelStage,\n trackAbandonment: trackFunnelAbandonment,\n trackConversion: trackFunnelConversion,\n getFunnelPath,\n getTimeInFunnel,\n clearSession,\n isReady,\n }), [\n trackFunnelStage, \n trackFunnelAbandonment, \n trackFunnelConversion,\n getFunnelPath,\n getTimeInFunnel,\n clearSession,\n isReady\n ]);\n}\n\n/**\n * Hook for lead tracking\n */\nexport function useLeadTracking() {\n const { trackLead, sendUserData, isReady } = useAnalytics();\n \n return useMemo(() => ({\n trackLead,\n sendUserData,\n isReady,\n }), [trackLead, sendUserData, isReady]);\n}\n\n/**\n * Hook for e-commerce tracking\n */\nexport function useEcommerceTracking() {\n const { trackEcommerce, isReady } = useAnalytics();\n \n return useMemo(() => ({\n trackEcommerce,\n isReady,\n }), [trackEcommerce, isReady]);\n}\n\n/**\n * Hook for experiment tracking\n */\nexport function useExperimentTracking() {\n const { trackExperiment, trackFeatureFlag, isReady } = useAnalytics();\n \n return useMemo(() => ({\n trackExperiment,\n trackFeatureFlag,\n isReady,\n }), [trackExperiment, trackFeatureFlag, isReady]);\n}"]}
|