UNPKG

@schibsted/sourcepoint

Version:

Package containing scripts used by Schibsteds' sites to integrate with Sourcepoint CMP

185 lines (157 loc) 6.57 kB
import { debug } from '../utils.js'; import { onInitPrivacyManagerView, getConsentObjectForBrands } from '../pulse/index.js'; export function createConsentApi(_window, config, type) { if (!config || !config.groupPmId) { throw new Error('groupPmId is required'); } const CMP = { ADVERTISING: 'CMP:advertising', ANALYTICS: 'CMP:analytics', MARKETING: 'CMP:marketing', PERSONALISATION: 'CMP:personalisation', PERFORMANCE_MARKETING: 'CMP:performance_marketing', }; let anySubscribers = []; const subscribers = {}; subscribers[CMP.ADVERTISING] = []; subscribers[CMP.ANALYTICS] = []; subscribers[CMP.MARKETING] = []; subscribers[CMP.PERSONALISATION] = []; subscribers[CMP.PERFORMANCE_MARKETING] = []; function getPermissionFromCache(category) { debug(`${type}: getPermissionFromCache(category=${category})`); return _window.localStorage.getItem(category); } let notifyAnyTimerFlag = null; // Variable to keep track of the timer /** * Notify all anySubscribers, debounce by 10ms to make sure it triggers only once for each change * @returns */ function throttledNotifyAnyChange() { // If there is already a timer running, return if (notifyAnyTimerFlag !== null) { return; } notifyAnyTimerFlag = setTimeout(() => { const _subscribers = anySubscribers; for (let i = 0; i < _subscribers.length; i++) { _subscribers[i](); } // Set a timer to clear the timerFlag after the specified delay notifyAnyTimerFlag = null; // Clear the timerFlag to allow the main function to be executed again }, 10); } const self = { subscribers: subscribers, consentedCallback: [], TCFCallbacks: [], showPrivacyManager: function () { debug('${type}: showPrivacyManager()'); onInitPrivacyManagerView(); _window._sp_.gdpr.loadPrivacyManagerModal(config.groupPmId); }, getPermissionSync: function (category) { debug(`${type}: getPermissionSync(category=${category})`); return getPermissionFromCache(category); }, getPermission: function (category, callback) { debug(`${type}: getPermission(category=${category})`); const unsub = self.subscribe( category, (function () { let beenCalled = false; return (permissionValue) => { if (beenCalled) { if (typeof unsub === 'function') { unsub(); } return; } beenCalled = true; callback(permissionValue); callback = function () {}; }; })() ); }, notify: (function (prevValues) { return (category, value) => { if (prevValues[category] === value) { debug(`${type}: notify(category=${category}, value=${value}) - IGNORED`); return; } throttledNotifyAnyChange(); debug(`${type}: notify(category=${category}, value=${value})`); prevValues[category] = value; const _subscribers = self.subscribers[category]; for (let i = 0; i < _subscribers.length; i++) { _subscribers[i](value); } }; })({ [CMP.ADVERTISING]: getPermissionFromCache(CMP.ADVERTISING), [CMP.ANALYTICS]: getPermissionFromCache(CMP.ANALYTICS), [CMP.MARKETING]: getPermissionFromCache(CMP.MARKETING), [CMP.PERSONALISATION]: getPermissionFromCache(CMP.PERSONALISATION), [CMP.PERFORMANCE_MARKETING]: getPermissionFromCache(CMP.PERFORMANCE_MARKETING), }), subscribe: function (category, callback) { debug(`${type}: subscribe(category=${category})`); if (!self.subscribers[category]) { console.error('Unable to subscribe - undefined consent category!'); return; } self.subscribers[category].push(callback); const value = getPermissionFromCache(category); if (value !== null) { callback(value); } return () => { self.subscribers[category] = self.subscribers[category].filter( (cb) => cb !== callback ); }; }, subscribeAny: function (callback) { debug(`subscribeAny`); anySubscribers.push(callback); return () => { anySubscribers = anySubscribers.filter((cb) => cb !== callback); }; }, getCachedOrDefaultConsentsForPulse: function (obj) { return getConsentObjectForBrands(_window, obj); }, isConsentedToAll: function (callback) { self.consentedCallback.push(callback); }, getConsentedToAllSync: function () { const consentString = `_sp_user_consent_${config.propertyId}`; const userConsentCookie = getPermissionFromCache(consentString); try { const schibstedConsents = Object.keys(localStorage).filter((e) => e.startsWith('CMP:') ); // isConsentedAll initial value is false and we return null if no consent was given if (schibstedConsents.length === 0) { return null; } const consentStatus = JSON.parse(userConsentCookie)?.gdpr?.consentStatus; const isVLChange = consentStatus?.vendorListAdditions || consentStatus?.legalBasisChanges; if (isVLChange) { return null; } const consentedValue = consentStatus?.consentedAll; return consentedValue === undefined ? null : consentedValue; } catch { return null; } }, onTcfReady: function (callback) { self.TCFCallbacks.push(callback); }, }; _window._SourcePoint_Consent_Callback = self.notify; return self; }