@dereekb/dbx-analytics 13.3.0 → 13.3.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.
@@ -7,38 +7,105 @@ import { safeCompareEquality, poll } from '@dereekb/util';
7
7
  import { toObservable } from '@angular/core/rxjs-interop';
8
8
  import { AbstractAsyncWindowLoadedService } from '@dereekb/browser';
9
9
 
10
+ /**
11
+ * Categorizes the kind of analytics stream event emitted by {@link DbxAnalyticsService}.
12
+ *
13
+ * Listeners use this type to route events to the appropriate analytics provider method
14
+ * (e.g., Segment `track()`, `identify()`, `page()`).
15
+ */
10
16
  var DbxAnalyticsStreamEventType;
11
17
  (function (DbxAnalyticsStreamEventType) {
18
+ /** A page/screen view event, typically sent on route transitions. */
12
19
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["PageView"] = 0] = "PageView";
13
20
  /**
14
- * Emitted any time the user value changes.
21
+ * Emitted any time the user value changes, including when transitioning from defined to undefined.
15
22
  *
16
- * Can emit when the user goes from defined to undefined.
23
+ * Used by listeners to update the identified user in analytics providers.
17
24
  */
18
25
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["UserChange"] = 1] = "UserChange";
19
26
  /**
20
- * Emitted any time the user id changes.
27
+ * Emitted only when the user's unique ID changes, filtering out property-only updates.
28
+ *
29
+ * Useful for triggering identity calls without redundant updates when only traits change.
21
30
  */
22
31
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["UserIdChange"] = 2] = "UserIdChange";
23
32
  // User Events
33
+ /** A new user registration event. */
24
34
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["NewUserEvent"] = 3] = "NewUserEvent";
35
+ /** A returning user login event. */
25
36
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["UserLoginEvent"] = 4] = "UserLoginEvent";
37
+ /** A user logout event. */
26
38
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["UserLogoutEvent"] = 5] = "UserLogoutEvent";
39
+ /** An update to user profile properties/traits. */
27
40
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["UserPropertiesEvent"] = 6] = "UserPropertiesEvent";
28
41
  // Events
42
+ /** A generic custom analytics event. */
29
43
  DbxAnalyticsStreamEventType[DbxAnalyticsStreamEventType["Event"] = 7] = "Event";
30
44
  })(DbxAnalyticsStreamEventType || (DbxAnalyticsStreamEventType = {}));
31
45
 
46
+ /**
47
+ * Abstract emitter interface for sending analytics events.
48
+ *
49
+ * Implemented by {@link DbxAnalyticsService} as the primary concrete implementation.
50
+ * Components and services use this to fire analytics events without coupling to a specific provider.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * // Inject and send a custom event
55
+ * const emitter = inject(DbxAnalyticsEventEmitterService);
56
+ * emitter.sendEventData('Button Clicked', { buttonId: 'save' });
57
+ * ```
58
+ */
32
59
  class DbxAnalyticsEventEmitterService {
33
60
  }
61
+ /**
62
+ * Abstract interface exposing the analytics event stream as an observable.
63
+ *
64
+ * Implemented by {@link DbxAnalyticsService}. Listeners subscribe to `events$` to forward events to external providers.
65
+ */
34
66
  class DbxAnalyticsEventStreamService {
35
67
  }
68
+ /**
69
+ * Abstract source for the current analytics user identity.
70
+ *
71
+ * Provide an implementation to automatically associate a user with all emitted analytics events.
72
+ * Typically backed by the auth system (e.g., {@link DbxFirebaseAnalyticsUserSource}).
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * // Provide a static user source
77
+ * const userSource: DbxAnalyticsUserSource = {
78
+ * analyticsUser$: of({ user: 'uid_abc123', properties: { role: 'admin' } })
79
+ * };
80
+ * ```
81
+ */
36
82
  class DbxAnalyticsUserSource {
37
83
  }
84
+ /**
85
+ * Abstract listener that receives analytics events from {@link DbxAnalyticsService}.
86
+ *
87
+ * Implement this to forward events to an external analytics provider (e.g., Segment, Mixpanel).
88
+ * Register listeners via {@link DbxAnalyticsServiceConfiguration.listeners}.
89
+ */
38
90
  class DbxAnalyticsServiceListener {
39
91
  }
40
92
  /**
41
- * Abstract AnalyticsServiceListener implementation.
93
+ * Base class for analytics service listeners that manages subscription lifecycle and provides
94
+ * reactive access to the analytics service and its event stream.
95
+ *
96
+ * Subclasses implement {@link _initializeServiceSubscription} to subscribe to events and forward them
97
+ * to an external analytics provider.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * class MyAnalyticsListener extends AbstractDbxAnalyticsServiceListener {
102
+ * protected _initializeServiceSubscription(): Subscription | false {
103
+ * return this.analyticsEvents$.subscribe((event) => {
104
+ * console.log('Event:', event.type, event.event?.name);
105
+ * });
106
+ * }
107
+ * }
108
+ * ```
42
109
  */
43
110
  class AbstractDbxAnalyticsServiceListener {
44
111
  _sub = new SubscriptionObject();
@@ -59,12 +126,46 @@ class AbstractDbxAnalyticsServiceListener {
59
126
  this._sub.destroy();
60
127
  }
61
128
  }
129
+ /**
130
+ * Configuration for {@link DbxAnalyticsService}, controlling which listeners receive events,
131
+ * whether analytics runs in production mode, and optionally providing a user source.
132
+ *
133
+ * In non-production mode, listeners are not initialized and all events are logged to the console instead.
134
+ * Provide via {@link provideDbxAnalyticsService} using a factory function.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * const config: DbxAnalyticsServiceConfiguration = {
139
+ * isProduction: environment.production,
140
+ * logEvents: !environment.production,
141
+ * listeners: [segmentListener],
142
+ * userSource: firebaseAnalyticsUserSource
143
+ * };
144
+ * ```
145
+ */
62
146
  class DbxAnalyticsServiceConfiguration {
63
147
  listeners = [];
64
148
  isProduction;
65
149
  logEvents;
66
150
  userSource;
67
151
  }
152
+ /**
153
+ * Wraps a {@link DbxUserAnalyticsEvent} into a {@link DbxAnalyticsStreamEventAnalyticsEventWrapper},
154
+ * extracting the user ID for convenient access by listeners.
155
+ *
156
+ * @param event - the analytics event with optional user context
157
+ * @param type - the stream event type classification; defaults to `Event`
158
+ * @returns a wrapper combining the event, type, user, and extracted userId
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const wrapper = dbxAnalyticsStreamEventAnalyticsEventWrapper(
163
+ * { name: 'Button Clicked', user: { user: 'uid_123' } },
164
+ * DbxAnalyticsStreamEventType.Event
165
+ * );
166
+ * // wrapper.userId === 'uid_123'
167
+ * ```
168
+ */
68
169
  function dbxAnalyticsStreamEventAnalyticsEventWrapper(event, type = DbxAnalyticsStreamEventType.Event) {
69
170
  const { user } = event;
70
171
  const userId = user ? user.user : undefined;
@@ -76,7 +177,27 @@ function dbxAnalyticsStreamEventAnalyticsEventWrapper(event, type = DbxAnalytics
76
177
  };
77
178
  }
78
179
  /**
79
- * Primary analytics service that emits analytics events that components can listen to.
180
+ * Central analytics service that emits typed analytics events for consumption by registered listeners.
181
+ *
182
+ * Acts as both the event emitter (components call methods like {@link sendEventData}, {@link sendPageView})
183
+ * and the event stream source (listeners subscribe to {@link events$}).
184
+ *
185
+ * In production mode, registered {@link DbxAnalyticsServiceListener} instances (e.g., Segment) receive all events.
186
+ * In non-production mode, events are logged to the console for debugging.
187
+ *
188
+ * Provided via {@link provideDbxAnalyticsService} with a {@link DbxAnalyticsServiceConfiguration} factory.
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * // Send a custom event from a component
193
+ * const analytics = inject(DbxAnalyticsService);
194
+ * analytics.sendEventData('Interview Started', { candidateId: 'abc123' });
195
+ *
196
+ * // Send a page view on route transitions
197
+ * transitionService.onSuccess({}, () => {
198
+ * analytics.sendPageView();
199
+ * });
200
+ * ```
80
201
  */
81
202
  class DbxAnalyticsService {
82
203
  _config = inject(DbxAnalyticsServiceConfiguration);
@@ -102,7 +223,11 @@ class DbxAnalyticsService {
102
223
  }
103
224
  // MARK: Source
104
225
  /**
105
- * Sets the user directly, overridding the UserSource.
226
+ * Sets the analytics user directly, overriding any configured {@link DbxAnalyticsUserSource}.
227
+ *
228
+ * Pass `undefined` to clear the current user (e.g., on logout).
229
+ *
230
+ * @param user - the user to identify, or undefined to clear
106
231
  */
107
232
  setUser(user) {
108
233
  let source;
@@ -114,12 +239,20 @@ class DbxAnalyticsService {
114
239
  console.warn('DbxAnalyticsService has a userSource that is set. Source is now overridden by setUser() value.');
115
240
  }
116
241
  }
242
+ /**
243
+ * Sets the reactive user source that automatically updates the analytics user as auth state changes.
244
+ *
245
+ * @param source - the user source providing an observable of the current analytics user
246
+ */
117
247
  setUserSource(source) {
118
248
  this._userSource.next(source);
119
249
  }
120
250
  // MARK: AnalyticsEventEmitterService
121
251
  /**
122
- * Sends an event.
252
+ * Emits a new user registration event, typically sent once after account creation.
253
+ *
254
+ * @param user - the newly registered user
255
+ * @param data - registration-specific data including the signup method
123
256
  */
124
257
  sendNewUserEvent(user, data) {
125
258
  this.sendNextEvent({
@@ -127,12 +260,24 @@ class DbxAnalyticsService {
127
260
  data
128
261
  }, DbxAnalyticsStreamEventType.NewUserEvent, user);
129
262
  }
263
+ /**
264
+ * Emits a user login event, identifying the user in analytics providers.
265
+ *
266
+ * @param user - the user who logged in
267
+ * @param data - optional additional event data
268
+ */
130
269
  sendUserLoginEvent(user, data) {
131
270
  this.sendNextEvent({
132
271
  name: DbxAnalyticsService.USER_LOGIN_EVENT_NAME,
133
272
  data
134
273
  }, DbxAnalyticsStreamEventType.UserLoginEvent, user);
135
274
  }
275
+ /**
276
+ * Emits a user logout event and optionally clears the current analytics user.
277
+ *
278
+ * @param data - optional additional event data
279
+ * @param clearUser - whether to reset the analytics user identity; defaults to `true`
280
+ */
136
281
  sendUserLogoutEvent(data, clearUser = true) {
137
282
  this.sendNextEvent({
138
283
  name: DbxAnalyticsService.USER_LOGOUT_EVENT_NAME,
@@ -142,6 +287,12 @@ class DbxAnalyticsService {
142
287
  this.setUser(undefined);
143
288
  }
144
289
  }
290
+ /**
291
+ * Emits a user properties update event, used to sync user traits to analytics providers.
292
+ *
293
+ * @param user - the user whose properties are being updated
294
+ * @param data - optional additional event data
295
+ */
145
296
  sendUserPropertiesEvent(user, data) {
146
297
  this.sendNextEvent({
147
298
  name: DbxAnalyticsService.USER_PROPERTIES_EVENT_NAME,
@@ -154,14 +305,42 @@ class DbxAnalyticsService {
154
305
  data
155
306
  });
156
307
  }
308
+ /**
309
+ * Sends a named event with no additional data, useful for simple occurrence tracking.
310
+ *
311
+ * @param eventType - the event name to track
312
+ *
313
+ * @example
314
+ * ```ts
315
+ * analytics.sendEventType('Finish Account Setup');
316
+ * ```
317
+ */
157
318
  sendEventType(eventType) {
158
319
  this.sendNextEvent({
159
320
  name: eventType
160
321
  }, DbxAnalyticsStreamEventType.Event);
161
322
  }
323
+ /**
324
+ * Sends a fully constructed analytics event object.
325
+ *
326
+ * @param event - the event containing name, optional value, and data
327
+ */
162
328
  sendEvent(event) {
163
329
  this.sendNextEvent(event, DbxAnalyticsStreamEventType.Event);
164
330
  }
331
+ /**
332
+ * Sends a page view event, typically called on successful route transitions.
333
+ *
334
+ * @param page - optional page name/path override; if omitted, the provider determines the current page
335
+ *
336
+ * @example
337
+ * ```ts
338
+ * // In a router config function
339
+ * transitionService.onSuccess({}, () => {
340
+ * analyticsService.sendPageView();
341
+ * });
342
+ * ```
343
+ */
165
344
  sendPageView(page) {
166
345
  this.sendNextEvent({
167
346
  name: page
@@ -225,7 +404,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
225
404
  }], ctorParameters: () => [] });
226
405
 
227
406
  /**
228
- * Used to listen to an ActionContext and send analytical events based on action events.
407
+ * Standalone directive that listens to a host {@link DbxActionDirective} and fires analytics events
408
+ * based on the action's lifecycle (triggered, ready, success, error).
409
+ *
410
+ * Attach to any element that has a `dbxAction` directive and pass a {@link DbxActionAnalyticsConfig}
411
+ * to define which events to send at each lifecycle stage.
412
+ *
413
+ * @example
414
+ * ```html
415
+ * <button dbxAction
416
+ * [dbxActionHandler]="handleSave"
417
+ * [dbxActionAnalytics]="saveAnalytics">
418
+ * Save
419
+ * </button>
420
+ * ```
229
421
  */
230
422
  class DbxActionAnalyticsDirective {
231
423
  source = inject((DbxActionContextStoreSourceInstance), { host: true });
@@ -288,10 +480,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
288
480
  }] });
289
481
 
290
482
  /**
291
- * Creates a EnvironmentProviders that provides a DbxAnalyticsService.
483
+ * Creates Angular environment providers that register {@link DbxAnalyticsService} and its configuration.
484
+ *
485
+ * Call this in your application's `providers` array to set up analytics with a custom configuration factory
486
+ * that resolves listeners, user sources, and environment flags at runtime.
292
487
  *
293
- * @param config Configuration
294
- * @returns EnvironmentProviders
488
+ * @param config - contains the factory function that produces a {@link DbxAnalyticsServiceConfiguration}
489
+ * @returns environment providers for the analytics service
490
+ *
491
+ * @example
492
+ * ```ts
493
+ * // In app.config.ts
494
+ * export const appConfig: ApplicationConfig = {
495
+ * providers: [
496
+ * provideDbxAnalyticsService({
497
+ * dbxAnalyticsServiceConfigurationFactory: (injector: Injector) => ({
498
+ * isProduction: environment.production,
499
+ * logEvents: !environment.production,
500
+ * listeners: [injector.get(DbxAnalyticsSegmentServiceListener)],
501
+ * userSource: injector.get(DbxFirebaseAnalyticsUserSource)
502
+ * })
503
+ * })
504
+ * ]
505
+ * };
506
+ * ```
295
507
  */
296
508
  function provideDbxAnalyticsService(config) {
297
509
  const { dbxAnalyticsServiceConfigurationFactory } = config;
@@ -308,7 +520,20 @@ function provideDbxAnalyticsService(config) {
308
520
  return makeEnvironmentProviders(providers);
309
521
  }
310
522
 
523
+ /**
524
+ * Injection token for optionally preloading the Segment analytics script.
525
+ */
311
526
  const PRELOAD_SEGMENT_TOKEN = new InjectionToken('DbxAnalyticsSegmentApiServicePreload');
527
+ /**
528
+ * Configuration for the Segment analytics integration.
529
+ *
530
+ * @example
531
+ * ```ts
532
+ * const config = new DbxAnalyticsSegmentApiServiceConfig('your-segment-write-key');
533
+ * config.active = environment.production;
534
+ * config.logging = !environment.production;
535
+ * ```
536
+ */
312
537
  class DbxAnalyticsSegmentApiServiceConfig {
313
538
  writeKey;
314
539
  logging = true;
@@ -318,9 +543,26 @@ class DbxAnalyticsSegmentApiServiceConfig {
318
543
  }
319
544
  }
320
545
  /**
321
- * Segment API Service used for waiting/retrieving the segment API from window when initialized.
546
+ * Service that manages the async loading and initialization of the Segment analytics SDK from `window.analytics`.
547
+ *
548
+ * Polls for the Segment snippet to be invoked, then calls `analytics.load()` with the configured write key.
549
+ * Once Segment reports ready, the resolved SDK instance is available via the inherited `service$` observable.
550
+ *
551
+ * Requires the Segment analytics snippet to be included in `index.html`.
322
552
  *
323
- * This requires some setup in index.html.
553
+ * Provided via {@link provideDbxAnalyticsSegmentApiService}.
554
+ *
555
+ * @example
556
+ * ```ts
557
+ * // In app.config.ts
558
+ * provideDbxAnalyticsSegmentApiService({
559
+ * dbxAnalyticsSegmentApiServiceConfigFactory: (injector) => {
560
+ * const config = new DbxAnalyticsSegmentApiServiceConfig(environment.analytics.segment);
561
+ * config.active = environment.production;
562
+ * return config;
563
+ * }
564
+ * })
565
+ * ```
324
566
  */
325
567
  class DbxAnalyticsSegmentApiService extends AbstractAsyncWindowLoadedService {
326
568
  _config = inject(DbxAnalyticsSegmentApiServiceConfig);
@@ -365,7 +607,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
365
607
  }], ctorParameters: () => [] });
366
608
 
367
609
  /**
368
- * DbxAnalyticsServiceListener adapter for Segment.
610
+ * Analytics listener that forwards {@link DbxAnalyticsStreamEvent} events to the Segment SDK.
611
+ *
612
+ * Automatically maps event types to the appropriate Segment methods:
613
+ * - {@link DbxAnalyticsStreamEventType.Event} / {@link DbxAnalyticsStreamEventType.UserLoginEvent} -> `track()`
614
+ * - {@link DbxAnalyticsStreamEventType.UserChange} / {@link DbxAnalyticsStreamEventType.NewUserEvent} -> `identify()`
615
+ * - {@link DbxAnalyticsStreamEventType.UserLogoutEvent} -> `reset()`
616
+ * - {@link DbxAnalyticsStreamEventType.PageView} -> `page()`
617
+ *
618
+ * Events are only sent when the Segment configuration is marked as `active`.
619
+ * Provided at root level and registered as a listener via {@link DbxAnalyticsServiceConfiguration.listeners}.
620
+ *
621
+ * @example
622
+ * ```ts
623
+ * // Register in analytics configuration factory
624
+ * function analyticsConfigFactory(injector: Injector): DbxAnalyticsServiceConfiguration {
625
+ * const segmentListener = injector.get(DbxAnalyticsSegmentServiceListener);
626
+ * return {
627
+ * isProduction: true,
628
+ * listeners: [segmentListener]
629
+ * };
630
+ * }
631
+ * ```
369
632
  */
370
633
  class DbxAnalyticsSegmentServiceListener extends AbstractDbxAnalyticsServiceListener {
371
634
  _segmentApi = inject(DbxAnalyticsSegmentApiService);
@@ -483,10 +746,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
483
746
  }], ctorParameters: () => [] });
484
747
 
485
748
  /**
486
- * Creates a EnvironmentProviders that provides a DbxAnalyticsSegmentApiService.
749
+ * Creates Angular environment providers that register {@link DbxAnalyticsSegmentApiService} for Segment analytics integration.
750
+ *
751
+ * Use alongside {@link provideDbxAnalyticsService} to wire Segment as an analytics listener.
752
+ *
753
+ * @param config - Segment-specific configuration including the write key factory
754
+ * @returns environment providers for Segment analytics
487
755
  *
488
- * @param config Configuration
489
- * @returns EnvironmentProviders
756
+ * @example
757
+ * ```ts
758
+ * // In app.config.ts
759
+ * export const appConfig: ApplicationConfig = {
760
+ * providers: [
761
+ * provideDbxAnalyticsSegmentApiService({
762
+ * dbxAnalyticsSegmentApiServiceConfigFactory: (injector) => {
763
+ * const config = new DbxAnalyticsSegmentApiServiceConfig(environment.analytics.segment);
764
+ * config.active = environment.production;
765
+ * config.logging = !environment.production;
766
+ * return config;
767
+ * }
768
+ * }),
769
+ * provideDbxAnalyticsService({
770
+ * dbxAnalyticsServiceConfigurationFactory: (injector) => ({
771
+ * isProduction: environment.production,
772
+ * listeners: [injector.get(DbxAnalyticsSegmentServiceListener)]
773
+ * })
774
+ * })
775
+ * ]
776
+ * };
777
+ * ```
490
778
  */
491
779
  function provideDbxAnalyticsSegmentApiService(config) {
492
780
  const { preloadSegmentToken, dbxAnalyticsSegmentApiServiceConfigFactory } = config;