@chordcommerce/analytics
Version:
Chord Commerce event tracking
148 lines (147 loc) • 6.49 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { ketchConsentAdapter } from './ketch.js';
import { onetrustConsentAdapter } from './onetrust.js';
import { shopifyConsentAdapter } from './shopify.js';
import { segmentConsentAdapter } from './segment.js';
export const addCdpConsent = (options) => {
let lastProcessedConsent = null;
const POLLING_INTERVAL_MS = 50;
const TIMEOUT_MS = options.awaitConsentTimeout
? options.awaitConsentTimeout
: 60000;
/**
* Returns the adapter for the specified consent management platform.
*/
const getAdapter = () => {
var _a;
switch ((_a = options.consent) === null || _a === void 0 ? void 0 : _a.toLowerCase()) {
case 'ketch':
return ketchConsentAdapter();
case 'onetrust':
return onetrustConsentAdapter(options);
case 'shopify':
return shopifyConsentAdapter();
case 'segment':
return segmentConsentAdapter();
default:
return null;
}
};
// Initialize adapter immediately so getConsentConfig() works
const adapter = getAdapter();
/**
* Polls if user can be tracked based on consent
* @returns Promise that resolves to true if condition is met within timeout, false otherwise
*/
const checkUserCanBeTracked = () => __awaiter(void 0, void 0, void 0, function* () {
return new Promise((resolve) => {
// Checking immediately first
if (adapter === null || adapter === void 0 ? void 0 : adapter.userCanBeTracked()) {
resolve(true);
return;
}
const interval = setInterval(() => {
if (adapter === null || adapter === void 0 ? void 0 : adapter.userCanBeTracked()) {
clearInterval(interval);
resolve(true);
}
}, POLLING_INTERVAL_MS);
setTimeout(() => {
clearInterval(interval);
resolve(false);
}, TIMEOUT_MS);
});
});
/**
* Tracks consent preference changes.
* Note: Per-event consent stamping is handled in ChordAnalytics via stampConsent().
*/
const trackConsentUpdate = (updatedConsent) => __awaiter(void 0, void 0, void 0, function* () {
if (lastProcessedConsent &&
JSON.stringify(lastProcessedConsent) === JSON.stringify(updatedConsent)) {
return;
}
lastProcessedConsent = updatedConsent;
const chordAnalytics = window[options.namespace];
if (chordAnalytics &&
typeof chordAnalytics.track === 'function' &&
updatedConsent.consentCategories !== undefined) {
yield chordAnalytics.track('Consent Preferences Updated', updatedConsent);
if (options.enableLogging && options.debug) {
console.log('[Chord Analytics DEBUG]: Consent preferences updated, sent tracking event');
}
}
});
/**
* Sets up consent management by initializing the adapter and handling consent updates.
* Returns the initial consent so it can be tracked after CDP is fully ready (avoiding circular await).
*/
const setupConsentManagement = () => __awaiter(void 0, void 0, void 0, function* () {
if (!adapter)
return null;
// Set up the consent update handler first to catch any immediate updates
adapter.handleConsentUpdates((updatedConsent) => {
trackConsentUpdate(updatedConsent);
});
// Return initial consent to be tracked after CDP is fully initialized
const initialConsent = yield adapter.getCurrentConsent();
lastProcessedConsent = initialConsent;
return initialConsent;
});
/**
* Initializes consent management and sets up consent update handlers.
* Returns initial consent configuration to be tracked after CDP is fully ready,
* or null if consent setup failed or was blocked.
*/
const init = () => __awaiter(void 0, void 0, void 0, function* () {
if (options.debug && options.enableLogging) {
console.log('[Chord Analytics DEBUG]: consent init() called, adapter:', adapter ? options.consent : 'null');
}
if (adapter === null) {
console.error(`Consent management adapter "${options.consent}" is not supported.`);
return null;
}
if (options.awaitConsent) {
if (options.debug && options.enableLogging) {
console.log('[Chord Analytics DEBUG]: awaitConsent is true, checking if user can be tracked');
}
const canBeTracked = yield checkUserCanBeTracked();
if (!canBeTracked) {
if (options.debug && options.enableLogging) {
console.log('[Chord Analytics DEBUG]: User cannot be tracked, returning null');
}
return null;
}
}
// Set up consent management and wait for it to complete
try {
return yield setupConsentManagement();
}
catch (error) {
console.error('Error setting up consent management:', error);
return null;
}
});
const getConsentConfig = () => {
if (!(adapter === null || adapter === void 0 ? void 0 : adapter.getCategories) || !(adapter === null || adapter === void 0 ? void 0 : adapter.isConsentReady)) {
return undefined;
}
return {
getCategories: () => adapter.getCategories(),
isConsentReady: () => adapter.isConsentReady(),
debug: options.debug && options.enableLogging,
};
};
return {
init,
getConsentConfig,
};
};