@chordcommerce/analytics 1.18.3-beta.1 → 1.19.0-beta.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.
Files changed (35) hide show
  1. package/dist/cjs/client/cdp.d.ts +5 -2
  2. package/dist/cjs/client/cdp.js +15 -7
  3. package/dist/cjs/client/consent/index.d.ts +6 -8
  4. package/dist/cjs/client/consent/index.js +55 -89
  5. package/dist/cjs/client/consent/ketch.d.ts +2 -0
  6. package/dist/cjs/client/consent/ketch.js +5 -1
  7. package/dist/cjs/client/consent/onetrust-api.d.ts +103 -0
  8. package/dist/cjs/client/consent/onetrust-api.js +128 -0
  9. package/dist/cjs/client/consent/onetrust.d.ts +4 -16
  10. package/dist/cjs/client/consent/onetrust.js +25 -34
  11. package/dist/cjs/client/consent/segment.d.ts +2 -0
  12. package/dist/cjs/client/consent/segment.js +16 -10
  13. package/dist/cjs/client/consent/shopify.d.ts +2 -0
  14. package/dist/cjs/client/consent/shopify.js +12 -1
  15. package/dist/cjs/client/index.d.ts +54 -2
  16. package/dist/cjs/client/index.js +375 -81
  17. package/dist/cjs/types/consent.d.ts +13 -2
  18. package/dist/client/cdp.d.ts +5 -2
  19. package/dist/client/cdp.js +13 -5
  20. package/dist/client/consent/index.d.ts +6 -8
  21. package/dist/client/consent/index.js +50 -62
  22. package/dist/client/consent/ketch.d.ts +2 -0
  23. package/dist/client/consent/ketch.js +5 -1
  24. package/dist/client/consent/onetrust-api.d.ts +103 -0
  25. package/dist/client/consent/onetrust-api.js +119 -0
  26. package/dist/client/consent/onetrust.d.ts +4 -16
  27. package/dist/client/consent/onetrust.js +25 -33
  28. package/dist/client/consent/segment.d.ts +2 -0
  29. package/dist/client/consent/segment.js +10 -3
  30. package/dist/client/consent/shopify.d.ts +2 -0
  31. package/dist/client/consent/shopify.js +12 -1
  32. package/dist/client/index.d.ts +54 -2
  33. package/dist/client/index.js +244 -10
  34. package/dist/types/consent.d.ts +13 -2
  35. package/package.json +1 -1
@@ -58,7 +58,8 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
58
58
  Object.defineProperty(exports, "__esModule", { value: true });
59
59
  exports.ChordAnalytics = void 0;
60
60
  var cdp_js_1 = require("./cdp.js");
61
- var index_js_1 = require("../validators/index.js");
61
+ var index_js_1 = require("./consent/index.js");
62
+ var index_js_2 = require("../validators/index.js");
62
63
  var utils_js_1 = require("../utils.js");
63
64
  var DEBUG_MODE_STORAGE_KEY = 'chordcommerce/analytics/debug';
64
65
  var ChordAnalytics = /** @class */ (function () {
@@ -81,7 +82,20 @@ var ChordAnalytics = /** @class */ (function () {
81
82
  * Promise that resolves when CDP is ready
82
83
  */
83
84
  this.cdpReadyPromise = null;
85
+ this.consentConfig = null;
84
86
  this.resetInProgress = false;
87
+ /**
88
+ * Queue for events waiting for consent to be ready
89
+ */
90
+ this.consentEventQueue = [];
91
+ /**
92
+ * Whether we're currently waiting for consent and watching for it
93
+ */
94
+ this.consentWatcherActive = false;
95
+ /**
96
+ * Promise that resolves when consent is ready (shared across all queued events)
97
+ */
98
+ this.consentReadyPromise = null;
85
99
  /**
86
100
  * Set debug mode for Chord Analytics
87
101
  * @param enabled - Whether debug mode should be enabled
@@ -127,12 +141,153 @@ var ChordAnalytics = /** @class */ (function () {
127
141
  this.isResetting = function () {
128
142
  return _this.resetInProgress;
129
143
  };
144
+ /**
145
+ * Wait for consent manager to be ready (no timeout - queues indefinitely).
146
+ * Uses a shared promise so multiple events share the same watcher.
147
+ */
148
+ this.waitForConsent = function () { return __awaiter(_this, void 0, void 0, function () {
149
+ var _this = this;
150
+ return __generator(this, function (_a) {
151
+ switch (_a.label) {
152
+ case 0:
153
+ if (!this.consentConfig)
154
+ return [2 /*return*/];
155
+ if (this.consentConfig.isConsentReady())
156
+ return [2 /*return*/];
157
+ if (!this.consentReadyPromise) return [3 /*break*/, 2];
158
+ return [4 /*yield*/, this.consentReadyPromise];
159
+ case 1:
160
+ _a.sent();
161
+ return [2 /*return*/];
162
+ case 2:
163
+ // Start a new consent watcher - polls until consent is ready
164
+ this.consentReadyPromise = new Promise(function (resolve) {
165
+ var interval = setInterval(function () {
166
+ var _a;
167
+ if ((_a = _this.consentConfig) === null || _a === void 0 ? void 0 : _a.isConsentReady()) {
168
+ clearInterval(interval);
169
+ _this.consentReadyPromise = null;
170
+ resolve(true);
171
+ }
172
+ }, 100);
173
+ });
174
+ return [4 /*yield*/, this.consentReadyPromise];
175
+ case 3:
176
+ _a.sent();
177
+ return [2 /*return*/];
178
+ }
179
+ });
180
+ }); };
181
+ /**
182
+ * Queue an event to be sent when consent is ready.
183
+ * Starts a consent watcher if not already active.
184
+ */
185
+ this.queueEventForConsent = function (type, args) {
186
+ return new Promise(function (resolve) {
187
+ _this.consentEventQueue.push({ type: type, args: args, resolve: resolve });
188
+ // Start watching for consent if not already
189
+ if (!_this.consentWatcherActive) {
190
+ _this.consentWatcherActive = true;
191
+ _this.watchForConsentAndFlush();
192
+ }
193
+ });
194
+ };
195
+ /**
196
+ * Watch for consent to become ready, then flush the queue.
197
+ */
198
+ this.watchForConsentAndFlush = function () { return __awaiter(_this, void 0, void 0, function () {
199
+ return __generator(this, function (_a) {
200
+ switch (_a.label) {
201
+ case 0: return [4 /*yield*/, this.waitForConsent()];
202
+ case 1:
203
+ _a.sent();
204
+ return [4 /*yield*/, this.flushConsentQueue()];
205
+ case 2:
206
+ _a.sent();
207
+ this.consentWatcherActive = false;
208
+ return [2 /*return*/];
209
+ }
210
+ });
211
+ }); };
212
+ /**
213
+ * Flush all queued events now that consent is ready.
214
+ */
215
+ this.flushConsentQueue = function () { return __awaiter(_this, void 0, void 0, function () {
216
+ var queue, sendPromises;
217
+ var _this = this;
218
+ return __generator(this, function (_a) {
219
+ switch (_a.label) {
220
+ case 0:
221
+ queue = __spreadArray([], this.consentEventQueue, true);
222
+ this.consentEventQueue = [];
223
+ sendPromises = queue.map(function (item) { return __awaiter(_this, void 0, void 0, function () {
224
+ var _a, error_1;
225
+ return __generator(this, function (_b) {
226
+ switch (_b.label) {
227
+ case 0:
228
+ _b.trys.push([0, 9, , 10]);
229
+ _a = item.type;
230
+ switch (_a) {
231
+ case 'track': return [3 /*break*/, 1];
232
+ case 'page': return [3 /*break*/, 3];
233
+ case 'identify': return [3 /*break*/, 5];
234
+ }
235
+ return [3 /*break*/, 7];
236
+ case 1: return [4 /*yield*/, this.sendTrackEvent(item.args[0], item.args[1], item.args[2])];
237
+ case 2:
238
+ _b.sent();
239
+ return [3 /*break*/, 8];
240
+ case 3: return [4 /*yield*/, this.sendPageEvent(item.args[0], item.args[1])];
241
+ case 4:
242
+ _b.sent();
243
+ return [3 /*break*/, 8];
244
+ case 5: return [4 /*yield*/, this.sendIdentifyEvent(item.args[0], item.args[1], item.args[2])];
245
+ case 6:
246
+ _b.sent();
247
+ return [3 /*break*/, 8];
248
+ case 7: return [3 /*break*/, 8];
249
+ case 8: return [3 /*break*/, 10];
250
+ case 9:
251
+ error_1 = _b.sent();
252
+ this.logger('[Chord Analytics]: Error sending queued event:', error_1);
253
+ return [3 /*break*/, 10];
254
+ case 10:
255
+ item.resolve();
256
+ return [2 /*return*/];
257
+ }
258
+ });
259
+ }); });
260
+ return [4 /*yield*/, Promise.all(sendPromises)];
261
+ case 1:
262
+ _a.sent();
263
+ return [2 /*return*/];
264
+ }
265
+ });
266
+ }); };
267
+ /**
268
+ * Configure CDP with fresh consent categories before each event.
269
+ * Uses Jitsu's configure() to update privacy.consentCategories.
270
+ */
271
+ this.configureConsentOnCdp = function () {
272
+ if (!_this.consentConfig)
273
+ return;
274
+ var categories = _this.consentConfig.getCategories();
275
+ var privacyConfig = { privacy: { consentCategories: categories } };
276
+ var a = _this.ccdp();
277
+ if (a && typeof a.configure === 'function') {
278
+ a.configure(privacyConfig);
279
+ }
280
+ var b = _this.cdp();
281
+ if (b && typeof b.configure === 'function') {
282
+ b.configure(privacyConfig);
283
+ }
284
+ };
130
285
  this.validate = function (event, props) {
131
286
  if (!event) {
132
287
  _this.logger('No event name provided');
133
288
  return [{ success: false }];
134
289
  }
135
- var schema = event && index_js_1.eventSchemas[event];
290
+ var schema = event && index_js_2.eventSchemas[event];
136
291
  if (!schema)
137
292
  return [{ success: true, data: props }];
138
293
  return schema.map(function (s) { return s.safeParse(props); });
@@ -159,21 +314,58 @@ var ChordAnalytics = /** @class */ (function () {
159
314
  };
160
315
  /**
161
316
  * Send a `track` event to the CDP with any event name and properties.
317
+ * If consent is not ready, the event is queued until consent is available.
162
318
  */
163
319
  this.track = function (event, props, options) { return __awaiter(_this, void 0, void 0, function () {
164
- var formattedProps, middlewareProps, searchParams_1, urlSearchParams, searchData_1, finalEventProps;
165
- var _this = this;
166
320
  return __generator(this, function (_a) {
167
321
  switch (_a.label) {
168
322
  case 0:
323
+ if (this.options.enableLogging && this.options.debug) {
324
+ // eslint-disable-next-line no-console
325
+ console.log("[Chord Analytics DEBUG]: track() called with event: \"".concat(event, "\""));
326
+ }
169
327
  if (!event)
170
328
  this.logger('No event name provided');
171
329
  if (!this.cdpReadyPromise) return [3 /*break*/, 2];
330
+ if (this.options.enableLogging && this.options.debug) {
331
+ // eslint-disable-next-line no-console
332
+ console.log("[Chord Analytics DEBUG]: track(\"".concat(event, "\") waiting for cdpReadyPromise"));
333
+ }
172
334
  return [4 /*yield*/, this.cdpReadyPromise];
173
335
  case 1:
174
336
  _a.sent();
337
+ if (this.options.enableLogging && this.options.debug) {
338
+ // eslint-disable-next-line no-console
339
+ console.log("[Chord Analytics DEBUG]: track(\"".concat(event, "\") cdpReadyPromise resolved"));
340
+ }
175
341
  _a.label = 2;
176
342
  case 2:
343
+ // If consent is configured but not ready, queue the event
344
+ if (this.consentConfig && !this.consentConfig.isConsentReady()) {
345
+ if (this.options.enableLogging && this.options.debug) {
346
+ // eslint-disable-next-line no-console
347
+ console.log("[Chord Analytics DEBUG]: track(\"".concat(event, "\") consent not ready, queuing event"));
348
+ }
349
+ return [2 /*return*/, this.queueEventForConsent('track', [event, props, options])];
350
+ }
351
+ if (this.options.enableLogging && this.options.debug) {
352
+ // eslint-disable-next-line no-console
353
+ console.log("[Chord Analytics DEBUG]: track(\"".concat(event, "\") sending event now"));
354
+ }
355
+ // Consent ready (or not configured) - send immediately
356
+ return [2 /*return*/, this.sendTrackEvent(event, props, options)];
357
+ }
358
+ });
359
+ }); };
360
+ /**
361
+ * Internal method to actually send a track event to CDP.
362
+ */
363
+ this.sendTrackEvent = function (event, props, options) { return __awaiter(_this, void 0, void 0, function () {
364
+ var formattedProps, middlewareProps, searchParams_1, urlSearchParams, searchData_1, finalEventProps;
365
+ var _this = this;
366
+ return __generator(this, function (_a) {
367
+ switch (_a.label) {
368
+ case 0:
177
369
  formattedProps = this.options.stripNull && props ? (0, utils_js_1.pruneNullValues)(props) : props;
178
370
  middlewareProps = {};
179
371
  if (this.middleware.length > 0) {
@@ -215,7 +407,9 @@ var ChordAnalytics = /** @class */ (function () {
215
407
  }
216
408
  });
217
409
  }
218
- return [2 /*return*/, new Promise(function (resolve) {
410
+ // Configure CDP with fresh consent before sending
411
+ this.configureConsentOnCdp();
412
+ return [4 /*yield*/, new Promise(function (resolve) {
219
413
  var cdpPromises = [];
220
414
  try {
221
415
  var a_1 = _this.ccdp();
@@ -247,19 +441,104 @@ var ChordAnalytics = /** @class */ (function () {
247
441
  resolve();
248
442
  }
249
443
  })];
444
+ case 1:
445
+ _a.sent();
446
+ return [2 /*return*/];
250
447
  }
251
448
  });
252
449
  }); };
253
450
  /**
254
451
  * Send an `identify` event to the CDP with user id and traits.
452
+ * If consent is not ready, the event is queued until consent is available.
255
453
  */
256
- this.identify = function () {
257
- var props = [];
258
- for (var _i = 0; _i < arguments.length; _i++) {
259
- props[_i] = arguments[_i];
260
- }
454
+ this.identify = function (userIdOrTraits, traitsOrOptions, options) { return __awaiter(_this, void 0, void 0, function () {
455
+ return __generator(this, function (_a) {
456
+ switch (_a.label) {
457
+ case 0:
458
+ if (!this.cdpReadyPromise) return [3 /*break*/, 2];
459
+ return [4 /*yield*/, this.cdpReadyPromise];
460
+ case 1:
461
+ _a.sent();
462
+ _a.label = 2;
463
+ case 2:
464
+ // If consent is configured but not ready, queue the event
465
+ if (this.consentConfig && !this.consentConfig.isConsentReady()) {
466
+ return [2 /*return*/, this.queueEventForConsent('identify', [
467
+ userIdOrTraits,
468
+ traitsOrOptions,
469
+ options,
470
+ ])];
471
+ }
472
+ // Consent ready (or not configured) - send immediately
473
+ return [2 /*return*/, this.sendIdentifyEvent(userIdOrTraits, traitsOrOptions, options)];
474
+ }
475
+ });
476
+ }); };
477
+ /**
478
+ * Internal method to actually send an identify event to CDP.
479
+ */
480
+ this.sendIdentifyEvent = function (userIdOrTraits, traitsOrOptions, options) { return __awaiter(_this, void 0, void 0, function () {
481
+ var userId, traits, opts, identifyPromises, a_2, b_2, results, error_2;
482
+ return __generator(this, function (_a) {
483
+ switch (_a.label) {
484
+ case 0:
485
+ if (typeof userIdOrTraits === 'string') {
486
+ userId = userIdOrTraits;
487
+ traits = traitsOrOptions;
488
+ opts = options;
489
+ }
490
+ else {
491
+ traits = userIdOrTraits;
492
+ opts = traitsOrOptions;
493
+ }
494
+ // Configure CDP with fresh consent before sending
495
+ this.configureConsentOnCdp();
496
+ _a.label = 1;
497
+ case 1:
498
+ _a.trys.push([1, 3, , 4]);
499
+ identifyPromises = [];
500
+ a_2 = this.ccdp();
501
+ if (a_2 && typeof a_2.identify === 'function') {
502
+ identifyPromises.push(new Promise(function (resolve) {
503
+ if (userId) {
504
+ a_2.identify(userId, traits, opts, function () { return resolve(); });
505
+ }
506
+ else {
507
+ a_2.identify(traits, opts, function () { return resolve(); });
508
+ }
509
+ }));
510
+ }
511
+ b_2 = this.cdp();
512
+ if (b_2 && typeof b_2.identify === 'function') {
513
+ identifyPromises.push(new Promise(function (resolve) {
514
+ if (userId) {
515
+ b_2.identify(userId, traits, opts, function () { return resolve(); });
516
+ }
517
+ else {
518
+ b_2.identify(traits, opts, function () { return resolve(); });
519
+ }
520
+ }));
521
+ }
522
+ return [4 /*yield*/, Promise.allSettled(identifyPromises)];
523
+ case 2:
524
+ results = _a.sent();
525
+ this.logger('identify event sent', results);
526
+ return [3 /*break*/, 4];
527
+ case 3:
528
+ error_2 = _a.sent();
529
+ this.logger(error_2);
530
+ return [3 /*break*/, 4];
531
+ case 4: return [2 /*return*/];
532
+ }
533
+ });
534
+ }); };
535
+ /**
536
+ * Send a `page` event to the CDP.
537
+ * If consent is not ready, the event is queued until consent is available.
538
+ */
539
+ this.page = function (options, props) {
540
+ if (props === void 0) { props = {}; }
261
541
  return __awaiter(_this, void 0, void 0, function () {
262
- var identifyPromises, a_2, b_2, results, error_1;
263
542
  return __generator(this, function (_a) {
264
543
  switch (_a.label) {
265
544
  case 0:
@@ -269,80 +548,55 @@ var ChordAnalytics = /** @class */ (function () {
269
548
  _a.sent();
270
549
  _a.label = 2;
271
550
  case 2:
272
- _a.trys.push([2, 4, , 5]);
273
- identifyPromises = [];
274
- a_2 = this.ccdp();
275
- if (a_2 && typeof a_2.identify === 'function') {
276
- identifyPromises.push(new Promise(function (resolve) {
277
- a_2.identify.apply(a_2, __spreadArray(__spreadArray([], props, false), [function () { return resolve(); }], false));
278
- }));
279
- }
280
- b_2 = this.cdp();
281
- if (b_2 && typeof b_2.identify === 'function') {
282
- identifyPromises.push(new Promise(function (resolve) {
283
- b_2.identify.apply(b_2, __spreadArray(__spreadArray([], props, false), [function () { return resolve(); }], false));
284
- }));
551
+ // If consent is configured but not ready, queue the event
552
+ if (this.consentConfig && !this.consentConfig.isConsentReady()) {
553
+ return [2 /*return*/, this.queueEventForConsent('page', [options, props])];
285
554
  }
286
- return [4 /*yield*/, Promise.allSettled(identifyPromises)];
287
- case 3:
288
- results = _a.sent();
289
- this.logger('identify event sent', results);
290
- return [3 /*break*/, 5];
291
- case 4:
292
- error_1 = _a.sent();
293
- this.logger(error_1);
294
- return [3 /*break*/, 5];
295
- case 5: return [2 /*return*/];
555
+ // Consent ready (or not configured) - send immediately
556
+ return [2 /*return*/, this.sendPageEvent(options, props)];
296
557
  }
297
558
  });
298
559
  });
299
560
  };
300
561
  /**
301
- * Send a `page` event to the CDP.
562
+ * Internal method to actually send a page event to CDP.
302
563
  */
303
- this.page = function (props) {
564
+ this.sendPageEvent = function (options, props) {
304
565
  if (props === void 0) { props = {}; }
305
566
  return __awaiter(_this, void 0, void 0, function () {
306
567
  var pagePromises, a_3, b_3;
307
568
  var _this = this;
308
569
  return __generator(this, function (_a) {
309
- switch (_a.label) {
310
- case 0:
311
- if (!this.cdpReadyPromise) return [3 /*break*/, 2];
312
- return [4 /*yield*/, this.cdpReadyPromise];
313
- case 1:
314
- _a.sent();
315
- _a.label = 2;
316
- case 2:
317
- try {
318
- pagePromises = [];
319
- a_3 = this.ccdp();
320
- if (a_3 && typeof a_3.page === 'function') {
321
- pagePromises.push(new Promise(function (resolve) {
322
- a_3.page(__assign(__assign({}, props), { meta: _this.meta() }), function () { return resolve(); });
323
- }));
324
- }
325
- b_3 = this.cdp();
326
- if (b_3 && typeof b_3.page === 'function') {
327
- pagePromises.push(new Promise(function (resolve) {
328
- b_3.page(__assign(__assign({}, props), { meta: _this.meta() }), function () { return resolve(); });
329
- }));
330
- }
331
- // We don't return the promise to maintain the void return type
332
- Promise.allSettled(pagePromises).then(function (results) {
333
- _this.logger('page event sent', results);
334
- });
335
- }
336
- catch (error) {
337
- this.logger(error);
338
- }
339
- return [2 /*return*/];
570
+ // Configure CDP with fresh consent before sending
571
+ this.configureConsentOnCdp();
572
+ try {
573
+ pagePromises = [];
574
+ a_3 = this.ccdp();
575
+ if (a_3 && typeof a_3.page === 'function') {
576
+ pagePromises.push(new Promise(function (resolve) {
577
+ a_3.page(__assign(__assign({}, props), { meta: _this.meta() }), options, function () { return resolve(); });
578
+ }));
579
+ }
580
+ b_3 = this.cdp();
581
+ if (b_3 && typeof b_3.page === 'function') {
582
+ pagePromises.push(new Promise(function (resolve) {
583
+ b_3.page(__assign(__assign({}, props), { meta: _this.meta() }), options, function () { return resolve(); });
584
+ }));
585
+ }
586
+ // We don't return the promise to maintain the void return type
587
+ Promise.allSettled(pagePromises).then(function (results) {
588
+ _this.logger('page event sent', results);
589
+ });
340
590
  }
591
+ catch (error) {
592
+ this.logger(error);
593
+ }
594
+ return [2 /*return*/];
341
595
  });
342
596
  });
343
597
  };
344
598
  this.reset = function () { return __awaiter(_this, void 0, void 0, function () {
345
- var a, b, maxAttempts, attempts, userState, error_2;
599
+ var a, b, maxAttempts, attempts, userState, error_3;
346
600
  var _a;
347
601
  return __generator(this, function (_b) {
348
602
  switch (_b.label) {
@@ -380,8 +634,8 @@ var ChordAnalytics = /** @class */ (function () {
380
634
  return [3 /*break*/, 1];
381
635
  case 3: return [3 /*break*/, 6];
382
636
  case 4:
383
- error_2 = _b.sent();
384
- this.logger(error_2);
637
+ error_3 = _b.sent();
638
+ this.logger(error_3);
385
639
  return [3 /*break*/, 6];
386
640
  case 5:
387
641
  this.resetInProgress = false;
@@ -855,31 +1109,71 @@ var ChordAnalytics = /** @class */ (function () {
855
1109
  stripNull: true,
856
1110
  };
857
1111
  this.options = __assign(__assign({}, defaults), options);
1112
+ if (this.options.consent) {
1113
+ var consentManager = (0, index_js_1.addCdpConsent)(this.options);
1114
+ this.consentConfig = consentManager.getConsentConfig() || null;
1115
+ }
858
1116
  if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.cdpDomain) && ((_c = this.options) === null || _c === void 0 ? void 0 : _c.cdpWriteKey) && window) {
859
1117
  window[this.options.namespace] = (window === null || window === void 0 ? void 0 : window[this.options.namespace]) || this;
860
1118
  this.initializeCdp();
861
1119
  }
862
1120
  }
863
1121
  /**
864
- * Initialize CDP snippet and wait for it to be ready
1122
+ * Initialize CDP snippet and wait for it to be ready.
1123
+ * Fires initial consent track event after CDP is fully initialized to avoid circular await.
865
1124
  */
866
1125
  ChordAnalytics.prototype.initializeCdp = function () {
867
1126
  return __awaiter(this, void 0, void 0, function () {
868
- var error_3;
1127
+ var snippetPromise, initialConsent, error_4;
869
1128
  return __generator(this, function (_a) {
870
1129
  switch (_a.label) {
871
1130
  case 0:
872
- _a.trys.push([0, 2, , 3]);
873
- this.cdpReadyPromise = (0, cdp_js_1.addCdpSnippet)(this.options);
874
- return [4 /*yield*/, this.cdpReadyPromise];
1131
+ if (this.options.enableLogging && this.options.debug) {
1132
+ // eslint-disable-next-line no-console
1133
+ console.log('[Chord Analytics DEBUG]: initializeCdp() started');
1134
+ }
1135
+ _a.label = 1;
875
1136
  case 1:
876
- _a.sent();
877
- return [3 /*break*/, 3];
1137
+ _a.trys.push([1, 6, , 7]);
1138
+ snippetPromise = (0, cdp_js_1.addCdpSnippet)(this.options);
1139
+ // Create a void promise for cdpReadyPromise that resolves when snippet is done
1140
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1141
+ this.cdpReadyPromise = snippetPromise.then(function () { });
1142
+ return [4 /*yield*/, snippetPromise];
878
1143
  case 2:
879
- error_3 = _a.sent();
880
- console.error('CDP initialization failed:', error_3);
881
- return [3 /*break*/, 3];
882
- case 3: return [2 /*return*/];
1144
+ initialConsent = (_a.sent()).initialConsent;
1145
+ if (this.options.enableLogging && this.options.debug) {
1146
+ // eslint-disable-next-line no-console
1147
+ console.log('[Chord Analytics DEBUG]: snippetPromise resolved, initialConsent:', JSON.stringify(initialConsent));
1148
+ // eslint-disable-next-line no-console
1149
+ console.log('[Chord Analytics DEBUG]: consentCategories defined?', (initialConsent === null || initialConsent === void 0 ? void 0 : initialConsent.consentCategories) !== undefined);
1150
+ }
1151
+ if (!(initialConsent && initialConsent.consentCategories !== undefined)) return [3 /*break*/, 4];
1152
+ if (this.options.enableLogging && this.options.debug) {
1153
+ // eslint-disable-next-line no-console
1154
+ console.log('[Chord Analytics DEBUG]: About to call this.track() for Consent Preferences Updated');
1155
+ }
1156
+ return [4 /*yield*/, this.track('Consent Preferences Updated', initialConsent)];
1157
+ case 3:
1158
+ _a.sent();
1159
+ if (this.options.enableLogging && this.options.debug) {
1160
+ // eslint-disable-next-line no-console
1161
+ console.log('[Chord Analytics DEBUG]: Initial consent preferences tracked');
1162
+ }
1163
+ return [3 /*break*/, 5];
1164
+ case 4:
1165
+ if (this.options.enableLogging && this.options.debug) {
1166
+ // eslint-disable-next-line no-console
1167
+ console.log('[Chord Analytics DEBUG]: Skipping initial consent track - no consent or no consentCategories');
1168
+ }
1169
+ _a.label = 5;
1170
+ case 5: return [3 /*break*/, 7];
1171
+ case 6:
1172
+ error_4 = _a.sent();
1173
+ // eslint-disable-next-line no-console
1174
+ console.error('CDP initialization failed:', error_4);
1175
+ return [3 /*break*/, 7];
1176
+ case 7: return [2 /*return*/];
883
1177
  }
884
1178
  });
885
1179
  });
@@ -1,11 +1,22 @@
1
1
  export interface ConsentAdapter {
2
2
  getCurrentConsent: () => ConsentConfiguration | Promise<ConsentConfiguration>;
3
- handleConsentUpdates: (fn: (ConsentConfiguration: any) => void) => void;
3
+ handleConsentUpdates: (fn: (consent: ConsentConfiguration) => void) => void;
4
4
  userCanBeTracked: () => boolean | Promise<boolean>;
5
+ /**
6
+ * Get current consent categories - called FRESH on every event, no caching!
7
+ */
8
+ getCategories?: () => Record<string, boolean>;
9
+ /**
10
+ * Check if consent manager is ready (duck typing check)
11
+ */
12
+ isConsentReady?: () => boolean;
13
+ /**
14
+ * Get the consent model ('opt-in' or 'opt-out')
15
+ */
16
+ getConsentModel?: () => 'opt-in' | 'opt-out';
5
17
  }
6
18
  export interface ConsentConfiguration {
7
19
  consentCategories?: {
8
20
  [key: string]: boolean;
9
21
  };
10
- dontSend?: boolean;
11
22
  }
@@ -1,3 +1,6 @@
1
- import type { ChordAnalyticsOptions, ChordAnalyticsQueue } from '../types/index.js';
2
- export declare const addCdpSnippet: (options: ChordAnalyticsOptions) => Promise<void>;
1
+ import type { ChordAnalyticsOptions, ChordAnalyticsQueue, ConsentConfiguration } from '../types/index.js';
2
+ export interface CdpSnippetResult {
3
+ initialConsent: ConsentConfiguration | null;
4
+ }
5
+ export declare const addCdpSnippet: (options: ChordAnalyticsOptions) => Promise<CdpSnippetResult>;
3
6
  export declare const cdpQueue: (namespace: string) => ChordAnalyticsQueue;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-console */
1
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -11,10 +12,12 @@ import { addCdpConsent } from './consent/index.js';
11
12
  import { normalizeCDPDomain } from './utils.js';
12
13
  /*
13
14
  * Adds the Chord CDP snippet to the page.
15
+ * Returns initial consent configuration to be tracked after CDP is fully ready.
14
16
  */
15
17
  export const addCdpSnippet = (options) => __awaiter(void 0, void 0, void 0, function* () {
16
- if (!document || typeof document.createElement === 'undefined')
17
- return;
18
+ if (!document || typeof document.createElement === 'undefined') {
19
+ return { initialConsent: null };
20
+ }
18
21
  const normalizedCDPDomain = normalizeCDPDomain(options.cdpDomain);
19
22
  // Create a promise that resolves when CDP is ready
20
23
  const cdpReadyPromise = new Promise((resolve) => {
@@ -39,15 +42,20 @@ export const addCdpSnippet = (options) => __awaiter(void 0, void 0, void 0, func
39
42
  document.head.appendChild(s);
40
43
  // Wait for CDP to be ready before setting up consent
41
44
  yield cdpReadyPromise;
45
+ let initialConsent = null;
42
46
  if (options.consent) {
43
47
  if (options.debug && options.enableLogging) {
44
- console.log('Chord CDP: Setting up consent management');
48
+ console.log('[Chord Analytics DEBUG]: Setting up consent management');
45
49
  }
46
- yield addCdpConsent(options).init();
50
+ initialConsent = yield addCdpConsent(options).init();
47
51
  if (options.debug && options.enableLogging) {
48
- console.log('Chord CDP: Consent management setup complete');
52
+ console.log('[Chord Analytics DEBUG]: Consent management setup complete');
49
53
  }
50
54
  }
55
+ if (options.debug && options.enableLogging) {
56
+ console.log('[Chord Analytics DEBUG]: CDP snippet added, initialConsent:', JSON.stringify(initialConsent));
57
+ }
58
+ return { initialConsent };
51
59
  });
52
60
  /*
53
61
  * Returns the CDP queue to hold events ahead of CDP initialization.