@stacksee/analytics 0.2.2 → 0.3.2

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/server.js CHANGED
@@ -69,7 +69,9 @@ function v(r) {
69
69
  providers: r.providers || [],
70
70
  debug: r.debug,
71
71
  enabled: r.enabled
72
- }, t = new u(e);
72
+ }, t = new u(
73
+ e
74
+ );
73
75
  return t.initialize(), t;
74
76
  }
75
77
  export {
@@ -1,6 +1,6 @@
1
- import { AnyEventName, AnyEventProperties } from '../../core/events/index.js';
2
1
  import { AnalyticsConfig, EventContext } from '../../core/events/types.js';
3
- export declare class BrowserAnalytics<TEventName extends string = AnyEventName, TEventProperties extends Record<string, unknown> = AnyEventProperties> {
2
+ type DefaultEventMap = Record<string, Record<string, unknown>>;
3
+ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = DefaultEventMap> {
4
4
  private providers;
5
5
  private context;
6
6
  private userId?;
@@ -12,7 +12,7 @@ export declare class BrowserAnalytics<TEventName extends string = AnyEventName,
12
12
  private _doInitialize;
13
13
  private ensureInitialized;
14
14
  identify(userId: string, traits?: Record<string, unknown>): void;
15
- track(eventName: TEventName, properties: TEventProperties): Promise<void>;
15
+ track<TEventName extends keyof TEventMap & string>(eventName: TEventName, properties: TEventMap[TEventName]): Promise<void>;
16
16
  page(properties?: Record<string, unknown>): void;
17
17
  reset(): void;
18
18
  updateContext(context: Partial<EventContext>): void;
@@ -22,3 +22,4 @@ export declare class BrowserAnalytics<TEventName extends string = AnyEventName,
22
22
  private getOS;
23
23
  private getBrowser;
24
24
  }
25
+ export {};
@@ -1,13 +1,13 @@
1
- import { AnyEventName, AnyEventProperties } from '../../core/events/index.js';
2
1
  import { AnalyticsConfig, EventContext } from '../../core/events/types.js';
3
- export declare class ServerAnalytics<TEventName extends string = AnyEventName, TEventProperties extends Record<string, unknown> = AnyEventProperties> {
2
+ type DefaultEventMap = Record<string, Record<string, unknown>>;
3
+ export declare class ServerAnalytics<TEventMap extends DefaultEventMap = DefaultEventMap> {
4
4
  private providers;
5
5
  private config;
6
6
  private initialized;
7
7
  constructor(config: AnalyticsConfig);
8
8
  initialize(): void;
9
9
  identify(userId: string, traits?: Record<string, unknown>): void;
10
- track(eventName: TEventName, properties: TEventProperties, options?: {
10
+ track<TEventName extends keyof TEventMap & string>(eventName: TEventName, properties: TEventMap[TEventName], options?: {
11
11
  userId?: string;
12
12
  sessionId?: string;
13
13
  context?: EventContext;
@@ -18,3 +18,4 @@ export declare class ServerAnalytics<TEventName extends string = AnyEventName, T
18
18
  shutdown(): Promise<void>;
19
19
  private getCategoryFromEventName;
20
20
  }
21
+ export {};
@@ -1,5 +1,14 @@
1
1
  import { BrowserAnalytics } from './adapters/client/browser-analytics.js';
2
2
  import { AnalyticsProvider } from './core/events/types.js';
3
+ import { EventCollection } from './core/events/index.js';
4
+ type DefaultEventMap = Record<string, Record<string, unknown>>;
5
+ type EventMapFromCollection<T> = T extends EventCollection<infer Events> ? {
6
+ [K in keyof Events as Events[K] extends {
7
+ name: infer N;
8
+ } ? N extends string ? N : never : never]: Events[K] extends {
9
+ properties: infer P;
10
+ } ? P : never;
11
+ } : never;
3
12
  export interface ClientAnalyticsConfig {
4
13
  providers?: AnalyticsProvider[];
5
14
  debug?: boolean;
@@ -12,8 +21,9 @@ export interface ClientAnalyticsConfig {
12
21
  * ```typescript
13
22
  * import { createClientAnalytics } from '@stacksee/analytics/client';
14
23
  * import { PostHogClientProvider } from '@stacksee/analytics/providers/posthog';
24
+ * import { AppEvents } from './events';
15
25
  *
16
- * const analytics = createClientAnalytics({
26
+ * const analytics = createClientAnalytics<typeof AppEvents>({
17
27
  * providers: [
18
28
  * new PostHogClientProvider({
19
29
  * apiKey: 'your-api-key',
@@ -24,16 +34,20 @@ export interface ClientAnalyticsConfig {
24
34
  * enabled: true
25
35
  * });
26
36
  *
27
- * // Optional: explicitly initialize (otherwise happens on first track/identify/page call)
28
- * await analytics.initialize();
37
+ * // Now event names and properties are fully typed!
38
+ * analytics.track('user_signed_up', {
39
+ * userId: 'user-123',
40
+ * email: 'user@example.com',
41
+ * plan: 'pro'
42
+ * });
29
43
  * ```
30
44
  */
31
- export declare function createClientAnalytics(config: ClientAnalyticsConfig): BrowserAnalytics;
45
+ export declare function createClientAnalytics<TEvents = never>(config: ClientAnalyticsConfig): BrowserAnalytics<EventMapFromCollection<TEvents>>;
32
46
  export { createClientAnalytics as createAnalytics };
33
47
  /**
34
48
  * Get the current analytics instance
35
49
  */
36
- export declare function getAnalytics(): BrowserAnalytics;
50
+ export declare function getAnalytics(): BrowserAnalytics<DefaultEventMap>;
37
51
  /**
38
52
  * Convenience function to track events
39
53
  */
@@ -19,7 +19,7 @@ export interface EventContext {
19
19
  os?: string;
20
20
  browser?: string;
21
21
  };
22
- campaign?: {
22
+ utm?: {
23
23
  source?: string;
24
24
  medium?: string;
25
25
  name?: string;
@@ -1,5 +1,13 @@
1
1
  import { ServerAnalytics } from './adapters/server/server-analytics.js';
2
2
  import { AnalyticsProvider } from './core/events/types.js';
3
+ import { EventCollection } from './core/events/index.js';
4
+ type EventMapFromCollection<T> = T extends EventCollection<infer Events> ? {
5
+ [K in keyof Events as Events[K] extends {
6
+ name: infer N;
7
+ } ? N extends string ? N : never : never]: Events[K] extends {
8
+ properties: infer P;
9
+ } ? P : never;
10
+ } : never;
3
11
  export interface ServerAnalyticsConfig {
4
12
  providers?: AnalyticsProvider[];
5
13
  debug?: boolean;
@@ -12,8 +20,9 @@ export interface ServerAnalyticsConfig {
12
20
  * ```typescript
13
21
  * import { createServerAnalytics } from '@stacksee/analytics/server';
14
22
  * import { PostHogServerProvider } from '@stacksee/analytics/providers/posthog';
23
+ * import { AppEvents } from './events';
15
24
  *
16
- * const analytics = createServerAnalytics({
25
+ * const analytics = createServerAnalytics<typeof AppEvents>({
17
26
  * providers: [
18
27
  * new PostHogServerProvider({
19
28
  * apiKey: process.env.POSTHOG_API_KEY,
@@ -23,7 +32,14 @@ export interface ServerAnalyticsConfig {
23
32
  * debug: true,
24
33
  * enabled: true
25
34
  * });
35
+ *
36
+ * // Now event names and properties are fully typed!
37
+ * await analytics.track('user_signed_up', {
38
+ * userId: 'user-123',
39
+ * email: 'user@example.com',
40
+ * plan: 'pro'
41
+ * }, { userId: 'user-123' });
26
42
  * ```
27
43
  */
28
- export declare function createServerAnalytics(config: ServerAnalyticsConfig): ServerAnalytics;
44
+ export declare function createServerAnalytics<TEvents = never>(config: ServerAnalyticsConfig): ServerAnalytics<EventMapFromCollection<TEvents>>;
29
45
  export { ServerAnalytics };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacksee/analytics",
3
- "version": "0.2.2",
3
+ "version": "0.3.2",
4
4
  "description": "A highly typed, provider-agnostic analytics library for TypeScript applications",
5
5
  "type": "module",
6
6
  "exports": {
@@ -15,6 +15,10 @@
15
15
  "./server": {
16
16
  "types": "./dist/server.d.ts",
17
17
  "import": "./dist/server.js"
18
+ },
19
+ "./providers": {
20
+ "types": "./dist/providers.d.ts",
21
+ "import": "./dist/providers.js"
18
22
  }
19
23
  },
20
24
  "main": "./dist/index.js",
package/readme.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  A highly typed, provider-agnostic analytics library for TypeScript applications. Works seamlessly on both client and server sides with full type safety for your custom events.
4
4
 
5
+ ## Table of Contents
6
+
7
+ - [Features](#features)
8
+ - [Installation](#installation)
9
+ - [Quick Start](#quick-start)
10
+ - [1. Define Your Events](#1-define-your-events)
11
+ - [2. Client-Side Usage](#2-client-side-usage)
12
+ - [3. Server-Side Usage](#3-server-side-usage)
13
+ - [Async Tracking](#async-tracking-when-to-await-vs-fire-and-forget)
14
+ - [Fire-and-forget (Client-side typical usage)](#fire-and-forget-client-side-typical-usage)
15
+ - [Await for critical events (Server-side typical usage)](#await-for-critical-events-server-side-typical-usage)
16
+ - [Error handling](#error-handling)
17
+ - [Best practices](#best-practices)
18
+ - [A complete example](#a-complete-example)
19
+ - [Advanced Usage](#advanced-usage)
20
+ - [Creating a Typed Analytics Service](#creating-a-typed-analytics-service)
21
+ - [Event Categories](#event-categories)
22
+ - [Adding Custom Providers](#adding-custom-providers)
23
+ - [Client-Only and Server-Only Providers](#client-only-and-server-only-providers)
24
+ - [Using Multiple Providers](#using-multiple-providers)
25
+ - [Server Deployments and waitUntil](#server-deployments-and-waituntil)
26
+ - [Vercel Functions](#vercel-functions)
27
+ - [Cloudflare Workers](#cloudflare-workers)
28
+ - [Netlify Functions](#netlify-functions)
29
+ - [API Reference](#api-reference)
30
+ - [Client API](#client-api)
31
+ - [Server API](#server-api)
32
+ - [Type Helpers](#type-helpers)
33
+ - [Best Practices](#best-practices)
34
+ - [Contributing](#contributing)
35
+ - [License](#license)
36
+
5
37
  ## Features
6
38
 
7
39
  - 🎯 **Type-safe events**: Define your own strongly typed events with full IntelliSense support
@@ -30,8 +62,7 @@ Create strongly typed events specific to your application:
30
62
  ```typescript
31
63
  import { CreateEventDefinition, EventCollection } from '@stacksee/analytics';
32
64
 
33
- // Define your event types
34
- export const AppEvents = {
65
+ export const appEvents = {
35
66
  userSignedUp: {
36
67
  name: 'user_signed_up',
37
68
  category: 'user',
@@ -54,9 +85,10 @@ export const AppEvents = {
54
85
  }
55
86
  } as const satisfies EventCollection<Record<string, CreateEventDefinition<string>>>;
56
87
 
57
- // Extract types for use in your app
58
- export type AppEventName = keyof typeof AppEvents;
59
- export type AppEventProperties<T extends AppEventName> = typeof AppEvents[T]['properties'];
88
+ // Optionally extract types for use in your app
89
+ export type AppEvents = typeof appEvents;
90
+ export type AppEventName = keyof typeof appEvents;
91
+ export type AppEventProperties<T extends AppEventName> = typeof appEvents[T]['properties'];
60
92
  ```
61
93
 
62
94
  Tip: If you have a lot of events, you can also divide your events into multiple files, then export them as a single object.
@@ -66,10 +98,11 @@ Tip: If you have a lot of events, you can also divide your events into multiple
66
98
  ```typescript
67
99
  import { createClientAnalytics } from '@stacksee/analytics/client';
68
100
  import { PostHogClientProvider } from '@stacksee/analytics/providers/posthog';
69
- import { AppEvents } from './events';
101
+ import type { AppEvents } from './events';
70
102
 
71
103
  // Initialize analytics with providers as plugins
72
- const analytics = createClientAnalytics({
104
+ // Pass your event collection as a type parameter for full type safety
105
+ const analytics = createClientAnalytics<AppEvents>({
73
106
  providers: [
74
107
  new PostHogClientProvider({
75
108
  apiKey: 'your-posthog-api-key',
@@ -81,20 +114,18 @@ const analytics = createClientAnalytics({
81
114
  enabled: true
82
115
  });
83
116
 
84
- // Track events with full type safety
85
- analytics.track(AppEvents.pageViewed.name, {
86
- path: '/dashboard',
87
- title: 'Dashboard',
88
- referrer: document.referrer
89
- });
90
-
91
- analytics.track(AppEvents.userSignedUp.name, {
117
+ // Track events with full type safety - event names and properties are typed!
118
+ analytics.track('user_signed_up', {
92
119
  userId: 'user-123',
93
120
  email: 'user@example.com',
94
121
  plan: 'pro',
95
122
  referralSource: 'google'
96
123
  });
97
124
 
125
+ // TypeScript will error if you use wrong event names or properties
126
+ // analytics.track('wrong_event', {}); // ❌ Error: Argument of type '"wrong_event"' is not assignable
127
+ // analytics.track('user_signed_up', { wrongProp: 'value' }); // ❌ Error: Object literal may only specify known properties
128
+
98
129
  // Identify users
99
130
  analytics.identify('user-123', {
100
131
  email: 'user@example.com',
@@ -108,10 +139,11 @@ analytics.identify('user-123', {
108
139
  ```typescript
109
140
  import { createServerAnalytics } from '@stacksee/analytics/server';
110
141
  import { PostHogServerProvider } from '@stacksee/analytics/providers/posthog';
111
- import { AppEvents } from './events';
142
+ import type { AppEvents } from './events';
112
143
 
113
144
  // Create analytics instance with providers as plugins
114
- const analytics = createServerAnalytics({
145
+ // Pass your event collection as a type parameter for full type safety
146
+ const analytics = createServerAnalytics<AppEvents>({
115
147
  providers: [
116
148
  new PostHogServerProvider({
117
149
  apiKey: process.env.POSTHOG_API_KEY,
@@ -123,8 +155,8 @@ const analytics = createServerAnalytics({
123
155
  enabled: true
124
156
  });
125
157
 
126
- // Track events - now returns a Promise
127
- await analytics.track(AppEvents.featureUsed.name, {
158
+ // Track events - now returns a Promise with full type safety
159
+ await analytics.track('feature_used', {
128
160
  featureName: 'export-data',
129
161
  userId: 'user-123',
130
162
  duration: 1500
@@ -240,7 +272,7 @@ import { PostHogClientProvider } from '@stacksee/analytics/providers/posthog';
240
272
  import { PUBLIC_POSTHOG_API_KEY, PUBLIC_POSTHOG_HOST } from '$env/static/public';
241
273
 
242
274
  // Define your events for the waitlist
243
- export const AppEvents = {
275
+ export const appEvents = {
244
276
  waitlistJoined: {
245
277
  name: 'waitlist_joined',
246
278
  category: 'user',
@@ -260,11 +292,11 @@ export const AppEvents = {
260
292
  } as const;
261
293
 
262
294
  // Client-side analytics instance
263
- export const clientAnalytics = createClientAnalytics({
295
+ export const clientAnalytics = createClientAnalytics<AppEvents>({
264
296
  providers: [
265
297
  new PostHogClientProvider({
266
- apiKey: import.meta.env.VITE_POSTHOG_KEY, // Ensure VITE_POSTHOG_KEY is in your .env file
267
- host: 'https://app.posthog.com'
298
+ apiKey: PUBLIC_POSTHOG_API_KEY,
299
+ host: PUBLIC_POSTHOG_HOST
268
300
  })
269
301
  ],
270
302
  debug: import.meta.env.DEV
@@ -278,21 +310,21 @@ import { PostHogServerProvider } from '@stacksee/analytics/providers/posthog';
278
310
  import { AppEvents } from '$lib/config/analytics'; // Import AppEvents
279
311
  import { PUBLIC_POSTHOG_API_KEY, PUBLIC_POSTHOG_HOST } from '$env/static/public';
280
312
 
281
- export const serverAnalytics = createServerAnalytics({
313
+ export const serverAnalytics = createServerAnalytics<AppEvents>({
282
314
  providers: [
283
315
  new PostHogServerProvider({
284
316
  apiKey: PUBLIC_POSTHOG_API_KEY,
285
317
  host: PUBLIC_POSTHOG_HOST
286
318
  })
287
319
  ],
288
- debug: process.env.NODE_ENV === 'development'
320
+ debug: import.meta.env.DEV
289
321
  });
290
322
  ```
291
323
 
292
324
  ```svelte
293
325
  <!-- src/routes/join-waitlist/+page.svelte -->
294
326
  <script lang="ts">
295
- import { clientAnalytics, AppEvents } from '$lib/config/analytics';
327
+ import { clientAnalytics } from '$lib/config/analytics';
296
328
 
297
329
  let email = $state('');
298
330
  let loading = $state(false);
@@ -305,7 +337,7 @@ export const serverAnalytics = createServerAnalytics({
305
337
 
306
338
  try {
307
339
  // Track waitlist joined event on the client
308
- clientAnalytics.track(AppEvents.waitlistJoined.name, {
340
+ clientAnalytics.track('waitlist_joined', {
309
341
  email,
310
342
  source: 'waitlist_page_form'
311
343
  });
@@ -360,7 +392,6 @@ export const serverAnalytics = createServerAnalytics({
360
392
  ```typescript
361
393
  // src/routes/api/join-waitlist/+server.ts
362
394
  import { serverAnalytics } from '$lib/server/analytics';
363
- import { AppEvents } from '$lib/config/analytics'; // Import AppEvents
364
395
  import { json, type RequestHandler } from '@sveltejs/kit';
365
396
 
366
397
  async function approveUserForWaitlist(email: string): Promise<{ userId: string }> {
@@ -382,7 +413,7 @@ export const POST: RequestHandler = async ({ request }) => {
382
413
 
383
414
  const { userId } = await approveUserForWaitlist(email);
384
415
 
385
- serverAnalytics.track(AppEvents.waitlistApproved.name, {
416
+ serverAnalytics.track('waitlist_approved', {
386
417
  userId,
387
418
  email
388
419
  }, {
@@ -414,55 +445,6 @@ export const POST: RequestHandler = async ({ request }) => {
414
445
  };
415
446
  ```
416
447
 
417
- ## Advanced Usage
418
-
419
- ### Creating a Typed Analytics Service
420
-
421
- For better type safety across your application, create a typed wrapper:
422
-
423
- ```typescript
424
- import {
425
- BrowserAnalytics,
426
- ServerAnalytics,
427
- ExtractEventNames,
428
- ExtractEventPropertiesFromCollection
429
- } from '@stacksee/analytics';
430
- import { AppEvents } from './events';
431
-
432
- // Type aliases for your app
433
- type AppEventName = ExtractEventNames<typeof AppEvents>;
434
- type AppEventProps<T extends AppEventName> = ExtractEventPropertiesFromCollection<typeof AppEvents, T>;
435
-
436
- // Client-side typed wrapper
437
- export class AppAnalytics {
438
- constructor(private analytics: BrowserAnalytics) {}
439
-
440
- track<T extends AppEventName>(
441
- eventName: T,
442
- properties: AppEventProps<T>
443
- ): Promise<void> {
444
- return this.analytics.track(eventName, properties);
445
- }
446
-
447
- // ... other methods
448
- }
449
-
450
- // Server-side typed wrapper
451
- export class ServerAppAnalytics {
452
- constructor(private analytics: ServerAnalytics) {}
453
-
454
- track<T extends AppEventName>(
455
- eventName: T,
456
- properties: AppEventProps<T>,
457
- options?: { userId?: string; sessionId?: string }
458
- ): Promise<void> {
459
- return this.analytics.track(eventName, properties, options);
460
- }
461
-
462
- // ... other methods
463
- }
464
- ```
465
-
466
448
  ### Event Categories
467
449
 
468
450
  Event categories help organize your analytics data. The SDK provides predefined categories with TypeScript autocomplete:
@@ -478,7 +460,7 @@ Event categories help organize your analytics data. The SDK provides predefined
478
460
  You can also use **custom categories** for your specific needs:
479
461
 
480
462
  ```typescript
481
- export const AppEvents = {
463
+ export const appEvents = {
482
464
  aiResponse: {
483
465
  name: 'ai_response_generated',
484
466
  category: 'ai', // Custom category
@@ -536,7 +518,7 @@ export class GoogleAnalyticsProvider extends BaseAnalyticsProvider {
536
518
  Then use it as a plugin in your configuration:
537
519
 
538
520
  ```typescript
539
- const analytics = await createClientAnalytics({
521
+ const analytics = await createClientAnalytics<typeof AppEvents>({
540
522
  providers: [
541
523
  new PostHogClientProvider({ apiKey: 'xxx' }),
542
524
  new GoogleAnalyticsProvider({ measurementId: 'xxx' })
@@ -588,7 +570,7 @@ Then use the appropriate provider based on your environment:
588
570
  import { createClientAnalytics } from '@stacksee/analytics/client';
589
571
  import { MixpanelClientProvider } from './providers/mixpanel-client';
590
572
 
591
- const clientAnalytics = createClientAnalytics({
573
+ const clientAnalytics = createClientAnalytics<typeof AppEvents>({
592
574
  providers: [
593
575
  new MixpanelClientProvider({ projectToken: 'xxx' })
594
576
  ]
@@ -598,7 +580,7 @@ const clientAnalytics = createClientAnalytics({
598
580
  import { createServerAnalytics } from '@stacksee/analytics/server';
599
581
  import { MixpanelServerProvider } from './providers/mixpanel-server';
600
582
 
601
- const serverAnalytics = createServerAnalytics({
583
+ const serverAnalytics = createServerAnalytics<typeof AppEvents>({
602
584
  providers: [
603
585
  new MixpanelServerProvider({
604
586
  projectToken: 'xxx',
@@ -625,7 +607,7 @@ import { PostHogClientProvider } from '@stacksee/analytics/providers/posthog';
625
607
  import { GoogleAnalyticsProvider } from './providers/google-analytics';
626
608
  import { MixpanelProvider } from './providers/mixpanel';
627
609
 
628
- const analytics = createClientAnalytics({
610
+ const analytics = createClientAnalytics<typeof AppEvents>({
629
611
  providers: [
630
612
  // PostHog for product analytics
631
613
  new PostHogClientProvider({
@@ -666,7 +648,7 @@ Vercel provides a `waitUntil` API that allows you to continue processing after t
666
648
  import { waitUntil } from '@vercel/functions';
667
649
 
668
650
  export default async function handler(req, res) {
669
- const analytics = createServerAnalytics({
651
+ const analytics = createServerAnalytics<typeof AppEvents>({
670
652
  providers: [new PostHogServerProvider({ apiKey: process.env.POSTHOG_API_KEY })]
671
653
  });
672
654
 
@@ -695,7 +677,7 @@ Cloudflare Workers provides a `waitUntil` method on the execution context:
695
677
  ```typescript
696
678
  export default {
697
679
  async fetch(request, env, ctx) {
698
- const analytics = createServerAnalytics({
680
+ const analytics = createServerAnalytics<typeof AppEvents>({
699
681
  providers: [new PostHogServerProvider({ apiKey: env.POSTHOG_API_KEY })]
700
682
  });
701
683
 
@@ -724,7 +706,7 @@ Netlify Functions also support `waitUntil` through their context object:
724
706
 
725
707
  ```typescript
726
708
  export async function handler(event, context) {
727
- const analytics = createServerAnalytics({
709
+ const analytics = createServerAnalytics<AppEvents>({
728
710
  providers: [new PostHogServerProvider({ apiKey: process.env.POSTHOG_API_KEY })]
729
711
  });
730
712
 
@@ -758,15 +740,24 @@ export async function handler(event, context) {
758
740
 
759
741
  ### Client API
760
742
 
761
- #### `createClientAnalytics(config)`
762
- Initialize analytics for browser environment.
743
+ #### `createClientAnalytics<TEvents>(config)`
744
+ Initialize analytics for browser environment with optional type-safe events.
763
745
 
746
+ - `TEvents` - (optional) Your event collection type for full type safety
764
747
  - `config.providers` - Array of analytics provider instances
765
748
  - `config.debug` - Enable debug logging
766
749
  - `config.enabled` - Enable/disable analytics
767
750
 
768
- #### `BrowserAnalytics`
769
- - `track(eventName, properties): Promise<void>` - Track an event (returns a promise)
751
+ ```typescript
752
+ const analytics = createClientAnalytics<typeof AppEvents>({
753
+ providers: [/* ... */],
754
+ debug: true,
755
+ enabled: true
756
+ });
757
+ ```
758
+
759
+ #### `BrowserAnalytics<TEventMap>`
760
+ - `track(eventName, properties): Promise<void>` - Track an event with type-safe event names and properties
770
761
  - `identify(userId, traits)` - Identify a user
771
762
  - `page(properties)` - Track a page view
772
763
  - `reset()` - Reset user session
@@ -774,15 +765,24 @@ Initialize analytics for browser environment.
774
765
 
775
766
  ### Server API
776
767
 
777
- #### `createServerAnalytics(config)`
778
- Create analytics instance for server environment.
768
+ #### `createServerAnalytics<TEvents>(config)`
769
+ Create analytics instance for server environment with optional type-safe events.
779
770
 
771
+ - `TEvents` - (optional) Your event collection type for full type safety
780
772
  - `config.providers` - Array of analytics provider instances
781
773
  - `config.debug` - Enable debug logging
782
774
  - `config.enabled` - Enable/disable analytics
783
775
 
784
- #### `ServerAnalytics`
785
- - `track(eventName, properties, options): Promise<void>` - Track an event with optional context (returns a promise)
776
+ ```typescript
777
+ const analytics = createServerAnalytics<AppEvents>({
778
+ providers: [/* ... */],
779
+ debug: true,
780
+ enabled: true
781
+ });
782
+ ```
783
+
784
+ #### `ServerAnalytics<TEventMap>`
785
+ - `track(eventName, properties, options): Promise<void>` - Track an event with type-safe event names and properties
786
786
  - `identify(userId, traits)` - Identify a user
787
787
  - `page(properties, options)` - Track a page view
788
788
  - `shutdown()` - Flush pending events and cleanup