"use strict"; 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()); }); }; (function (mobkoi, boot, document) { const UID_COOKIE_NAME = '_mobkoi_uid'; const EQUATIV_BASE_URL = 'https://sync.smartadserver.com'; const EQUATIV_NETWORK_ID = '5290'; const MESSAGE_PREFIX = 'Render Lib Cookie Sync Script'; const SAS_UID = 'sas_uid'; const SAS_UID_MACRO = `[${SAS_UID}]`; // Store the config in a higher scope to make it accessible to other functions let cachedConfig = {}; function logDebug(message) { if (cachedConfig.debugLevel >= 3) { console.log(`${MESSAGE_PREFIX} [INFO]: ${message}`); } } function logWarn(message) { if (cachedConfig.debugLevel >= 2) { console.warn(`${MESSAGE_PREFIX} [WARN]: ${message}`); } } function logError(message) { console.error(`${MESSAGE_PREFIX} [ERROR]: ${message}`); } const runtimeEnvironment = (() => { const hostname = window.location.hostname; if (hostname.includes('local') || hostname.includes('127.0.0.1')) { return 'local'; } else if (hostname.includes('.dev.mobkoi.com')) { return 'dev'; } else if (hostname.includes('.maximus.mobkoi.com')) { return 'prod'; } else { return 'unknown'; } })(); console.debug(`Runtime environment: ${runtimeEnvironment}`); const adServerBaseUrl = (() => { switch (runtimeEnvironment) { case 'dev': return 'https://adserver.dev.mobkoi.com'; case 'local': return 'https://adserver.local.mobkoi.com'; default: return 'https://adserver.maximus.mobkoi.com'; } })(); console.debug(`Ad Server Base URL: ${adServerBaseUrl}`); const utils = { document: { createHiddenIframe(url, onIframeLoad = undefined) { const iframe = document.createElement('iframe'); iframe.width = 0; iframe.height = 0; iframe.style.display = 'none'; iframe.id = `mobkoi-sync-iframe-${Math.random().toString(16)}`; iframe.src = url; if (onIframeLoad && typeof onIframeLoad === 'function') { iframe.onload = function () { onIframeLoad(iframe); }; } document.body.appendChild(iframe); return iframe; }, }, consent: { /** * Obtains the GDPR consent string from the TCF API. * If the TCF API is not available immediately, this function will poll for the TCF API to be available. * @returns The GDPR consent string or null if not available */ getGdprConsent() { const tcfApi = utils.consent.getTcfApi(); return new Promise((resolve) => { tcfApi('getTCData', 2, function (tcData, success) { if (success && tcData && tcData.tcString) { logDebug(`GDPR consent found: "${tcData.tcString}"`); resolve(tcData.tcString); } else { logError(`TCF API available but failed to get consent data. tcData: "${JSON.stringify(tcData)}", success: "${success}"`); resolve(null); } }); }); }, /** * Get a reference to the TCF API which you call as normal. It only works * if our tag is wrapped in an iframe. If works by searching for the CMP frame by * looping through parent frames and find the "__tcfapiLocator" iframe and * obtain the tcf api from the iframe. * @see [How does the CMP Stub API works](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-stub-api-work) * @see [CMP API v2.0](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#cmp-api-v20) * @returns {Function} A function that works like window.__tcfapi */ getTcfApi() { // If the API is already available, return it if (window.__tcfapi && typeof window.__tcfapi === 'function') { return window.__tcfapi; } // Set up constants const TCF_CALL_TIMEOUT = 5000; const cmpCallbacks = {}; // Set up the message handler only once const messageHandlerSet = Symbol('tcfMessageHandlerSet'); if (!window[messageHandlerSet]) { function postMessageHandler(event) { let json = {}; try { json = typeof event.data === 'string' ? JSON.parse(event.data) : event.data; } catch (ignore) { } const payload = json.__tcfapiReturn; if (payload) { const callback = cmpCallbacks[payload.callId]; if (callback) { delete cmpCallbacks[payload.callId]; window.clearTimeout(callback.tid); callback.cb(payload.returnValue, payload.success); } } } window.addEventListener('message', postMessageHandler, false); window[messageHandlerSet] = true; } // Create and return the proxy function return function (cmd, version, callback, arg) { return __awaiter(this, void 0, void 0, function* () { // Find CMP frame if we haven't already const cmpFrame = yield utils.consent.findCmpIframe(); // If no CMP frame found, return error if (!cmpFrame) { logError('CMP Iframe not found'); callback({ msg: 'CMP not found' }, false); return; } // Create unique ID for this call const callId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; // Prepare message const msg = { __tcfapiCall: { command: cmd, parameter: arg, version: version, callId: callId, }, }; // Store callback with timeout cmpCallbacks[callId] = { cb: callback, tid: window.setTimeout(() => { delete cmpCallbacks[callId]; callback({ msg: 'CMP timeout' }, false); }, TCF_CALL_TIMEOUT), }; // Send message to CMP frame cmpFrame.postMessage(msg, '*'); }); }; }, // Try to find the CMP frame without busy waiting findCmpIframe() { return new Promise((resolve) => { // First try the current window if (window.frames['__tcfapiLocator']) { return resolve(window); } // If we're at the top window and didn't find it, it doesn't exist if (window === window.top) { return resolve(null); } // Otherwise, try to walk up the parent chain let currentFrame = window; const tryNextFrame = () => { try { // Safety check - don't go beyond top if (currentFrame === window.top) { return resolve(null); } currentFrame = currentFrame.parent; if (currentFrame.frames['__tcfapiLocator']) { return resolve(currentFrame); } // Try the next parent after a short delay setTimeout(tryNextFrame, 5); } catch (error) { // Error accessing frame likely due to same-origin policy resolve(null); } }; tryNextFrame(); }); }, }, equativ: { requestEquativSasId() { return __awaiter(this, void 0, void 0, function* () { logDebug('Start requesting Equativ SAS ID'); const equativPixelUrl = yield utils.equativ.buildEquativPixelUrl(); logDebug(`Equativ SAS ID request URL: "${equativPixelUrl}"`); if (!equativPixelUrl) { logError('Fail to generate Equativ SAS ID request URL. Abort cookie sync with Equativ.'); return Promise.resolve(null); } // Submit the pixel URL to the iframe endpoint const pixelIframeUrl = adServerBaseUrl + '/pixeliframe?' + 'pixelUrl=' + encodeURIComponent(equativPixelUrl) + `&cookieName=${SAS_UID}`; return new Promise((resolve) => { /** * Listen for messages from the iframe */ window.addEventListener('message', function (event) { switch (event.data.type) { case 'MOBKOI_PIXEL_SYNC_COMPLETE': const sasUid = event.data.syncData; logDebug('Parent window Sync completed. SAS ID:', sasUid); resolve(sasUid); break; case 'MOBKOI_PIXEL_SYNC_ERROR': logError('Parent window Sync failed:', event.data.error); resolve(null); break; } }); utils.document.createHiddenIframe(pixelIframeUrl, () => { logDebug('Pixel Iframe loaded'); }); }); }); }, buildEquativPixelUrl() { return __awaiter(this, void 0, void 0, function* () { logDebug('Generating Equativ SAS ID request URL'); const gdprConsentString = (yield utils.consent.getGdprConsent()) || ''; if (!gdprConsentString) { logWarn('GDPR consent not found'); return null; } const smartServerUrl = EQUATIV_BASE_URL + '/getuid?' + `url=` + encodeURIComponent(`${adServerBaseUrl}/getPixel?value=`) + SAS_UID_MACRO + `&gdpr_consent=${gdprConsentString}` + `&nwid=${EQUATIV_NETWORK_ID}`; return smartServerUrl; }); }, }, storage: { save(key, value) { try { const isSetCookieSuccess = utils.storage.setCookie(key, value); if (isSetCookieSuccess) { logDebug(`Item saved to cookie: "${key}"="${value}"`); return true; } const isSetLocalStorageSuccess = utils.storage.setLocalStorageItem(key, value); if (isSetLocalStorageSuccess) { logDebug(`Item saved to LocalStorage: "${key}"="${value}"`); return true; } logError(`Failed to save item to LocalStorage: "${key}"`); return false; } catch (error) { logError(`Failed to save item to storage: "${key}"`, error); } }, read(key) { const cookieValue = utils.storage.getCookie(key); if (cookieValue) { return cookieValue; } const localStorageValue = utils.storage.getLocalStorageItem(key); if (localStorageValue) { return localStorageValue; } logDebug(`Item not found in localStorage and cookie: "${key}"`); return ''; }, setLocalStorageItem(key, value) { try { localStorage.setItem(key, value); return utils.storage.getLocalStorageItem(key) === value; } catch (error) { logError(`Failed to save item to LocalStorage: "${key}"`, error); return false; } }, getLocalStorageItem(key) { return localStorage.getItem(key); }, setCookie(name, value, days = 30) { const date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); const expires = 'expires=' + date.toUTCString(); document.cookie = name + '=' + value + ';' + expires + ';path=/;SameSite=None;Secure'; return utils.storage.getCookie(name) === value; }, getCookie(name) { // Construct the name of the cookie to search for const nameEquals = name + '='; const cookiesArray = document.cookie.split(';'); for (let i = 0; i < cookiesArray.length; i++) { let cookie = cookiesArray[i]; // Remove leading spaces from the cookie string while (cookie.charAt(0) === ' ') { cookie = cookie.substring(1, cookie.length); } // Check if the current cookie starts with the name we are looking for if (cookie.indexOf(nameEquals) === 0) { // Return the value of the cookie (excluding the name and '=') return cookie.substring(nameEquals.length, cookie.length); } } // Return an empty string if the cookie was not found return ''; }, }, }; return function (config, payload) { // Store the config in a higher scope to make it accessible to other functions cachedConfig = Object.assign({ debugLevel: 0 }, config); console.log('Mobkoi Script Debug level:', cachedConfig.debugLevel); logDebug('Config:', cachedConfig); logDebug(new Date().toTimeString().substring(0, 8) + '.000 [MOBKOI] Bootstrapping ' + (cachedConfig.auctionDetails ? 'auction' : 'direct')); boot.endpoint = cachedConfig.host; //set the endpoint for lib-init logging let uidPromise = null; const existingUid = utils.storage.read(UID_COOKIE_NAME); if (!existingUid) { uidPromise = utils.equativ.requestEquativSasId().then((sasId) => { if (!sasId) { logError('Fail at requesting Equativ SAS ID'); return; } if (sasId === SAS_UID_MACRO) { logError('Fail at requesting Equativ SAS ID. Equativ did not replace the SAS UID macro.'); return; } utils.storage.save(UID_COOKIE_NAME, sasId); logDebug(`Equativ SAS ID set to cookie: "${sasId}"`); return sasId; }); } else { logDebug('Equativ SAS ID already exists'); logDebug(`Equativ SAS ID: "${existingUid}". Type: ${typeof existingUid}`); } if (!mobkoi.loaded) { mobkoi.push({ endpoint: cachedConfig.host, debug: Number(cachedConfig.debugLevel || 0), }); document.querySelector('HEAD').appendChild(Object.assign(document.createElement('script'), { type: 'application/javascript', async: 1, src: cachedConfig.libPath, })); } mobkoi.push([ 'tag', document.currentScript, cachedConfig.tagId, cachedConfig.publisherOptionsString, { options: cachedConfig.options, extras: { iid: cachedConfig.impressionId, idh: cachedConfig.encodeImpressionId, aud: cachedConfig.aud || 0, getuid() { return __awaiter(this, void 0, void 0, function* () { if (uidPromise) { return yield uidPromise; } else { return utils.storage.read(UID_COOKIE_NAME); } }); }, }, }, payload, ]); }; })((window.MOBKOI = window.MOBKOI || []), (window.MOBKOI_BOOT = window.MOBKOI_BOOT || {}), document)({"host":"https://adserver.maximus.mobkoi.com","libPath":"https://storage.googleapis.com/mobkoi-formats/mobkoi-lib-4.2.0.js","tagId":"DF2E363C","impressionId":"1019be18-afd3-4b14-a225-1a9e27f9d2a9","VERSION":"3.0.0","st":"1749597150732","debugLevel":1,"publisherOptionsString":{"test":0,"debug":0},"options":{"debug":1,"test":1,"label":"Mobkoi Dev"}}, null); //# sourceMappingURL=render-lib-cookie-sync.template.js.map