@stacksee/analytics 0.4.2 → 0.4.3
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/dist/client-CyvENC-f.js +577 -0
- package/dist/client-MwIAm9fk.js +96 -0
- package/dist/client.js +1 -1
- package/dist/index.js +10 -14
- package/dist/providers.js +85 -4
- package/dist/server.js +403 -0
- package/dist/src/adapters/client/browser-analytics.d.ts +393 -0
- package/dist/src/adapters/server/server-analytics.d.ts +403 -0
- package/dist/src/index.d.ts +1 -2
- package/dist/src/providers/client.d.ts +3 -0
- package/dist/test/providers.test.d.ts +1 -0
- package/dist/test/server.test.d.ts +1 -0
- package/package.json +1 -1
- package/dist/client-CyxgEISv.js +0 -184
- package/dist/server-BKqARaUf.js +0 -174
|
@@ -4,20 +4,423 @@ export declare class ServerAnalytics<TEventMap extends DefaultEventMap = Default
|
|
|
4
4
|
private providers;
|
|
5
5
|
private config;
|
|
6
6
|
private initialized;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new ServerAnalytics instance for server-side event tracking.
|
|
9
|
+
*
|
|
10
|
+
* The server analytics instance is designed for Node.js environments including
|
|
11
|
+
* long-running servers, serverless functions, and edge computing environments.
|
|
12
|
+
*
|
|
13
|
+
* @param config Analytics configuration including providers and default context
|
|
14
|
+
* @param config.providers Array of analytics provider instances (e.g., PostHogServerProvider)
|
|
15
|
+
* @param config.defaultContext Optional default context to include with all events
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { ServerAnalytics } from '@stacksee/analytics/server';
|
|
20
|
+
* import { PostHogServerProvider } from '@stacksee/analytics/providers/posthog';
|
|
21
|
+
*
|
|
22
|
+
* const analytics = new ServerAnalytics({
|
|
23
|
+
* providers: [
|
|
24
|
+
* new PostHogServerProvider({
|
|
25
|
+
* apiKey: process.env.POSTHOG_API_KEY,
|
|
26
|
+
* host: process.env.POSTHOG_HOST
|
|
27
|
+
* })
|
|
28
|
+
* ],
|
|
29
|
+
* defaultContext: {
|
|
30
|
+
* app: { version: '1.0.0', environment: 'production' }
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* analytics.initialize();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
7
37
|
constructor(config: AnalyticsConfig);
|
|
38
|
+
/**
|
|
39
|
+
* Initializes all analytics providers.
|
|
40
|
+
*
|
|
41
|
+
* This method must be called before tracking events. It initializes all configured
|
|
42
|
+
* providers synchronously. Unlike the browser version, server initialization is
|
|
43
|
+
* typically synchronous as providers don't need to load external scripts.
|
|
44
|
+
*
|
|
45
|
+
* The method is safe to call multiple times and will not re-initialize if already done.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const analytics = new ServerAnalytics({ providers: [] });
|
|
50
|
+
*
|
|
51
|
+
* // Initialize before tracking events
|
|
52
|
+
* analytics.initialize();
|
|
53
|
+
*
|
|
54
|
+
* // Now ready to track events
|
|
55
|
+
* await analytics.track('api_request', { endpoint: '/users' });
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* // In a serverless function
|
|
61
|
+
* export async function handler(req, res) {
|
|
62
|
+
* const analytics = new ServerAnalytics({ providers: [] });
|
|
63
|
+
* analytics.initialize(); // Quick synchronous initialization
|
|
64
|
+
*
|
|
65
|
+
* await analytics.track('function_invoked', {
|
|
66
|
+
* path: req.path,
|
|
67
|
+
* method: req.method
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* await analytics.shutdown(); // Important for serverless
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
8
74
|
initialize(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Identifies a user with optional traits.
|
|
77
|
+
*
|
|
78
|
+
* Associates subsequent events with the specified user ID and optionally
|
|
79
|
+
* sets user properties. This method is typically called when processing
|
|
80
|
+
* authentication or when you have user context available on the server.
|
|
81
|
+
*
|
|
82
|
+
* @param userId Unique identifier for the user (e.g., database ID, email)
|
|
83
|
+
* @param traits Optional user properties and characteristics
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // Basic user identification
|
|
88
|
+
* analytics.identify('user-123');
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* // Identify with user traits from database
|
|
94
|
+
* analytics.identify('user-123', {
|
|
95
|
+
* email: 'john@example.com',
|
|
96
|
+
* name: 'John Doe',
|
|
97
|
+
* plan: 'enterprise',
|
|
98
|
+
* company: 'Acme Corp',
|
|
99
|
+
* createdAt: '2024-01-15T10:00:00Z',
|
|
100
|
+
* lastSeenAt: new Date().toISOString()
|
|
101
|
+
* });
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // In an API authentication middleware
|
|
107
|
+
* async function authMiddleware(req, res, next) {
|
|
108
|
+
* const user = await getUserFromToken(req.headers.authorization);
|
|
109
|
+
*
|
|
110
|
+
* analytics.identify(user.id, {
|
|
111
|
+
* email: user.email,
|
|
112
|
+
* role: user.role,
|
|
113
|
+
* organization: user.organization
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* req.user = user;
|
|
117
|
+
* next();
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
9
121
|
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
122
|
+
/**
|
|
123
|
+
* Tracks a custom event with properties and optional context.
|
|
124
|
+
*
|
|
125
|
+
* This is the main method for tracking business events on the server side.
|
|
126
|
+
* The method sends the event to all configured providers and waits for completion.
|
|
127
|
+
* Failed providers don't prevent others from succeeding.
|
|
128
|
+
*
|
|
129
|
+
* Server-side tracking typically includes additional context like IP addresses,
|
|
130
|
+
* user agents, and server-specific metadata that isn't available on the client.
|
|
131
|
+
*
|
|
132
|
+
* @param eventName Name of the event to track (must match your event definitions)
|
|
133
|
+
* @param properties Event-specific properties and data
|
|
134
|
+
* @param options Optional configuration including user ID, session ID, and context
|
|
135
|
+
* @param options.userId User ID to associate with this event
|
|
136
|
+
* @param options.sessionId Session ID to associate with this event
|
|
137
|
+
* @param options.context Additional context for this event
|
|
138
|
+
* @returns Promise that resolves when tracking is complete for all providers
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* // Basic event tracking
|
|
143
|
+
* await analytics.track('api_request', {
|
|
144
|
+
* endpoint: '/api/users',
|
|
145
|
+
* method: 'GET',
|
|
146
|
+
* responseTime: 150,
|
|
147
|
+
* statusCode: 200
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* // Track with user context
|
|
154
|
+
* await analytics.track('purchase_completed', {
|
|
155
|
+
* orderId: 'order-123',
|
|
156
|
+
* amount: 99.99,
|
|
157
|
+
* currency: 'USD',
|
|
158
|
+
* itemCount: 3
|
|
159
|
+
* }, {
|
|
160
|
+
* userId: 'user-456',
|
|
161
|
+
* sessionId: 'session-789',
|
|
162
|
+
* context: {
|
|
163
|
+
* page: { path: '/checkout/complete' },
|
|
164
|
+
* device: { userAgent: req.headers['user-agent'] },
|
|
165
|
+
* ip: req.ip
|
|
166
|
+
* }
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* // In an Express.js route handler
|
|
173
|
+
* app.post('/api/users', async (req, res) => {
|
|
174
|
+
* const user = await createUser(req.body);
|
|
175
|
+
*
|
|
176
|
+
* // Track user creation with server context
|
|
177
|
+
* await analytics.track('user_created', {
|
|
178
|
+
* userId: user.id,
|
|
179
|
+
* email: user.email,
|
|
180
|
+
* plan: user.plan
|
|
181
|
+
* }, {
|
|
182
|
+
* userId: user.id,
|
|
183
|
+
* context: {
|
|
184
|
+
* page: { path: req.path },
|
|
185
|
+
* device: { userAgent: req.headers['user-agent'] },
|
|
186
|
+
* ip: req.ip,
|
|
187
|
+
* server: { version: process.env.APP_VERSION }
|
|
188
|
+
* }
|
|
189
|
+
* });
|
|
190
|
+
*
|
|
191
|
+
* res.json(user);
|
|
192
|
+
* });
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* // Error handling in tracking
|
|
198
|
+
* try {
|
|
199
|
+
* await analytics.track('payment_processed', {
|
|
200
|
+
* amount: 100,
|
|
201
|
+
* currency: 'USD'
|
|
202
|
+
* });
|
|
203
|
+
* } catch (error) {
|
|
204
|
+
* // This only catches initialization errors
|
|
205
|
+
* // Individual provider failures are logged but don't throw
|
|
206
|
+
* console.error('Failed to track event:', error);
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
10
210
|
track<TEventName extends keyof TEventMap & string>(eventName: TEventName, properties: TEventMap[TEventName], options?: {
|
|
11
211
|
userId?: string;
|
|
12
212
|
sessionId?: string;
|
|
13
213
|
context?: EventContext;
|
|
14
214
|
}): Promise<void>;
|
|
215
|
+
/**
|
|
216
|
+
* Tracks a page view event from the server side.
|
|
217
|
+
*
|
|
218
|
+
* Server-side page view tracking is useful for server-rendered applications,
|
|
219
|
+
* SSR frameworks, or when you want to ensure page views are tracked even
|
|
220
|
+
* if client-side JavaScript fails.
|
|
221
|
+
*
|
|
222
|
+
* @param properties Optional properties to include with the page view
|
|
223
|
+
* @param options Optional configuration including context
|
|
224
|
+
* @param options.context Additional context for this page view
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* // Basic server-side page view
|
|
229
|
+
* analytics.pageView();
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* // Page view with server context
|
|
235
|
+
* analytics.pageView({
|
|
236
|
+
* loadTime: 250,
|
|
237
|
+
* template: 'product-detail',
|
|
238
|
+
* ssr: true
|
|
239
|
+
* }, {
|
|
240
|
+
* context: {
|
|
241
|
+
* page: {
|
|
242
|
+
* path: '/products/widget-123',
|
|
243
|
+
* title: 'Amazing Widget - Product Details'
|
|
244
|
+
* },
|
|
245
|
+
* device: {
|
|
246
|
+
* userAgent: req.headers['user-agent']
|
|
247
|
+
* },
|
|
248
|
+
* server: {
|
|
249
|
+
* renderTime: 45,
|
|
250
|
+
* cacheHit: false
|
|
251
|
+
* }
|
|
252
|
+
* }
|
|
253
|
+
* });
|
|
254
|
+
* ```
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```typescript
|
|
258
|
+
* // In a Next.js API route or middleware
|
|
259
|
+
* export async function middleware(req) {
|
|
260
|
+
* if (req.nextUrl.pathname.startsWith('/product/')) {
|
|
261
|
+
* analytics.pageView({
|
|
262
|
+
* category: 'product',
|
|
263
|
+
* productId: req.nextUrl.pathname.split('/').pop()
|
|
264
|
+
* }, {
|
|
265
|
+
* context: {
|
|
266
|
+
* page: { path: req.nextUrl.pathname },
|
|
267
|
+
* device: { userAgent: req.headers.get('user-agent') },
|
|
268
|
+
* referrer: req.headers.get('referer')
|
|
269
|
+
* }
|
|
270
|
+
* });
|
|
271
|
+
* }
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
15
275
|
pageView(properties?: Record<string, unknown>, options?: {
|
|
16
276
|
context?: EventContext;
|
|
17
277
|
}): void;
|
|
278
|
+
/**
|
|
279
|
+
* Tracks when a user leaves a page from the server side.
|
|
280
|
+
*
|
|
281
|
+
* Server-side page leave tracking is less common than client-side but can be
|
|
282
|
+
* useful in certain scenarios like tracking session timeouts, or when combined
|
|
283
|
+
* with server-side session management.
|
|
284
|
+
*
|
|
285
|
+
* Note: Not all analytics providers support page leave events. The method
|
|
286
|
+
* will only call providers that implement the pageLeave method.
|
|
287
|
+
*
|
|
288
|
+
* @param properties Optional properties to include with the page leave event
|
|
289
|
+
* @param options Optional configuration including context
|
|
290
|
+
* @param options.context Additional context for this page leave
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* // Basic page leave tracking
|
|
295
|
+
* analytics.pageLeave();
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```typescript
|
|
300
|
+
* // Page leave with session context
|
|
301
|
+
* analytics.pageLeave({
|
|
302
|
+
* sessionDuration: 45000, // 45 seconds
|
|
303
|
+
* pagesViewed: 3,
|
|
304
|
+
* exitReason: 'session_timeout'
|
|
305
|
+
* }, {
|
|
306
|
+
* context: {
|
|
307
|
+
* session: {
|
|
308
|
+
* id: 'session-123',
|
|
309
|
+
* startTime: sessionStartTime,
|
|
310
|
+
* endTime: Date.now()
|
|
311
|
+
* },
|
|
312
|
+
* server: {
|
|
313
|
+
* reason: 'inactivity_timeout'
|
|
314
|
+
* }
|
|
315
|
+
* }
|
|
316
|
+
* });
|
|
317
|
+
* ```
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```typescript
|
|
321
|
+
* // In a session cleanup job
|
|
322
|
+
* async function cleanupExpiredSessions() {
|
|
323
|
+
* const expiredSessions = await getExpiredSessions();
|
|
324
|
+
*
|
|
325
|
+
* for (const session of expiredSessions) {
|
|
326
|
+
* analytics.pageLeave({
|
|
327
|
+
* sessionId: session.id,
|
|
328
|
+
* duration: session.duration,
|
|
329
|
+
* reason: 'expired'
|
|
330
|
+
* });
|
|
331
|
+
*
|
|
332
|
+
* await removeSession(session.id);
|
|
333
|
+
* }
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
18
337
|
pageLeave(properties?: Record<string, unknown>, options?: {
|
|
19
338
|
context?: EventContext;
|
|
20
339
|
}): void;
|
|
340
|
+
/**
|
|
341
|
+
* Shuts down all analytics providers and flushes pending events.
|
|
342
|
+
*
|
|
343
|
+
* This method is crucial for server environments, especially serverless functions,
|
|
344
|
+
* as it ensures all events are sent before the process terminates. Some providers
|
|
345
|
+
* batch events and need an explicit flush to send them.
|
|
346
|
+
*
|
|
347
|
+
* Always call this method before your server shuts down or before a serverless
|
|
348
|
+
* function completes execution.
|
|
349
|
+
*
|
|
350
|
+
* @returns Promise that resolves when all providers have been shut down
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```typescript
|
|
354
|
+
* // Basic shutdown
|
|
355
|
+
* await analytics.shutdown();
|
|
356
|
+
* ```
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```typescript
|
|
360
|
+
* // In a serverless function
|
|
361
|
+
* export async function handler(event, context) {
|
|
362
|
+
* const analytics = new ServerAnalytics({ providers: [] });
|
|
363
|
+
* analytics.initialize();
|
|
364
|
+
*
|
|
365
|
+
* try {
|
|
366
|
+
* // Process the event
|
|
367
|
+
* await processEvent(event);
|
|
368
|
+
*
|
|
369
|
+
* // Track completion
|
|
370
|
+
* await analytics.track('function_completed', {
|
|
371
|
+
* duration: Date.now() - startTime,
|
|
372
|
+
* success: true
|
|
373
|
+
* });
|
|
374
|
+
* } catch (error) {
|
|
375
|
+
* await analytics.track('function_failed', {
|
|
376
|
+
* error: error.message,
|
|
377
|
+
* duration: Date.now() - startTime
|
|
378
|
+
* });
|
|
379
|
+
* } finally {
|
|
380
|
+
* // Always shutdown to flush events
|
|
381
|
+
* await analytics.shutdown();
|
|
382
|
+
* }
|
|
383
|
+
*
|
|
384
|
+
* return { statusCode: 200 };
|
|
385
|
+
* }
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* ```typescript
|
|
390
|
+
* // In an Express.js server
|
|
391
|
+
* const server = app.listen(3000);
|
|
392
|
+
*
|
|
393
|
+
* // Graceful shutdown
|
|
394
|
+
* process.on('SIGTERM', async () => {
|
|
395
|
+
* console.log('Shutting down gracefully...');
|
|
396
|
+
*
|
|
397
|
+
* server.close(async () => {
|
|
398
|
+
* // Flush analytics events before exit
|
|
399
|
+
* await analytics.shutdown();
|
|
400
|
+
* process.exit(0);
|
|
401
|
+
* });
|
|
402
|
+
* });
|
|
403
|
+
* ```
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```typescript
|
|
407
|
+
* // With Vercel's waitUntil
|
|
408
|
+
* import { waitUntil } from '@vercel/functions';
|
|
409
|
+
*
|
|
410
|
+
* export default async function handler(req, res) {
|
|
411
|
+
* // Process request
|
|
412
|
+
* const result = await processRequest(req);
|
|
413
|
+
*
|
|
414
|
+
* // Track in background without blocking response
|
|
415
|
+
* waitUntil(
|
|
416
|
+
* analytics.track('api_request', { endpoint: req.url })
|
|
417
|
+
* .then(() => analytics.shutdown())
|
|
418
|
+
* );
|
|
419
|
+
*
|
|
420
|
+
* return res.json(result);
|
|
421
|
+
* }
|
|
422
|
+
* ```
|
|
423
|
+
*/
|
|
21
424
|
shutdown(): Promise<void>;
|
|
22
425
|
private getCategoryFromEventName;
|
|
23
426
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export type { EventCategory, BaseEvent, EventContext, AnalyticsProvider, AnalyticsConfig, } from './core/events/types.js';
|
|
2
2
|
export type { CreateEventDefinition, ExtractEventNames, ExtractEventPropertiesFromCollection, EventCollection, AnyEventName, AnyEventProperties, EventMapFromCollection, } from './core/events/index.js';
|
|
3
3
|
export { createAnalytics as createClientAnalytics, getAnalytics, track as trackClient, identify as identifyClient, pageView as pageViewClient, pageLeave as pageLeaveClient, reset as resetClient, type ClientAnalyticsConfig, } from './client.js';
|
|
4
|
-
export {
|
|
5
|
-
export { BaseAnalyticsProvider, PostHogClientProvider, PostHogServerProvider, type PostHogConfig, type PostHogOptions, } from './providers/index.js';
|
|
4
|
+
export { BaseAnalyticsProvider, PostHogClientProvider, type PostHogConfig, } from './providers/client.js';
|
|
6
5
|
export { BrowserAnalytics } from './adapters/client/browser-analytics.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
package/dist/client-CyxgEISv.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
var c = Object.defineProperty;
|
|
2
|
-
var u = (t, e, i) => e in t ? c(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i;
|
|
3
|
-
var s = (t, e, i) => u(t, typeof e != "symbol" ? e + "" : e, i);
|
|
4
|
-
import { i as h } from "./environment-Bnc8FqHv.js";
|
|
5
|
-
class p {
|
|
6
|
-
constructor(e) {
|
|
7
|
-
s(this, "providers", []);
|
|
8
|
-
s(this, "context", {});
|
|
9
|
-
s(this, "userId");
|
|
10
|
-
s(this, "sessionId");
|
|
11
|
-
s(this, "initialized", !1);
|
|
12
|
-
s(this, "initializePromise");
|
|
13
|
-
this.providers = e.providers, e.defaultContext && (this.context = { ...e.defaultContext }), this.sessionId = this.generateSessionId();
|
|
14
|
-
}
|
|
15
|
-
async initialize() {
|
|
16
|
-
if (h() && !this.initialized)
|
|
17
|
-
return this.initializePromise ? this.initializePromise : (this.initializePromise = this._doInitialize(), this.initializePromise);
|
|
18
|
-
}
|
|
19
|
-
async _doInitialize() {
|
|
20
|
-
const e = this.providers.map(
|
|
21
|
-
(i) => i.initialize()
|
|
22
|
-
);
|
|
23
|
-
await Promise.all(e), this.initialized = !0, this.updateContext({
|
|
24
|
-
page: {
|
|
25
|
-
path: window.location.pathname,
|
|
26
|
-
title: document.title,
|
|
27
|
-
referrer: document.referrer
|
|
28
|
-
},
|
|
29
|
-
device: {
|
|
30
|
-
type: this.getDeviceType(),
|
|
31
|
-
os: this.getOS(),
|
|
32
|
-
browser: this.getBrowser()
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
async ensureInitialized() {
|
|
37
|
-
!this.initialized && !this.initializePromise ? await this.initialize() : this.initializePromise && await this.initializePromise;
|
|
38
|
-
}
|
|
39
|
-
identify(e, i) {
|
|
40
|
-
this.userId = e, this.ensureInitialized().catch((r) => {
|
|
41
|
-
console.error("[Analytics] Failed to initialize during identify:", r);
|
|
42
|
-
});
|
|
43
|
-
for (const r of this.providers)
|
|
44
|
-
r.identify(e, i);
|
|
45
|
-
}
|
|
46
|
-
async track(e, i) {
|
|
47
|
-
await this.ensureInitialized();
|
|
48
|
-
const r = {
|
|
49
|
-
action: e,
|
|
50
|
-
category: this.getCategoryFromEventName(e),
|
|
51
|
-
properties: i,
|
|
52
|
-
timestamp: Date.now(),
|
|
53
|
-
userId: this.userId,
|
|
54
|
-
sessionId: this.sessionId
|
|
55
|
-
}, o = this.providers.map(async (d) => {
|
|
56
|
-
try {
|
|
57
|
-
await d.track(r, this.context);
|
|
58
|
-
} catch (l) {
|
|
59
|
-
console.error(
|
|
60
|
-
`[Analytics] Provider ${d.name} failed to track event:`,
|
|
61
|
-
l
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
await Promise.all(o);
|
|
66
|
-
}
|
|
67
|
-
pageView(e) {
|
|
68
|
-
this.ensureInitialized().catch((i) => {
|
|
69
|
-
console.error("[Analytics] Failed to initialize during pageView:", i);
|
|
70
|
-
}), this.updateContext({
|
|
71
|
-
page: {
|
|
72
|
-
path: window.location.pathname,
|
|
73
|
-
title: document.title,
|
|
74
|
-
referrer: document.referrer
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
for (const i of this.providers)
|
|
78
|
-
i.pageView(e, this.context);
|
|
79
|
-
}
|
|
80
|
-
pageLeave(e) {
|
|
81
|
-
this.ensureInitialized().catch((i) => {
|
|
82
|
-
console.error("[Analytics] Failed to initialize during pageLeave:", i);
|
|
83
|
-
});
|
|
84
|
-
for (const i of this.providers)
|
|
85
|
-
i.pageLeave && i.pageLeave(e, this.context);
|
|
86
|
-
}
|
|
87
|
-
reset() {
|
|
88
|
-
this.userId = void 0, this.sessionId = this.generateSessionId();
|
|
89
|
-
for (const e of this.providers)
|
|
90
|
-
e.reset();
|
|
91
|
-
}
|
|
92
|
-
updateContext(e) {
|
|
93
|
-
var i, r, o;
|
|
94
|
-
this.context = {
|
|
95
|
-
...this.context,
|
|
96
|
-
...e,
|
|
97
|
-
page: e.page ? {
|
|
98
|
-
path: e.page.path || ((i = this.context.page) == null ? void 0 : i.path) || window.location.pathname,
|
|
99
|
-
title: e.page.title || ((r = this.context.page) == null ? void 0 : r.title),
|
|
100
|
-
referrer: e.page.referrer || ((o = this.context.page) == null ? void 0 : o.referrer)
|
|
101
|
-
} : this.context.page,
|
|
102
|
-
device: {
|
|
103
|
-
...this.context.device,
|
|
104
|
-
...e.device
|
|
105
|
-
},
|
|
106
|
-
utm: {
|
|
107
|
-
...this.context.utm,
|
|
108
|
-
...e.utm
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
getCategoryFromEventName(e) {
|
|
113
|
-
const i = e.split("_");
|
|
114
|
-
return i.length > 1 && i[0] ? i[0] : "engagement";
|
|
115
|
-
}
|
|
116
|
-
generateSessionId() {
|
|
117
|
-
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
118
|
-
}
|
|
119
|
-
getDeviceType() {
|
|
120
|
-
const e = navigator.userAgent;
|
|
121
|
-
return /tablet|ipad|playbook|silk/i.test(e) ? "tablet" : /mobile|iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(
|
|
122
|
-
e
|
|
123
|
-
) ? "mobile" : "desktop";
|
|
124
|
-
}
|
|
125
|
-
getOS() {
|
|
126
|
-
const e = navigator.userAgent;
|
|
127
|
-
return e.indexOf("Win") !== -1 ? "Windows" : e.indexOf("Mac") !== -1 ? "macOS" : e.indexOf("Linux") !== -1 ? "Linux" : e.indexOf("Android") !== -1 ? "Android" : e.indexOf("iOS") !== -1 ? "iOS" : "Unknown";
|
|
128
|
-
}
|
|
129
|
-
getBrowser() {
|
|
130
|
-
const e = navigator.userAgent;
|
|
131
|
-
return e.indexOf("Chrome") !== -1 ? "Chrome" : e.indexOf("Safari") !== -1 ? "Safari" : e.indexOf("Firefox") !== -1 ? "Firefox" : e.indexOf("Edge") !== -1 ? "Edge" : "Unknown";
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
let n = null;
|
|
135
|
-
function m(t) {
|
|
136
|
-
if (n)
|
|
137
|
-
return console.warn("[Analytics] Already initialized"), n;
|
|
138
|
-
const e = {
|
|
139
|
-
providers: t.providers || [],
|
|
140
|
-
debug: t.debug,
|
|
141
|
-
enabled: t.enabled
|
|
142
|
-
};
|
|
143
|
-
return n = new p(
|
|
144
|
-
e
|
|
145
|
-
), n.initialize().catch((i) => {
|
|
146
|
-
console.error("[Analytics] Failed to initialize:", i);
|
|
147
|
-
}), n;
|
|
148
|
-
}
|
|
149
|
-
function a() {
|
|
150
|
-
if (!n)
|
|
151
|
-
throw new Error(
|
|
152
|
-
"[Analytics] Not initialized. Call createAnalytics() first."
|
|
153
|
-
);
|
|
154
|
-
return n;
|
|
155
|
-
}
|
|
156
|
-
function v(t, e) {
|
|
157
|
-
return a().track(t, e);
|
|
158
|
-
}
|
|
159
|
-
function y(t, e) {
|
|
160
|
-
a().identify(t, e);
|
|
161
|
-
}
|
|
162
|
-
function w(t) {
|
|
163
|
-
a().pageView(t);
|
|
164
|
-
}
|
|
165
|
-
function z(t) {
|
|
166
|
-
a().pageLeave(t);
|
|
167
|
-
}
|
|
168
|
-
function x() {
|
|
169
|
-
a().reset();
|
|
170
|
-
}
|
|
171
|
-
function A() {
|
|
172
|
-
n = null;
|
|
173
|
-
}
|
|
174
|
-
export {
|
|
175
|
-
p as B,
|
|
176
|
-
z as a,
|
|
177
|
-
A as b,
|
|
178
|
-
m as c,
|
|
179
|
-
a as g,
|
|
180
|
-
y as i,
|
|
181
|
-
w as p,
|
|
182
|
-
x as r,
|
|
183
|
-
v as t
|
|
184
|
-
};
|