@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.
- package/dist/cjs/client/cdp.d.ts +5 -2
- package/dist/cjs/client/cdp.js +15 -7
- package/dist/cjs/client/consent/index.d.ts +6 -8
- package/dist/cjs/client/consent/index.js +55 -89
- package/dist/cjs/client/consent/ketch.d.ts +2 -0
- package/dist/cjs/client/consent/ketch.js +5 -1
- package/dist/cjs/client/consent/onetrust-api.d.ts +103 -0
- package/dist/cjs/client/consent/onetrust-api.js +128 -0
- package/dist/cjs/client/consent/onetrust.d.ts +4 -16
- package/dist/cjs/client/consent/onetrust.js +25 -34
- package/dist/cjs/client/consent/segment.d.ts +2 -0
- package/dist/cjs/client/consent/segment.js +16 -10
- package/dist/cjs/client/consent/shopify.d.ts +2 -0
- package/dist/cjs/client/consent/shopify.js +12 -1
- package/dist/cjs/client/index.d.ts +54 -2
- package/dist/cjs/client/index.js +375 -81
- package/dist/cjs/types/consent.d.ts +13 -2
- package/dist/client/cdp.d.ts +5 -2
- package/dist/client/cdp.js +13 -5
- package/dist/client/consent/index.d.ts +6 -8
- package/dist/client/consent/index.js +50 -62
- package/dist/client/consent/ketch.d.ts +2 -0
- package/dist/client/consent/ketch.js +5 -1
- package/dist/client/consent/onetrust-api.d.ts +103 -0
- package/dist/client/consent/onetrust-api.js +119 -0
- package/dist/client/consent/onetrust.d.ts +4 -16
- package/dist/client/consent/onetrust.js +25 -33
- package/dist/client/consent/segment.d.ts +2 -0
- package/dist/client/consent/segment.js +10 -3
- package/dist/client/consent/shopify.d.ts +2 -0
- package/dist/client/consent/shopify.js +12 -1
- package/dist/client/index.d.ts +54 -2
- package/dist/client/index.js +244 -10
- package/dist/types/consent.d.ts +13 -2
- package/package.json +1 -1
package/dist/cjs/client/index.js
CHANGED
|
@@ -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("
|
|
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 &&
|
|
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
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
-
|
|
287
|
-
|
|
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
|
-
*
|
|
562
|
+
* Internal method to actually send a page event to CDP.
|
|
302
563
|
*/
|
|
303
|
-
this.
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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,
|
|
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
|
-
|
|
384
|
-
this.logger(
|
|
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
|
|
1127
|
+
var snippetPromise, initialConsent, error_4;
|
|
869
1128
|
return __generator(this, function (_a) {
|
|
870
1129
|
switch (_a.label) {
|
|
871
1130
|
case 0:
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
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.
|
|
877
|
-
|
|
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
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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: (
|
|
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
|
}
|
package/dist/client/cdp.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type { ChordAnalyticsOptions, ChordAnalyticsQueue } from '../types/index.js';
|
|
2
|
-
export
|
|
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;
|
package/dist/client/cdp.js
CHANGED
|
@@ -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
|
|
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
|
|
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.
|