@stacksee/analytics 0.3.4 → 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 +8 -7
- package/dist/index.js +10 -13
- package/dist/providers.js +53 -2583
- package/dist/server.js +421 -9
- package/dist/src/adapters/client/browser-analytics.d.ts +395 -1
- package/dist/src/adapters/server/server-analytics.d.ts +407 -1
- package/dist/src/client/index.d.ts +2 -2
- package/dist/src/client.d.ts +5 -1
- package/dist/src/core/events/types.d.ts +2 -1
- package/dist/src/index.d.ts +2 -3
- package/dist/src/providers/base.provider.d.ts +2 -1
- package/dist/src/providers/client.d.ts +3 -0
- package/dist/src/providers/index.d.ts +2 -1
- package/dist/src/providers/posthog/client.d.ts +5 -3
- package/dist/src/providers/posthog/server.d.ts +5 -3
- package/dist/src/server/index.d.ts +1 -1
- package/dist/test/mock-provider.d.ts +7 -2
- package/dist/test/providers.test.d.ts +1 -0
- package/dist/test/server.test.d.ts +1 -0
- package/package.json +3 -3
- package/readme.md +40 -2
- package/dist/client-bVe2QF_t.js +0 -173
- package/dist/module-BfXpy-Wp.js +0 -4198
- package/dist/src/providers/posthog/types.d.ts +0 -27
|
@@ -4,17 +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>;
|
|
15
|
-
|
|
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
|
+
*/
|
|
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
|
+
*/
|
|
337
|
+
pageLeave(properties?: Record<string, unknown>, options?: {
|
|
338
|
+
context?: EventContext;
|
|
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
|
+
*/
|
|
18
424
|
shutdown(): Promise<void>;
|
|
19
425
|
private getCategoryFromEventName;
|
|
20
426
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { createClientAnalytics, createAnalytics, getAnalytics, track, identify,
|
|
1
|
+
export { createClientAnalytics, createAnalytics, getAnalytics, track, identify, pageView, pageLeave, reset, type ClientAnalyticsConfig, } from '../client.js';
|
|
2
2
|
export { BrowserAnalytics } from '../adapters/client/browser-analytics.js';
|
|
3
3
|
export { PostHogClientProvider } from '../providers/posthog/client.js';
|
|
4
|
-
export type { PostHogConfig } from '
|
|
4
|
+
export type { PostHogConfig } from 'posthog-js';
|
|
5
5
|
export { BaseAnalyticsProvider } from '../providers/base.provider.js';
|
|
6
6
|
export type { EventCategory, BaseEvent, EventContext, AnalyticsProvider, AnalyticsConfig, } from '../core/events/types.js';
|
|
7
7
|
export type { CreateEventDefinition, ExtractEventNames, ExtractEventPropertiesFromCollection, EventCollection, AnyEventName, AnyEventProperties, } from '../core/events/index.js';
|
package/dist/src/client.d.ts
CHANGED
|
@@ -52,7 +52,11 @@ export declare function identify(userId: string, traits?: Record<string, unknown
|
|
|
52
52
|
/**
|
|
53
53
|
* Convenience function to track page views
|
|
54
54
|
*/
|
|
55
|
-
export declare function
|
|
55
|
+
export declare function pageView(properties?: Record<string, unknown>): void;
|
|
56
|
+
/**
|
|
57
|
+
* Convenience function to track page leave events
|
|
58
|
+
*/
|
|
59
|
+
export declare function pageLeave(properties?: Record<string, unknown>): void;
|
|
56
60
|
/**
|
|
57
61
|
* Convenience function to reset user session
|
|
58
62
|
*/
|
|
@@ -30,7 +30,8 @@ export interface AnalyticsProvider {
|
|
|
30
30
|
initialize(): Promise<void> | void;
|
|
31
31
|
identify(userId: string, traits?: Record<string, unknown>): Promise<void> | void;
|
|
32
32
|
track(event: BaseEvent, context?: EventContext): Promise<void> | void;
|
|
33
|
-
|
|
33
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void> | void;
|
|
34
|
+
pageLeave?(properties?: Record<string, unknown>, context?: EventContext): Promise<void> | void;
|
|
34
35
|
reset(): Promise<void> | void;
|
|
35
36
|
}
|
|
36
37
|
export interface AnalyticsConfig {
|
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
|
-
export { createAnalytics as createClientAnalytics, getAnalytics, track as trackClient, identify as identifyClient,
|
|
4
|
-
export {
|
|
5
|
-
export { BaseAnalyticsProvider, PostHogClientProvider, PostHogServerProvider, type PostHogConfig, } from './providers/index.js';
|
|
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 { BaseAnalyticsProvider, PostHogClientProvider, type PostHogConfig, } from './providers/client.js';
|
|
6
5
|
export { BrowserAnalytics } from './adapters/client/browser-analytics.js';
|
|
@@ -10,7 +10,8 @@ export declare abstract class BaseAnalyticsProvider implements AnalyticsProvider
|
|
|
10
10
|
abstract initialize(): Promise<void> | void;
|
|
11
11
|
abstract identify(userId: string, traits?: Record<string, unknown>): Promise<void> | void;
|
|
12
12
|
abstract track(event: BaseEvent, context?: EventContext): Promise<void> | void;
|
|
13
|
-
abstract
|
|
13
|
+
abstract pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void> | void;
|
|
14
|
+
pageLeave?(properties?: Record<string, unknown>, context?: EventContext): Promise<void> | void;
|
|
14
15
|
abstract reset(): Promise<void> | void;
|
|
15
16
|
protected log(message: string, data?: unknown): void;
|
|
16
17
|
protected isEnabled(): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { BaseAnalyticsProvider } from './base.provider.js';
|
|
2
2
|
export { PostHogClientProvider } from './posthog/client.js';
|
|
3
3
|
export { PostHogServerProvider } from './posthog/server.js';
|
|
4
|
-
export type { PostHogConfig } from '
|
|
4
|
+
export type { PostHogConfig } from 'posthog-js';
|
|
5
|
+
export type { PostHogOptions } from 'posthog-node';
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
2
|
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
-
import { PostHogConfig } from '
|
|
3
|
+
import { PostHogConfig } from 'posthog-js';
|
|
4
4
|
export declare class PostHogClientProvider extends BaseAnalyticsProvider {
|
|
5
5
|
name: string;
|
|
6
6
|
private posthog?;
|
|
7
7
|
private initialized;
|
|
8
8
|
private config;
|
|
9
|
-
constructor(config: PostHogConfig & {
|
|
9
|
+
constructor(config: Partial<PostHogConfig> & {
|
|
10
|
+
token: string;
|
|
10
11
|
debug?: boolean;
|
|
11
12
|
enabled?: boolean;
|
|
12
13
|
});
|
|
13
14
|
initialize(): Promise<void>;
|
|
14
15
|
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
15
16
|
track(event: BaseEvent, context?: EventContext): void;
|
|
16
|
-
|
|
17
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
18
|
+
pageLeave(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
17
19
|
reset(): void;
|
|
18
20
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { BaseEvent, EventContext } from '../../core/events/types.js';
|
|
2
2
|
import { BaseAnalyticsProvider } from '../base.provider.js';
|
|
3
|
-
import {
|
|
3
|
+
import { PostHogOptions } from 'posthog-node';
|
|
4
4
|
export declare class PostHogServerProvider extends BaseAnalyticsProvider {
|
|
5
5
|
name: string;
|
|
6
6
|
private client?;
|
|
7
7
|
private initialized;
|
|
8
8
|
private config;
|
|
9
|
-
constructor(config:
|
|
9
|
+
constructor(config: {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
} & PostHogOptions & {
|
|
10
12
|
debug?: boolean;
|
|
11
13
|
enabled?: boolean;
|
|
12
14
|
});
|
|
13
15
|
initialize(): void;
|
|
14
16
|
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
15
17
|
track(event: BaseEvent, context?: EventContext): void;
|
|
16
|
-
|
|
18
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
17
19
|
reset(): Promise<void>;
|
|
18
20
|
shutdown(): Promise<void>;
|
|
19
21
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { createServerAnalytics, ServerAnalytics, type ServerAnalyticsConfig, } from '../server.js';
|
|
2
2
|
export { PostHogServerProvider } from '../providers/posthog/server.js';
|
|
3
|
-
export type {
|
|
3
|
+
export type { PostHogOptions } from 'posthog-node';
|
|
4
4
|
export { BaseAnalyticsProvider } from '../providers/base.provider.js';
|
|
5
5
|
export type { EventCategory, BaseEvent, EventContext, AnalyticsProvider, AnalyticsConfig, } from '../core/events/types.js';
|
|
6
6
|
export type { CreateEventDefinition, ExtractEventNames, ExtractEventPropertiesFromCollection, EventCollection, AnyEventName, AnyEventProperties, } from '../core/events/index.js';
|
|
@@ -13,7 +13,11 @@ export declare class MockAnalyticsProvider extends BaseAnalyticsProvider {
|
|
|
13
13
|
event: BaseEvent;
|
|
14
14
|
context?: EventContext;
|
|
15
15
|
}>;
|
|
16
|
-
|
|
16
|
+
pageView: Array<{
|
|
17
|
+
properties?: Record<string, unknown>;
|
|
18
|
+
context?: EventContext;
|
|
19
|
+
}>;
|
|
20
|
+
pageLeave: Array<{
|
|
17
21
|
properties?: Record<string, unknown>;
|
|
18
22
|
context?: EventContext;
|
|
19
23
|
}>;
|
|
@@ -22,7 +26,8 @@ export declare class MockAnalyticsProvider extends BaseAnalyticsProvider {
|
|
|
22
26
|
initialize(): void;
|
|
23
27
|
identify(userId: string, traits?: Record<string, unknown>): void;
|
|
24
28
|
track(event: BaseEvent, context?: EventContext): void;
|
|
25
|
-
|
|
29
|
+
pageView(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
30
|
+
pageLeave(properties?: Record<string, unknown>, context?: EventContext): void;
|
|
26
31
|
reset(): void;
|
|
27
32
|
clearCalls(): void;
|
|
28
33
|
isInitialized(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksee/analytics",
|
|
3
|
-
"version": "0.3
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "A highly typed, provider-agnostic analytics library for TypeScript applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"vitest": "^2.0.3"
|
|
58
58
|
},
|
|
59
59
|
"optionalDependencies": {
|
|
60
|
-
"posthog-js": "^1.
|
|
61
|
-
"posthog-node": "^
|
|
60
|
+
"posthog-js": "^1.268.2",
|
|
61
|
+
"posthog-node": "^5.9.0"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
64
|
"pnpm": ">=9.0.0",
|
package/readme.md
CHANGED
|
@@ -445,6 +445,42 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
445
445
|
};
|
|
446
446
|
```
|
|
447
447
|
|
|
448
|
+
#### Note for SvelteKit Users: Navigation Tracking
|
|
449
|
+
|
|
450
|
+
If you're using SvelteKit and want to track page views and page leaves automatically with PostHog (as recommended in their documentation), add this to your root layout:
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
// src/app.html or src/routes/+layout.svelte
|
|
454
|
+
<script>
|
|
455
|
+
import { pageView, pageLeave } from '@stacksee/analytics/client';
|
|
456
|
+
import { beforeNavigate, afterNavigate } from '$app/navigation';
|
|
457
|
+
import { browser } from '$app/environment';
|
|
458
|
+
|
|
459
|
+
let { children } = $props():
|
|
460
|
+
|
|
461
|
+
// Only set up navigation tracking in the browser
|
|
462
|
+
if (browser) {
|
|
463
|
+
beforeNavigate(() => {
|
|
464
|
+
pageLeave();
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
afterNavigate(() => {
|
|
468
|
+
pageView();
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
</script>
|
|
472
|
+
|
|
473
|
+
<main>
|
|
474
|
+
{@render children()}
|
|
475
|
+
</main>
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
This automatically tracks:
|
|
479
|
+
- **Page leaves** before navigation (`$pageleave` events in PostHog)
|
|
480
|
+
- **Page views** after navigation (`$pageview` events in PostHog)
|
|
481
|
+
|
|
482
|
+
The tracking is framework-agnostic, so you can use similar patterns with Next.js router events, Vue Router hooks, or any other navigation system.
|
|
483
|
+
|
|
448
484
|
### Event Categories
|
|
449
485
|
|
|
450
486
|
Event categories help organize your analytics data. The SDK provides predefined categories with TypeScript autocomplete:
|
|
@@ -759,7 +795,8 @@ const analytics = createClientAnalytics<typeof AppEvents>({
|
|
|
759
795
|
#### `BrowserAnalytics<TEventMap>`
|
|
760
796
|
- `track(eventName, properties): Promise<void>` - Track an event with type-safe event names and properties
|
|
761
797
|
- `identify(userId, traits)` - Identify a user
|
|
762
|
-
- `
|
|
798
|
+
- `pageView(properties)` - Track a page view
|
|
799
|
+
- `pageLeave(properties)` - Track a page leave event
|
|
763
800
|
- `reset()` - Reset user session
|
|
764
801
|
- `updateContext(context)` - Update event context
|
|
765
802
|
|
|
@@ -784,7 +821,8 @@ const analytics = createServerAnalytics<AppEvents>({
|
|
|
784
821
|
#### `ServerAnalytics<TEventMap>`
|
|
785
822
|
- `track(eventName, properties, options): Promise<void>` - Track an event with type-safe event names and properties
|
|
786
823
|
- `identify(userId, traits)` - Identify a user
|
|
787
|
-
- `
|
|
824
|
+
- `pageView(properties, options)` - Track a page view
|
|
825
|
+
- `pageLeave(properties, options)` - Track a page leave event
|
|
788
826
|
- `shutdown()` - Flush pending events and cleanup
|
|
789
827
|
|
|
790
828
|
### Type Helpers
|