UNPKG

@chordcommerce/analytics

Version:

Chord Commerce event tracking

148 lines (147 loc) 6.49 kB
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, }; };