@stacksee/analytics 0.4.6 → 0.7.0

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.
@@ -0,0 +1,28 @@
1
+ var u = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
2
+ function f(e) {
3
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
4
+ }
5
+ function l(e) {
6
+ if (Object.prototype.hasOwnProperty.call(e, "__esModule")) return e;
7
+ var r = e.default;
8
+ if (typeof r == "function") {
9
+ var t = function o() {
10
+ return this instanceof o ? Reflect.construct(r, arguments, this.constructor) : r.apply(this, arguments);
11
+ };
12
+ t.prototype = r.prototype;
13
+ } else t = {};
14
+ return Object.defineProperty(t, "__esModule", { value: !0 }), Object.keys(e).forEach(function(o) {
15
+ var n = Object.getOwnPropertyDescriptor(e, o);
16
+ Object.defineProperty(t, o, n.get ? n : {
17
+ enumerable: !0,
18
+ get: function() {
19
+ return e[o];
20
+ }
21
+ });
22
+ }), t;
23
+ }
24
+ export {
25
+ l as a,
26
+ u as c,
27
+ f as g
28
+ };
@@ -1,10 +1,11 @@
1
1
  import { AnalyticsConfig, EventContext } from '../../core/events/types.js';
2
2
  type DefaultEventMap = Record<string, Record<string, unknown>>;
3
- export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = DefaultEventMap> {
3
+ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = DefaultEventMap, TUserTraits extends Record<string, unknown> = Record<string, unknown>> {
4
4
  private providers;
5
5
  private context;
6
6
  private userId?;
7
7
  private sessionId?;
8
+ private userTraits?;
8
9
  private initialized;
9
10
  private initializePromise?;
10
11
  /**
@@ -78,11 +79,16 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
78
79
  * sets user properties. This method should be called when a user logs in
79
80
  * or when you want to associate events with a known user.
80
81
  *
82
+ * **User Context (New):** User data (userId, email, traits) is automatically stored
83
+ * and included in all subsequent `track()` calls. This makes it easy for providers
84
+ * like Loops, Customer.io, or Intercom to access user information without passing
85
+ * it manually each time. The data is cleared when `reset()` is called (e.g., on logout).
86
+ *
81
87
  * The method automatically ensures initialization but doesn't block execution
82
88
  * if initialization is still in progress.
83
89
  *
84
90
  * @param userId Unique identifier for the user (e.g., database ID, email)
85
- * @param traits Optional user properties and characteristics
91
+ * @param traits Optional user properties and characteristics (email, name, plan, etc.)
86
92
  *
87
93
  * @example
88
94
  * ```typescript
@@ -92,7 +98,7 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
92
98
  *
93
99
  * @example
94
100
  * ```typescript
95
- * // Identify with user traits
101
+ * // Identify with user traits (recommended - enables email-based providers)
96
102
  * analytics.identify('user-123', {
97
103
  * email: 'john@example.com',
98
104
  * name: 'John Doe',
@@ -103,6 +109,10 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
103
109
  * notifications: false
104
110
  * }
105
111
  * });
112
+ *
113
+ * // Now all subsequent track() calls automatically include user context
114
+ * analytics.track('button_clicked', { buttonId: 'checkout' });
115
+ * // Providers receive: context.user = { userId: 'user-123', email: 'john@example.com', traits: {...} }
106
116
  * ```
107
117
  *
108
118
  * @example
@@ -111,15 +121,25 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
111
121
  * async function handleLogin(email: string, password: string) {
112
122
  * const user = await login(email, password);
113
123
  *
124
+ * // Identify user with full traits
114
125
  * analytics.identify(user.id, {
115
126
  * email: user.email,
116
127
  * name: user.name,
128
+ * plan: user.plan,
129
+ * company: user.company,
117
130
  * lastLogin: new Date().toISOString()
118
131
  * });
132
+ *
133
+ * // All subsequent events now include this user context automatically
134
+ * }
135
+ *
136
+ * // In a logout handler - clear user context
137
+ * async function handleLogout() {
138
+ * analytics.reset(); // Clears userId and traits
119
139
  * }
120
140
  * ```
121
141
  */
122
- identify(userId: string, traits?: Record<string, unknown>): void;
142
+ identify(userId: string, traits?: TUserTraits): void;
123
143
  /**
124
144
  * Tracks a custom event with properties.
125
145
  *
@@ -128,6 +148,10 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
128
148
  * configured providers. Events are enriched with context information like
129
149
  * timestamp, user ID, session ID, and browser context.
130
150
  *
151
+ * **User Context (New):** If `identify()` was called previously, user data (userId,
152
+ * email, traits) is automatically included in the event context sent to all providers.
153
+ * This happens transparently - you don't need to pass user data manually.
154
+ *
131
155
  * If providers are configured, the method waits for all providers to complete
132
156
  * tracking. Failed providers don't prevent others from succeeding.
133
157
  *
@@ -146,6 +170,19 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
146
170
  *
147
171
  * @example
148
172
  * ```typescript
173
+ * // User context is automatically included after identify()
174
+ * analytics.identify('user-123', {
175
+ * email: 'user@example.com',
176
+ * plan: 'pro'
177
+ * });
178
+ *
179
+ * // Now all events automatically include user context
180
+ * analytics.track('button_clicked', { buttonId: 'checkout' });
181
+ * // Providers receive: context.user = { userId: 'user-123', email: 'user@example.com', traits: {...} }
182
+ * ```
183
+ *
184
+ * @example
185
+ * ```typescript
149
186
  * // Track a purchase event
150
187
  * await analytics.track('purchase_completed', {
151
188
  * orderId: 'order-123',
@@ -409,7 +446,7 @@ export declare class BrowserAnalytics<TEventMap extends DefaultEventMap = Defaul
409
446
  * });
410
447
  * ```
411
448
  */
412
- updateContext(context: Partial<EventContext>): void;
449
+ updateContext(context: Partial<EventContext<TUserTraits>>): void;
413
450
  private getCategoryFromEventName;
414
451
  private generateSessionId;
415
452
  private getDeviceType;
@@ -1,6 +1,6 @@
1
- import { AnalyticsConfig, EventContext } from '../../core/events/types.js';
1
+ import { AnalyticsConfig, EventContext, UserContext } from '../../core/events/types.js';
2
2
  type DefaultEventMap = Record<string, Record<string, unknown>>;
3
- export declare class ServerAnalytics<TEventMap extends Record<string, Record<string, unknown>> = DefaultEventMap> {
3
+ export declare class ServerAnalytics<TEventMap extends Record<string, Record<string, unknown>> = DefaultEventMap, TUserTraits extends Record<string, unknown> = Record<string, unknown>> {
4
4
  private providers;
5
5
  private config;
6
6
  private initialized;
@@ -129,12 +129,17 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
129
129
  * Server-side tracking typically includes additional context like IP addresses,
130
130
  * user agents, and server-specific metadata that isn't available on the client.
131
131
  *
132
+ * **User Context (New):** You can now pass user data (email, traits) with each event
133
+ * via `options.user` or `options.context.user`. This is useful for providers like
134
+ * Loops, Customer.io, or Intercom that require user identifiers.
135
+ *
132
136
  * @param eventName Name of the event to track (must match your event definitions)
133
137
  * @param properties Event-specific properties and data
134
- * @param options Optional configuration including user ID, session ID, and context
138
+ * @param options Optional configuration including user ID, session ID, user context, and additional context
135
139
  * @param options.userId User ID to associate with this event
136
140
  * @param options.sessionId Session ID to associate with this event
137
- * @param options.context Additional context for this event
141
+ * @param options.user User context including email and traits (automatically included in event context)
142
+ * @param options.context Additional context for this event (page, device, etc.)
138
143
  * @returns Promise that resolves when tracking is complete for all providers
139
144
  *
140
145
  * @example
@@ -150,7 +155,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
150
155
  *
151
156
  * @example
152
157
  * ```typescript
153
- * // Track with user context
158
+ * // Track with user context (recommended for email-based providers)
154
159
  * await analytics.track('purchase_completed', {
155
160
  * orderId: 'order-123',
156
161
  * amount: 99.99,
@@ -158,33 +163,61 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
158
163
  * itemCount: 3
159
164
  * }, {
160
165
  * userId: 'user-456',
161
- * sessionId: 'session-789',
166
+ * user: {
167
+ * email: 'user@example.com',
168
+ * traits: {
169
+ * plan: 'pro',
170
+ * company: 'Acme Corp'
171
+ * }
172
+ * },
162
173
  * context: {
163
174
  * page: { path: '/checkout/complete' },
164
- * device: { userAgent: req.headers['user-agent'] },
165
- * ip: req.ip
175
+ * device: { userAgent: req.headers['user-agent'] }
166
176
  * }
167
177
  * });
178
+ * // Providers receive: context.user = { email: 'user@example.com', traits: {...} }
168
179
  * ```
169
180
  *
170
181
  * @example
171
182
  * ```typescript
172
- * // In an Express.js route handler
183
+ * // Alternative: Pass user via context.user
184
+ * await analytics.track('feature_used', {
185
+ * featureName: 'export'
186
+ * }, {
187
+ * userId: 'user-123',
188
+ * context: {
189
+ * user: {
190
+ * email: 'user@example.com'
191
+ * },
192
+ * page: { path: '/dashboard' }
193
+ * }
194
+ * });
195
+ * ```
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * // In an Express.js route handler with user data
173
200
  * app.post('/api/users', async (req, res) => {
174
201
  * const user = await createUser(req.body);
175
202
  *
176
- * // Track user creation with server context
203
+ * // Track user creation with full user context
177
204
  * await analytics.track('user_created', {
178
205
  * userId: user.id,
179
206
  * email: user.email,
180
207
  * plan: user.plan
181
208
  * }, {
182
209
  * userId: user.id,
210
+ * user: {
211
+ * email: user.email,
212
+ * traits: {
213
+ * name: user.name,
214
+ * plan: user.plan,
215
+ * company: user.company
216
+ * }
217
+ * },
183
218
  * context: {
184
219
  * page: { path: req.path },
185
- * device: { userAgent: req.headers['user-agent'] },
186
- * ip: req.ip,
187
- * server: { version: process.env.APP_VERSION }
220
+ * device: { userAgent: req.headers['user-agent'] }
188
221
  * }
189
222
  * });
190
223
  *
@@ -210,7 +243,8 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
210
243
  track<TEventName extends string>(eventName: TEventName, properties: TEventName extends keyof TEventMap ? TEventMap[TEventName] : Record<string, unknown>, options?: {
211
244
  userId?: string;
212
245
  sessionId?: string;
213
- context?: EventContext;
246
+ context?: EventContext<TUserTraits>;
247
+ user?: UserContext<TUserTraits>;
214
248
  }): Promise<void>;
215
249
  /**
216
250
  * Tracks a page view event from the server side.
@@ -273,7 +307,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
273
307
  * ```
274
308
  */
275
309
  pageView(properties?: Record<string, unknown>, options?: {
276
- context?: EventContext;
310
+ context?: EventContext<TUserTraits>;
277
311
  }): void;
278
312
  /**
279
313
  * Tracks when a user leaves a page from the server side.
@@ -335,7 +369,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
335
369
  * ```
336
370
  */
337
371
  pageLeave(properties?: Record<string, unknown>, options?: {
338
- context?: EventContext;
372
+ context?: EventContext<TUserTraits>;
339
373
  }): void;
340
374
  /**
341
375
  * Shuts down all analytics providers and flushes pending events.