/** * IIFE Pega mashup helper functions * Input initialization * VisitorID Cookie Synchronization: Handles both returning users and first-time visitors with consent flow */ (function () { "use strict"; // Configuration const CONFIG = { COOKIE_NAME: "vid", MAX_WAIT_TIME: 30000, // 30 seconds INITIAL_CHECK_INTERVAL: 100, // 100ms MAX_CHECK_INTERVAL: 1000, // 1 second MASHUP_GADGET_NAME: "PegaGadget", VISITORID_PROPERTY_REF: "pyWorkPage.Lead.VisitorID", }; /** * Get query param value with decoding */ function getQueryParam(name) { var results = new RegExp("[?&]" + name + "=([^&#]*)").exec( window.location.href ); if (results == null) { return null; } else { return decodeURI(results[1]) || 0; } } /** * Get cookie value with decoding */ function getCookie(name) { try { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) { const cookieValue = parts.pop().split(";").shift(); return decodeURIComponent(cookieValue); } } catch (error) { console.error("Error reading cookie:", error); } return null; } /** * Expose dataFromPage globally for Pega mashup * Referenced via data-pega-event-onpagedata="dataFromPage" * Initializes input param values for mashup */ window.dataFromPage = function (token) { const logPrefix = "[dataFromPage] -"; console.debug(logPrefix, "Initialize input:", token); switch (token) { case "SourceAdID": return getQueryParam("chorid"); case "SourceChannel": return getQueryParam("em_src"); case "SourceCampaign": return getQueryParam("em_cmp"); case "VisitorID": return getCookie(CONFIG.COOKIE_NAME); default: console.error(logPrefix, "Unknown token:", token); return "Unknown token"; } }; /* START VisitorID handling for the first-time visitor*/ /** * Send VisitorID to Pega mashup (for first-time visitors) */ function sendVisitorIDToPega(visitorID) { const logPrefix = "[sendVisitorIDToPega] -"; console.debug( logPrefix, "Sending VisitorID to Pega...", "VisitorID:", visitorID ); try { if (window.pega && window.pega.web && window.pega.web.api) { window.pega.web.api.doAction( CONFIG.MASHUP_GADGET_NAME, "setGadgetData", CONFIG.VISITORID_PROPERTY_REF, visitorID, { callback: function (response) { if (response) { console.debug( logPrefix, "VisitorID successfully synchronized to Pega" ); } else { console.error( logPrefix, "Failed to set VisitorID in Pega:", response ); } }, } ); return true; } else { console.warn(logPrefix, "Pega API not available"); return false; } } catch (error) { console.error(logPrefix, "Error sending VisitorID to Pega:", error); return false; } } /** * Wait for cookie with exponential backoff */ function waitForCookie(callback, timeout) { const logPrefix = "[waitForCookie] -"; const startTime = Date.now(); console.debug( logPrefix, "Waiting for VisitorID cookie...", "startTime:", startTime, "timeout:", timeout ); let interval = CONFIG.INITIAL_CHECK_INTERVAL; function check() { const visitorID = getCookie(CONFIG.COOKIE_NAME); if (visitorID) { console.debug(logPrefix, "VisitorID cookie detected"); callback(visitorID); return; } if (Date.now() - startTime > timeout) { console.warn(logPrefix, "VisitorID cookie wait timeout"); return; } // Exponential backoff to reduce CPU usage interval = Math.min(interval * 1.2, CONFIG.MAX_CHECK_INTERVAL); setTimeout(check, interval); } check(); } /** * Wait for Pega mashup with exponential backoff */ function waitForMashupReady(callback, timeout) { const logPrefix = "[waitForMashupReady] -"; const startTime = Date.now(); console.debug( logPrefix, "Waiting for mashup...", "startTime:", startTime, "timeout:", timeout ); let interval = CONFIG.INITIAL_CHECK_INTERVAL; function check() { // Check if Pega API is available if (window.pega && window.pega.web && window.pega.web.api) { console.log(logPrefix, "Pega mashup ready"); callback(); return; } if (Date.now() - startTime > timeout) { console.warn(logPrefix, "Pega mashup ready check timeout"); return; } interval = Math.min(interval * 1.2, CONFIG.MAX_CHECK_INTERVAL); setTimeout(check, interval); } check(); } /** * Handle first-time visitor scenario using polling (fallback) */ function handleFirstTimeVisitorFallback() { const logPrefix = "[handleFirstTimeVisitorFallback] -"; console.debug( logPrefix, "First-time visitor detected - waiting for consent and cookie" ); // Poll for cookie appearance waitForCookie(function (visitorID) { // Just to be sure that pega mashup is ready waitForMashupReady(function () { sendVisitorIDToPega(visitorID); }, CONFIG.MAX_WAIT_TIME); }, CONFIG.MAX_WAIT_TIME); } /** * Handle first-time visitor scenario using Cookie Store API */ function handleFirstTimeVisitorModern() { const logPrefix = "[handleFirstTimeVisitorModern] -"; console.debug( logPrefix, "First-time visitor detected - using Cookie Store API to monitor cookie" ); // Listen for cookie changes (event-driven, no polling!) cookieStore.addEventListener("change", async (event) => { for (const cookie of event.changed) { if (cookie.name === CONFIG.COOKIE_NAME) { const cookieValue = decodeURIComponent(cookie.value); console.debug( logPrefix, "VisitorID cookie detected via Cookie Store API", "VisitorID:", cookieValue ); // Wait for Pega and send waitForMashupReady(function () { sendVisitorIDToPega(cookieValue); }, CONFIG.MAX_WAIT_TIME); break; } } }); } /** * Set a random thread name for mashup */ function setMashupThreadName(mashupDiv) { const logPrefix = "[setMashupThreadName] -"; if (mashupDiv) { const threadName = "Whitepaper_" + Math.random().toString(36).slice(2, 2 + 10); mashupDiv.setAttribute('data-pega-threadname', threadName); console.debug(logPrefix, "ThreadName set to:", threadName); } } /** * Set class name for mashup */ function setMashupClassName(mashupDiv) { const logPrefix = "[setMashupClassName] -"; if (mashupDiv) { try { const paramsRaw = mashupDiv.getAttribute('data-pega-action-param-parameters'); if (!paramsRaw) { console.warn(logPrefix, "data-pega-action-param-parameters attribute not found"); return; } const params = JSON.parse(paramsRaw); const contentID = params.ContentID; if (!contentID) { console.warn(logPrefix, "ContentID not found in parameters"); return; } const suffix = contentID.slice(contentID.lastIndexOf('-') + 1); if (!suffix) { console.warn(logPrefix, "Could not extract suffix from ContentID:", contentID); return; } const className = mashupDiv.getAttribute('data-pega-action-param-classname'); if (!className) { console.warn(logPrefix, "data-pega-action-param-classname attribute not found"); return; } const classLastDashIndex = className.lastIndexOf('-'); if (classLastDashIndex === -1) { console.warn(logPrefix, "No dash found in data-pega-action-param-classname:", className); return; } const newClassName = className.slice(0, classLastDashIndex + 1) + suffix; mashupDiv.setAttribute('data-pega-action-param-classname', newClassName); console.debug(logPrefix, "data-pega-action-param-classname updated to:", newClassName); } catch (error) { console.error(logPrefix, "Error overriding data-pega-action-param-classname:", error); } } } /** * Init mashup div attributes */ function initMashup() { const logPrefix = "[initMashup] -"; console.debug(logPrefix, "Start"); const mashupDiv = document.querySelector(`div[data-pega-gadgetname="${CONFIG.MASHUP_GADGET_NAME}"]`); if (mashupDiv) { setMashupThreadName(mashupDiv) setMashupClassName(mashupDiv); } else { console.warn(logPrefix, "Mashup div not found!"); } console.debug(logPrefix, "End"); } /** * Main initialization */ function init() { const logPrefix = "[init] -"; console.debug(logPrefix, "Initializing"); initMashup(); const existingVisitorID = getCookie(CONFIG.COOKIE_NAME); if (existingVisitorID) { // RETURNING USER: Cookie exists // Pega will receive it via data-pega-event-onpagedata="dataFromPage" console.debug( logPrefix, "Returning user - VisitorID available for mashup initialization, existingVisitorID:", existingVisitorID ); } else { // FIRST-TIME VISITOR: Cookie doesn't exist yet if ("cookieStore" in window) { handleFirstTimeVisitorModern(); } else { console.warn( logPrefix, "Cookie Store API not available, using polling fallback" ); handleFirstTimeVisitorFallback(); } } } // Start when DOM is ready if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } /* END VisitorID handling for the first-time visitor*/ })(); //static-content-hash-trigger-GCC