@chordcommerce/analytics 1.18.2 → 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 +22 -6
- package/dist/cjs/client/consent/index.d.ts +6 -8
- package/dist/cjs/client/consent/index.js +62 -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 +17 -3
- package/dist/client/consent/index.d.ts +6 -8
- package/dist/client/consent/index.js +56 -64
- 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/client/index.d.ts
CHANGED
|
@@ -30,10 +30,24 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
30
30
|
* Promise that resolves when CDP is ready
|
|
31
31
|
*/
|
|
32
32
|
private cdpReadyPromise;
|
|
33
|
+
private consentConfig;
|
|
33
34
|
private resetInProgress;
|
|
35
|
+
/**
|
|
36
|
+
* Queue for events waiting for consent to be ready
|
|
37
|
+
*/
|
|
38
|
+
private consentEventQueue;
|
|
39
|
+
/**
|
|
40
|
+
* Whether we're currently waiting for consent and watching for it
|
|
41
|
+
*/
|
|
42
|
+
private consentWatcherActive;
|
|
43
|
+
/**
|
|
44
|
+
* Promise that resolves when consent is ready (shared across all queued events)
|
|
45
|
+
*/
|
|
46
|
+
private consentReadyPromise;
|
|
34
47
|
constructor(options: ChordAnalyticsOptions<T>);
|
|
35
48
|
/**
|
|
36
|
-
* Initialize CDP snippet and wait for it to be ready
|
|
49
|
+
* Initialize CDP snippet and wait for it to be ready.
|
|
50
|
+
* Fires initial consent track event after CDP is fully initialized to avoid circular await.
|
|
37
51
|
*/
|
|
38
52
|
private initializeCdp;
|
|
39
53
|
/**
|
|
@@ -45,6 +59,29 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
45
59
|
ccdp: () => AnyAnalytics;
|
|
46
60
|
logger: (message?: any, ...optionalParams: any[]) => void;
|
|
47
61
|
isResetting: () => boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Wait for consent manager to be ready (no timeout - queues indefinitely).
|
|
64
|
+
* Uses a shared promise so multiple events share the same watcher.
|
|
65
|
+
*/
|
|
66
|
+
private waitForConsent;
|
|
67
|
+
/**
|
|
68
|
+
* Queue an event to be sent when consent is ready.
|
|
69
|
+
* Starts a consent watcher if not already active.
|
|
70
|
+
*/
|
|
71
|
+
private queueEventForConsent;
|
|
72
|
+
/**
|
|
73
|
+
* Watch for consent to become ready, then flush the queue.
|
|
74
|
+
*/
|
|
75
|
+
private watchForConsentAndFlush;
|
|
76
|
+
/**
|
|
77
|
+
* Flush all queued events now that consent is ready.
|
|
78
|
+
*/
|
|
79
|
+
private flushConsentQueue;
|
|
80
|
+
/**
|
|
81
|
+
* Configure CDP with fresh consent categories before each event.
|
|
82
|
+
* Uses Jitsu's configure() to update privacy.consentCategories.
|
|
83
|
+
*/
|
|
84
|
+
private configureConsentOnCdp;
|
|
48
85
|
validate: (event: string, props: EventProperties) => ValidateResult[];
|
|
49
86
|
/**
|
|
50
87
|
* Generate the event `meta` property.
|
|
@@ -67,21 +104,36 @@ export declare class ChordAnalytics<T extends ObjectTypes = ObjectTypes> {
|
|
|
67
104
|
addSourceMiddleware: (func: AnalyticsMiddleware) => void;
|
|
68
105
|
/**
|
|
69
106
|
* Send a `track` event to the CDP with any event name and properties.
|
|
107
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
70
108
|
*/
|
|
71
109
|
track: (event: string, props?: EventProperties, options?: Options) => Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Internal method to actually send a track event to CDP.
|
|
112
|
+
*/
|
|
113
|
+
private sendTrackEvent;
|
|
72
114
|
/**
|
|
73
115
|
* Send an `identify` event to the CDP with user id and traits.
|
|
116
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
74
117
|
*/
|
|
75
118
|
identify: {
|
|
76
119
|
(userId?: string, traits?: IdentifyTraits, options?: AnyOptions): Promise<void>;
|
|
77
120
|
(traits?: IdentifyTraits, options?: AnyOptions): Promise<void>;
|
|
78
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Internal method to actually send an identify event to CDP.
|
|
124
|
+
*/
|
|
125
|
+
private sendIdentifyEvent;
|
|
79
126
|
/**
|
|
80
127
|
* Send a `page` event to the CDP.
|
|
128
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
81
129
|
*/
|
|
82
130
|
page: {
|
|
83
|
-
(props?: Record<string, any
|
|
131
|
+
(props?: Record<string, any>, options?: Options): void;
|
|
84
132
|
};
|
|
133
|
+
/**
|
|
134
|
+
* Internal method to actually send a page event to CDP.
|
|
135
|
+
*/
|
|
136
|
+
private sendPageEvent;
|
|
85
137
|
reset: () => Promise<void>;
|
|
86
138
|
trackCartViewed: (props: CartViewedInput<T>, options?: AnyOptions) => Promise<void>;
|
|
87
139
|
trackCheckoutStarted: (props: CheckoutStartedInput<T>, options?: AnyOptions) => Promise<void>;
|
package/dist/client/index.js
CHANGED
|
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { addCdpSnippet, cdpQueue } from './cdp.js';
|
|
11
|
+
import { addCdpConsent } from './consent/index.js';
|
|
11
12
|
import { eventSchemas } from '../validators/index.js';
|
|
12
13
|
import { pruneNullValues } from '../utils.js';
|
|
13
14
|
const DEBUG_MODE_STORAGE_KEY = 'chordcommerce/analytics/debug';
|
|
@@ -30,7 +31,20 @@ export class ChordAnalytics {
|
|
|
30
31
|
* Promise that resolves when CDP is ready
|
|
31
32
|
*/
|
|
32
33
|
this.cdpReadyPromise = null;
|
|
34
|
+
this.consentConfig = null;
|
|
33
35
|
this.resetInProgress = false;
|
|
36
|
+
/**
|
|
37
|
+
* Queue for events waiting for consent to be ready
|
|
38
|
+
*/
|
|
39
|
+
this.consentEventQueue = [];
|
|
40
|
+
/**
|
|
41
|
+
* Whether we're currently waiting for consent and watching for it
|
|
42
|
+
*/
|
|
43
|
+
this.consentWatcherActive = false;
|
|
44
|
+
/**
|
|
45
|
+
* Promise that resolves when consent is ready (shared across all queued events)
|
|
46
|
+
*/
|
|
47
|
+
this.consentReadyPromise = null;
|
|
34
48
|
/**
|
|
35
49
|
* Set debug mode for Chord Analytics
|
|
36
50
|
* @param enabled - Whether debug mode should be enabled
|
|
@@ -72,6 +86,102 @@ export class ChordAnalytics {
|
|
|
72
86
|
this.isResetting = () => {
|
|
73
87
|
return this.resetInProgress;
|
|
74
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Wait for consent manager to be ready (no timeout - queues indefinitely).
|
|
91
|
+
* Uses a shared promise so multiple events share the same watcher.
|
|
92
|
+
*/
|
|
93
|
+
this.waitForConsent = () => __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
if (!this.consentConfig)
|
|
95
|
+
return;
|
|
96
|
+
if (this.consentConfig.isConsentReady())
|
|
97
|
+
return;
|
|
98
|
+
// If already waiting, return the existing promise
|
|
99
|
+
if (this.consentReadyPromise) {
|
|
100
|
+
yield this.consentReadyPromise;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Start a new consent watcher - polls until consent is ready
|
|
104
|
+
this.consentReadyPromise = new Promise((resolve) => {
|
|
105
|
+
const interval = setInterval(() => {
|
|
106
|
+
var _a;
|
|
107
|
+
if ((_a = this.consentConfig) === null || _a === void 0 ? void 0 : _a.isConsentReady()) {
|
|
108
|
+
clearInterval(interval);
|
|
109
|
+
this.consentReadyPromise = null;
|
|
110
|
+
resolve(true);
|
|
111
|
+
}
|
|
112
|
+
}, 100);
|
|
113
|
+
});
|
|
114
|
+
yield this.consentReadyPromise;
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* Queue an event to be sent when consent is ready.
|
|
118
|
+
* Starts a consent watcher if not already active.
|
|
119
|
+
*/
|
|
120
|
+
this.queueEventForConsent = (type, args) => {
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
this.consentEventQueue.push({ type, args, resolve });
|
|
123
|
+
// Start watching for consent if not already
|
|
124
|
+
if (!this.consentWatcherActive) {
|
|
125
|
+
this.consentWatcherActive = true;
|
|
126
|
+
this.watchForConsentAndFlush();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Watch for consent to become ready, then flush the queue.
|
|
132
|
+
*/
|
|
133
|
+
this.watchForConsentAndFlush = () => __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
yield this.waitForConsent();
|
|
135
|
+
yield this.flushConsentQueue();
|
|
136
|
+
this.consentWatcherActive = false;
|
|
137
|
+
});
|
|
138
|
+
/**
|
|
139
|
+
* Flush all queued events now that consent is ready.
|
|
140
|
+
*/
|
|
141
|
+
this.flushConsentQueue = () => __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
const queue = [...this.consentEventQueue];
|
|
143
|
+
this.consentEventQueue = [];
|
|
144
|
+
const sendPromises = queue.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
try {
|
|
146
|
+
switch (item.type) {
|
|
147
|
+
case 'track':
|
|
148
|
+
yield this.sendTrackEvent(item.args[0], item.args[1], item.args[2]);
|
|
149
|
+
break;
|
|
150
|
+
case 'page':
|
|
151
|
+
yield this.sendPageEvent(item.args[0], item.args[1]);
|
|
152
|
+
break;
|
|
153
|
+
case 'identify':
|
|
154
|
+
yield this.sendIdentifyEvent(item.args[0], item.args[1], item.args[2]);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
this.logger('[Chord Analytics]: Error sending queued event:', error);
|
|
162
|
+
}
|
|
163
|
+
item.resolve();
|
|
164
|
+
}));
|
|
165
|
+
yield Promise.all(sendPromises);
|
|
166
|
+
});
|
|
167
|
+
/**
|
|
168
|
+
* Configure CDP with fresh consent categories before each event.
|
|
169
|
+
* Uses Jitsu's configure() to update privacy.consentCategories.
|
|
170
|
+
*/
|
|
171
|
+
this.configureConsentOnCdp = () => {
|
|
172
|
+
if (!this.consentConfig)
|
|
173
|
+
return;
|
|
174
|
+
const categories = this.consentConfig.getCategories();
|
|
175
|
+
const privacyConfig = { privacy: { consentCategories: categories } };
|
|
176
|
+
const a = this.ccdp();
|
|
177
|
+
if (a && typeof a.configure === 'function') {
|
|
178
|
+
a.configure(privacyConfig);
|
|
179
|
+
}
|
|
180
|
+
const b = this.cdp();
|
|
181
|
+
if (b && typeof b.configure === 'function') {
|
|
182
|
+
b.configure(privacyConfig);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
75
185
|
this.validate = (event, props) => {
|
|
76
186
|
if (!event) {
|
|
77
187
|
this.logger('No event name provided');
|
|
@@ -104,14 +214,46 @@ export class ChordAnalytics {
|
|
|
104
214
|
};
|
|
105
215
|
/**
|
|
106
216
|
* Send a `track` event to the CDP with any event name and properties.
|
|
217
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
107
218
|
*/
|
|
108
219
|
this.track = (event, props, options) => __awaiter(this, void 0, void 0, function* () {
|
|
220
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
221
|
+
// eslint-disable-next-line no-console
|
|
222
|
+
console.log(`[Chord Analytics DEBUG]: track() called with event: "${event}"`);
|
|
223
|
+
}
|
|
109
224
|
if (!event)
|
|
110
225
|
this.logger('No event name provided');
|
|
111
226
|
// Wait for CDP to be ready before sending track events
|
|
112
227
|
if (this.cdpReadyPromise) {
|
|
228
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
229
|
+
// eslint-disable-next-line no-console
|
|
230
|
+
console.log(`[Chord Analytics DEBUG]: track("${event}") waiting for cdpReadyPromise`);
|
|
231
|
+
}
|
|
113
232
|
yield this.cdpReadyPromise;
|
|
233
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
234
|
+
// eslint-disable-next-line no-console
|
|
235
|
+
console.log(`[Chord Analytics DEBUG]: track("${event}") cdpReadyPromise resolved`);
|
|
236
|
+
}
|
|
114
237
|
}
|
|
238
|
+
// If consent is configured but not ready, queue the event
|
|
239
|
+
if (this.consentConfig && !this.consentConfig.isConsentReady()) {
|
|
240
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
241
|
+
// eslint-disable-next-line no-console
|
|
242
|
+
console.log(`[Chord Analytics DEBUG]: track("${event}") consent not ready, queuing event`);
|
|
243
|
+
}
|
|
244
|
+
return this.queueEventForConsent('track', [event, props, options]);
|
|
245
|
+
}
|
|
246
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
247
|
+
// eslint-disable-next-line no-console
|
|
248
|
+
console.log(`[Chord Analytics DEBUG]: track("${event}") sending event now`);
|
|
249
|
+
}
|
|
250
|
+
// Consent ready (or not configured) - send immediately
|
|
251
|
+
return this.sendTrackEvent(event, props, options);
|
|
252
|
+
});
|
|
253
|
+
/**
|
|
254
|
+
* Internal method to actually send a track event to CDP.
|
|
255
|
+
*/
|
|
256
|
+
this.sendTrackEvent = (event, props, options) => __awaiter(this, void 0, void 0, function* () {
|
|
115
257
|
const formattedProps = this.options.stripNull && props ? pruneNullValues(props) : props;
|
|
116
258
|
let middlewareProps = {};
|
|
117
259
|
if (this.middleware.length > 0) {
|
|
@@ -153,7 +295,9 @@ export class ChordAnalytics {
|
|
|
153
295
|
}
|
|
154
296
|
});
|
|
155
297
|
}
|
|
156
|
-
|
|
298
|
+
// Configure CDP with fresh consent before sending
|
|
299
|
+
this.configureConsentOnCdp();
|
|
300
|
+
yield new Promise((resolve) => {
|
|
157
301
|
const cdpPromises = [];
|
|
158
302
|
try {
|
|
159
303
|
const a = this.ccdp();
|
|
@@ -188,24 +332,65 @@ export class ChordAnalytics {
|
|
|
188
332
|
});
|
|
189
333
|
/**
|
|
190
334
|
* Send an `identify` event to the CDP with user id and traits.
|
|
335
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
191
336
|
*/
|
|
192
|
-
this.identify = (
|
|
337
|
+
this.identify = (userIdOrTraits, traitsOrOptions, options) => __awaiter(this, void 0, void 0, function* () {
|
|
193
338
|
// Wait for CDP to be ready before sending identify events
|
|
194
339
|
if (this.cdpReadyPromise) {
|
|
195
340
|
yield this.cdpReadyPromise;
|
|
196
341
|
}
|
|
342
|
+
// If consent is configured but not ready, queue the event
|
|
343
|
+
if (this.consentConfig && !this.consentConfig.isConsentReady()) {
|
|
344
|
+
return this.queueEventForConsent('identify', [
|
|
345
|
+
userIdOrTraits,
|
|
346
|
+
traitsOrOptions,
|
|
347
|
+
options,
|
|
348
|
+
]);
|
|
349
|
+
}
|
|
350
|
+
// Consent ready (or not configured) - send immediately
|
|
351
|
+
return this.sendIdentifyEvent(userIdOrTraits, traitsOrOptions, options);
|
|
352
|
+
});
|
|
353
|
+
/**
|
|
354
|
+
* Internal method to actually send an identify event to CDP.
|
|
355
|
+
*/
|
|
356
|
+
this.sendIdentifyEvent = (userIdOrTraits, traitsOrOptions, options) => __awaiter(this, void 0, void 0, function* () {
|
|
357
|
+
// Parse arguments to extract userId, traits, and options
|
|
358
|
+
let userId;
|
|
359
|
+
let traits;
|
|
360
|
+
let opts;
|
|
361
|
+
if (typeof userIdOrTraits === 'string') {
|
|
362
|
+
userId = userIdOrTraits;
|
|
363
|
+
traits = traitsOrOptions;
|
|
364
|
+
opts = options;
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
traits = userIdOrTraits;
|
|
368
|
+
opts = traitsOrOptions;
|
|
369
|
+
}
|
|
370
|
+
// Configure CDP with fresh consent before sending
|
|
371
|
+
this.configureConsentOnCdp();
|
|
197
372
|
try {
|
|
198
373
|
const identifyPromises = [];
|
|
199
374
|
const a = this.ccdp();
|
|
200
375
|
if (a && typeof a.identify === 'function') {
|
|
201
376
|
identifyPromises.push(new Promise((resolve) => {
|
|
202
|
-
|
|
377
|
+
if (userId) {
|
|
378
|
+
a.identify(userId, traits, opts, () => resolve());
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
a.identify(traits, opts, () => resolve());
|
|
382
|
+
}
|
|
203
383
|
}));
|
|
204
384
|
}
|
|
205
385
|
const b = this.cdp();
|
|
206
386
|
if (b && typeof b.identify === 'function') {
|
|
207
387
|
identifyPromises.push(new Promise((resolve) => {
|
|
208
|
-
|
|
388
|
+
if (userId) {
|
|
389
|
+
b.identify(userId, traits, opts, () => resolve());
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
b.identify(traits, opts, () => resolve());
|
|
393
|
+
}
|
|
209
394
|
}));
|
|
210
395
|
}
|
|
211
396
|
const results = yield Promise.allSettled(identifyPromises);
|
|
@@ -217,24 +402,38 @@ export class ChordAnalytics {
|
|
|
217
402
|
});
|
|
218
403
|
/**
|
|
219
404
|
* Send a `page` event to the CDP.
|
|
405
|
+
* If consent is not ready, the event is queued until consent is available.
|
|
220
406
|
*/
|
|
221
|
-
this.page = (props = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
407
|
+
this.page = (options, props = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
222
408
|
// Wait for CDP to be ready before sending page events
|
|
223
409
|
if (this.cdpReadyPromise) {
|
|
224
410
|
yield this.cdpReadyPromise;
|
|
225
411
|
}
|
|
412
|
+
// If consent is configured but not ready, queue the event
|
|
413
|
+
if (this.consentConfig && !this.consentConfig.isConsentReady()) {
|
|
414
|
+
return this.queueEventForConsent('page', [options, props]);
|
|
415
|
+
}
|
|
416
|
+
// Consent ready (or not configured) - send immediately
|
|
417
|
+
return this.sendPageEvent(options, props);
|
|
418
|
+
});
|
|
419
|
+
/**
|
|
420
|
+
* Internal method to actually send a page event to CDP.
|
|
421
|
+
*/
|
|
422
|
+
this.sendPageEvent = (options, props = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
423
|
+
// Configure CDP with fresh consent before sending
|
|
424
|
+
this.configureConsentOnCdp();
|
|
226
425
|
try {
|
|
227
426
|
const pagePromises = [];
|
|
228
427
|
const a = this.ccdp();
|
|
229
428
|
if (a && typeof a.page === 'function') {
|
|
230
429
|
pagePromises.push(new Promise((resolve) => {
|
|
231
|
-
a.page(Object.assign(Object.assign({}, props), { meta: this.meta() }), () => resolve());
|
|
430
|
+
a.page(Object.assign(Object.assign({}, props), { meta: this.meta() }), options, () => resolve());
|
|
232
431
|
}));
|
|
233
432
|
}
|
|
234
433
|
const b = this.cdp();
|
|
235
434
|
if (b && typeof b.page === 'function') {
|
|
236
435
|
pagePromises.push(new Promise((resolve) => {
|
|
237
|
-
b.page(Object.assign(Object.assign({}, props), { meta: this.meta() }), () => resolve());
|
|
436
|
+
b.page(Object.assign(Object.assign({}, props), { meta: this.meta() }), options, () => resolve());
|
|
238
437
|
}));
|
|
239
438
|
}
|
|
240
439
|
// We don't return the promise to maintain the void return type
|
|
@@ -680,21 +879,56 @@ export class ChordAnalytics {
|
|
|
680
879
|
stripNull: true,
|
|
681
880
|
};
|
|
682
881
|
this.options = Object.assign(Object.assign({}, defaults), options);
|
|
882
|
+
if (this.options.consent) {
|
|
883
|
+
const consentManager = addCdpConsent(this.options);
|
|
884
|
+
this.consentConfig = consentManager.getConsentConfig() || null;
|
|
885
|
+
}
|
|
683
886
|
if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.cdpDomain) && ((_c = this.options) === null || _c === void 0 ? void 0 : _c.cdpWriteKey) && window) {
|
|
684
887
|
window[this.options.namespace] = (window === null || window === void 0 ? void 0 : window[this.options.namespace]) || this;
|
|
685
888
|
this.initializeCdp();
|
|
686
889
|
}
|
|
687
890
|
}
|
|
688
891
|
/**
|
|
689
|
-
* Initialize CDP snippet and wait for it to be ready
|
|
892
|
+
* Initialize CDP snippet and wait for it to be ready.
|
|
893
|
+
* Fires initial consent track event after CDP is fully initialized to avoid circular await.
|
|
690
894
|
*/
|
|
691
895
|
initializeCdp() {
|
|
692
896
|
return __awaiter(this, void 0, void 0, function* () {
|
|
897
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
898
|
+
// eslint-disable-next-line no-console
|
|
899
|
+
console.log('[Chord Analytics DEBUG]: initializeCdp() started');
|
|
900
|
+
}
|
|
693
901
|
try {
|
|
694
|
-
|
|
695
|
-
|
|
902
|
+
const snippetPromise = addCdpSnippet(this.options);
|
|
903
|
+
// Create a void promise for cdpReadyPromise that resolves when snippet is done
|
|
904
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
905
|
+
this.cdpReadyPromise = snippetPromise.then(() => { });
|
|
906
|
+
const { initialConsent } = yield snippetPromise;
|
|
907
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
908
|
+
// eslint-disable-next-line no-console
|
|
909
|
+
console.log('[Chord Analytics DEBUG]: snippetPromise resolved, initialConsent:', JSON.stringify(initialConsent));
|
|
910
|
+
// eslint-disable-next-line no-console
|
|
911
|
+
console.log('[Chord Analytics DEBUG]: consentCategories defined?', (initialConsent === null || initialConsent === void 0 ? void 0 : initialConsent.consentCategories) !== undefined);
|
|
912
|
+
}
|
|
913
|
+
// Now that CDP is fully ready, fire the initial consent track event
|
|
914
|
+
if (initialConsent && initialConsent.consentCategories !== undefined) {
|
|
915
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
916
|
+
// eslint-disable-next-line no-console
|
|
917
|
+
console.log('[Chord Analytics DEBUG]: About to call this.track() for Consent Preferences Updated');
|
|
918
|
+
}
|
|
919
|
+
yield this.track('Consent Preferences Updated', initialConsent);
|
|
920
|
+
if (this.options.enableLogging && this.options.debug) {
|
|
921
|
+
// eslint-disable-next-line no-console
|
|
922
|
+
console.log('[Chord Analytics DEBUG]: Initial consent preferences tracked');
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
else if (this.options.enableLogging && this.options.debug) {
|
|
926
|
+
// eslint-disable-next-line no-console
|
|
927
|
+
console.log('[Chord Analytics DEBUG]: Skipping initial consent track - no consent or no consentCategories');
|
|
928
|
+
}
|
|
696
929
|
}
|
|
697
930
|
catch (error) {
|
|
931
|
+
// eslint-disable-next-line no-console
|
|
698
932
|
console.error('CDP initialization failed:', error);
|
|
699
933
|
}
|
|
700
934
|
});
|
package/dist/types/consent.d.ts
CHANGED
|
@@ -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/package.json
CHANGED