<!-- OneTrust Cookies Consent Notice start for lightyear.cloud --> <script src="https://cdn-ukwest.onetrust.com/scripttemplates/otSDKStub.js" type="text/javascript" charset="UTF-8" data-domain-script="0197a69a-8630-7f3b-bd4c-caeb8c6dff1c" ></script> <script type="text/javascript"> (function () { // --- your allowlist of gated vendors + required OneTrust groups --- var RULES = [ // VWO { test: /\/\/dev\.visualwebsiteoptimizer\.com\//i, groups: ["C0003"] }, // YouTube - C0003 { test: /\/\/www\.youtube\.com\//i, groups: ["C0003"] }, { test: /\/\/youtube\.com\//i, groups: ["C0003"] }, { test: /\/\/www\.youtube-nocookie\.com\//i, groups: ["C0003"] }, { test: /\/\/youtubei\.googleapis\.com\//i, groups: ["C0003"] }, { test: /\/\/i\.ytimg\.com\//i, groups: ["C0003"] }, { test: /\/\/s\.ytimg\.com\//i, groups: ["C0003"] }, { test: /\/\/yt3\.ggpht\.com\//i, groups: ["C0003"] }, // Vimeo - C0003 { test: /\/\/player\.vimeo\.com\//i, groups: ["C0003"] }, { test: /\/\/vimeo\.com\//i, groups: ["C0003"] }, { test: /\/\/f\.vimeocdn\.com\//i, groups: ["C0003"] }, { test: /\/\/i\.vimeocdn\.com\//i, groups: ["C0003"] }, // Calendly - C0003 //{ test: /\/\/calendly\.com\//i, groups: ["C0003"] }, //{ test: /\/\/assets\.calendly\.com\//i, groups: ["C0003"] }, //{ test: /\/\/cdn\.calendly\.com\//i, groups: ["C0003"] }, // Existing C0004 domains { test: /\/\/munchkin\.marketo\.net\//i, groups: ["C0004"] }, { test: /\/\/cdn\.bizible\.com\//i, groups: ["C0004"] }, { test: /\/\/bizible\.com\//i, groups: ["C0004"] }, { test: /\/\/cdn\.bizibly\.com\//i, groups: ["C0004"] }, { test: /\/\/adobedc\.net\//i, groups: ["C0004"] }, { test: /\/\/a\.omappapi\.com\//i, groups: ["C0004"] }, { test: /\/\/tracker\.gaconnector\.com\//i, groups: ["C0004"] }, { test: /\/\/static\.hotjar\.com\//i, groups: ["C0004"] }, { test: /\/\/js\.hs\-scripts\.com\//i, groups: ["C0004"] }, { test: /\/scripts\/custom\-gclid\.js\//i, groups: ["C0004"] }, // HubSpot - C0004 { test: /\/\/js\.hubspot\.com\//i, groups: ["C0004"] }, { test: /\/\/js\.hsforms\.net\//i, groups: ["C0004"] }, { test: /\/\/js\.hscta\.net\//i, groups: ["C0004"] }, { test: /\/\/js\.hsadspixel\.net\//i, groups: ["C0004"] }, { test: /\/\/js\.hs\-analytics\.net\//i, groups: ["C0004"] }, { test: /\/\/js\.hs\-banner\.com\//i, groups: ["C0004"] }, // Bing - C0004 { test: /\/\/bat\.bing\.com\//i, groups: ["C0004"] }, { test: /\/\/clarity\.ms\//i, groups: ["C0004"] }, { test: /\/\/c\.bing\.com\//i, groups: ["C0004"] }, { test: /\/\/www\.bing\.com\/api\//i, groups: ["C0004"] }, // MSN - C0004 { test: /\/\/c\.msn\.com\//i, groups: ["C0004"] }, { test: /\/\/www\.msn\.com\/api\//i, groups: ["C0004"] }, // LinkedIn - C0005 { test: /\/\/snap\.licdn\.com\//i, groups: ["C0005"] }, { test: /\/\/px\.ads\.linkedin\.com\//i, groups: ["C0005"] }, { test: /\/\/www\.linkedin\.com\/px\//i, groups: ["C0005"] }, { test: /\/\/platform\.linkedin\.com\//i, groups: ["C0005"] }, ]; function matchRule(src) { for (var i = 0; i < RULES.length; i++) if (RULES[i].test.test(src)) return RULES[i]; return null; } function hasConsent(req) { var g = (window.OneTrustActiveGroups || window.OnetrustActiveGroups || "").split(","); return req.every(function (id) { return g.indexOf(id) !== -1; }); } function isMunchkinNode(node) { var src = node.getAttribute("data-gated-src") || node.getAttribute("src") || ""; return /\/\/munchkin\.marketo\.net\//i.test(src); } // --- Restore a blocked script element (preserve attrs + handlers) --- function restoreScript(node) { var replayQ = null; // --- Munchkin-specific handoff: remove stub so real lib can install itself if (isMunchkinNode(node) && window.Munchkin && window.Munchkin.__otStub) { replayQ = window.Munchkin.__q ? window.Munchkin.__q.slice() : null; try { delete window.Munchkin; } catch (e) { window.Munchkin = undefined; } } var s = document.createElement("script"); // copy common attrs [ "src", "async", "defer", "noModule", "crossorigin", "referrerpolicy", "integrity", "nonce", ].forEach(function (a) { var v = node.getAttribute(a); if (v !== null) s.setAttribute(a, v); }); // restore type (module vs classic). If plain, default to classic JS. var t = node.getAttribute("type"); s.type = t && t !== "text/plain" ? t : "text/javascript"; // copy handlers if any were set as properties if (node.onload) s.onload = node.onload; if (node.onerror) s.onerror = node.onerror; if (node.onreadystatechange) s.onreadystatechange = node.onreadystatechange; // inline support (rare for your RULES) if (node.text && !s.src) s.text = node.text; // when real script finishes loading, replay any queued calls if (isMunchkinNode(node) && replayQ) { s.addEventListener("load", function () { if (window.Munchkin && typeof window.Munchkin.init === "function") { replayQ.forEach(function (item) { var method = item[0], args = item[1] || []; if (typeof window.Munchkin[method] === "function") { window.Munchkin[method].apply(window.Munchkin, args); } }); } }); } node.replaceWith(s); } function restoreAllEligible() { // Only restore nodes whose vendor is allowed now var nodes = document.querySelectorAll( 'script.optanon-blocked[type="text/plain"][data-gated-src]' ); for (var i = 0; i < nodes.length; i++) { var n = nodes[i]; var src = n.getAttribute("data-gated-src") || n.getAttribute("src") || ""; var rule = matchRule(src); if (rule && hasConsent(rule.groups)) restoreScript(n); } } // --- Iframe and Video blocking for video platforms --- var IFRAME_RULES = [ { test: /youtube\.com|youtube-nocookie\.com|youtu\.be/i, groups: ["C0003"] }, { test: /vimeo\.com|player\.vimeo\.com/i, groups: ["C0003"] }, //{ test: /calendly\.com/i, groups: ["C0003"] } ]; var VIDEO_RULES = [ { test: /youtube\.com|youtube-nocookie\.com|youtu\.be/i, groups: ["C0003"] }, { test: /vimeo\.com|player\.vimeo\.com|vimeocdn\.com/i, groups: ["C0003"] }, { test: /wistia\.com|fast\.wistia/i, groups: ["C0003"] }, { test: /brightcove\.com|players\.brightcove/i, groups: ["C0003"] }, { test: /vidyard\.com/i, groups: ["C0003"] }, { test: /jwplayer\.com|jwpcdn\.com/i, groups: ["C0003"] }, { test: /cloudinary\.com/i, groups: ["C0003"] }, { test: /streamable\.com/i, groups: ["C0003"] } ]; function matchIframeRule(src) { for (var i = 0; i < IFRAME_RULES.length; i++) if (IFRAME_RULES[i].test.test(src)) return IFRAME_RULES[i]; return null; } function matchVideoRule(src) { for (var i = 0; i < VIDEO_RULES.length; i++) if (VIDEO_RULES[i].test.test(src)) return VIDEO_RULES[i]; return null; } // Generate unique ID for each video var videoIdCounter = 0; // Function to create placeholder element with unique ID function createPlaceholder(type, uniqueId) { var placeholder = document.createElement("div"); placeholder.className = "optanon-video-placeholder"; if (uniqueId) { placeholder.id = "optanon-placeholder-" + uniqueId; // Add unique ID for videos } placeholder.style.cssText = "position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;padding:20px;background:rgba(0,0,0,0.8);color:white;border-radius:5px;z-index:10;"; placeholder.innerHTML = "<p>Video Consent Required</p><p>This " + type + " requires your consent to load content from third-party providers.</p><button onclick='window.OneTrust.ToggleInfoDisplay()' style='margin-top: 15px; padding:12px 24px;background:#E4173F;color:white;border:none;border-radius:24px;cursor:pointer;font-size:16px;cursor:pointer;'>Manage Preferences</button>"; return placeholder; } // Function to block HTML5 video element function blockVideo(video) { var src = video.getAttribute("src") || video.getAttribute("data-src") || ""; // Check all source elements within the video tag var sources = video.querySelectorAll("source"); var needsBlocking = false; var rule = null; // Check main video src if (src) { rule = matchVideoRule(src); if (rule) needsBlocking = true; } // Check source elements for (var i = 0; i < sources.length; i++) { var sourceSrc = sources[i].getAttribute("src") || ""; var sourceRule = matchVideoRule(sourceSrc); if (sourceRule) { needsBlocking = true; rule = sourceRule; break; } } // Also check for third-party video platforms even without explicit rules if (!needsBlocking && video.hasAttribute("data-require-consent")) { needsBlocking = true; rule = { groups: ["C0003"] }; } if (!needsBlocking) return; if (rule && hasConsent(rule.groups)) return; // Check if already blocked if (video.hasAttribute("data-blocked")) return; // Generate unique ID for this video var uniqueId = ++videoIdCounter; // Store original sources and block the video video.setAttribute("data-consent-required", rule.groups.join(",")); video.setAttribute("data-video-unique-id", uniqueId); video.className += (video.className ? " " : "") + "optanon-blocked-video"; // Store and remove sources if (video.src) { video.setAttribute("data-blocked-src", video.src); video.removeAttribute("src"); } // Store source elements data and remove them var sourcesData = []; for (var j = 0; j < sources.length; j++) { sourcesData.push({ src: sources[j].src, type: sources[j].type, media: sources[j].media }); } if (sourcesData.length > 0) { video.setAttribute("data-blocked-sources", JSON.stringify(sourcesData)); // Remove source elements while (video.firstChild) { video.removeChild(video.firstChild); } } // Add placeholder styling video.style.position = "relative"; video.style.backgroundColor = "#f0f0f0"; video.style.minHeight = video.style.height || "315px"; video.style.minWidth = video.style.width || "560px"; // Disable video controls and autoplay video.removeAttribute("autoplay"); video.removeAttribute("controls"); video.setAttribute("data-blocked", "true"); // Create placeholder with unique ID var placeholder = createPlaceholder("video", uniqueId); // Position parent if needed if (video.parentElement) { if (video.parentElement.style.position !== "absolute" && video.parentElement.style.position !== "relative" && video.parentElement.style.position !== "fixed") { video.parentElement.style.position = "relative"; } video.parentElement.appendChild(placeholder); video.setAttribute("data-placeholder-id", placeholder.id); } } // Function to restore blocked videos function restoreBlockedVideos() { var videos = document.querySelectorAll("video.optanon-blocked-video"); for (var i = 0; i < videos.length; i++) { var video = videos[i]; var requiredGroups = (video.getAttribute("data-consent-required") || "").split(","); if (hasConsent(requiredGroups)) { // Remove placeholder using the stored ID var placeholderId = video.getAttribute("data-placeholder-id"); if (placeholderId) { var placeholder = document.getElementById(placeholderId); if (placeholder) { placeholder.remove(); } } // Also try to remove any placeholder in the parent (fallback) if (video.parentElement) { var allPlaceholders = video.parentElement.querySelectorAll(".optanon-video-placeholder"); allPlaceholders.forEach(function(p) { p.remove(); }); } // Restore main src var blockedSrc = video.getAttribute("data-blocked-src"); if (blockedSrc) { video.src = blockedSrc; video.removeAttribute("data-blocked-src"); } // Restore source elements var sourcesData = video.getAttribute("data-blocked-sources"); if (sourcesData) { try { var sources = JSON.parse(sourcesData); for (var j = 0; j < sources.length; j++) { var source = document.createElement("source"); source.src = sources[j].src; if (sources[j].type) source.type = sources[j].type; if (sources[j].media) source.media = sources[j].media; video.appendChild(source); } } catch (e) { console.error("Error parsing video sources:", e); } video.removeAttribute("data-blocked-sources"); } // Restore video attributes video.setAttribute("controls", "true"); video.removeAttribute("data-blocked"); video.removeAttribute("data-consent-required"); video.removeAttribute("data-placeholder-id"); video.removeAttribute("data-video-unique-id"); video.className = video.className.replace("optanon-blocked-video", "").trim(); // Clear inline styles that were added for blocking video.style.backgroundColor = ""; video.style.minHeight = ""; video.style.minWidth = ""; video.style.position = ""; // Reload video video.load(); } } // Clean up any orphaned placeholders (safety measure) var orphanedPlaceholders = document.querySelectorAll(".optanon-video-placeholder"); orphanedPlaceholders.forEach(function(placeholder) { // Check if there's a corresponding blocked video var uniqueId = placeholder.id.replace("optanon-placeholder-", ""); var correspondingVideo = document.querySelector('[data-video-unique-id="' + uniqueId + '"]'); // If no corresponding blocked video exists, or if consent is granted, remove the placeholder if (!correspondingVideo || !correspondingVideo.hasAttribute("data-blocked")) { placeholder.remove(); } }); } // Function to block iframe function blockIframe(iframe) { var src = iframe.getAttribute("src") || iframe.getAttribute("data-src") || ""; var rule = matchIframeRule(src); if (!rule) return; // not a targeted iframe if (hasConsent(rule.groups)) return; // consent already granted // Store original src and block the iframe if (iframe.src) { iframe.setAttribute("data-blocked-src", iframe.src); iframe.removeAttribute("src"); } iframe.setAttribute("data-consent-required", rule.groups.join(",")); iframe.className += (iframe.className ? " " : "") + "optanon-blocked-iframe"; // Add placeholder styling iframe.style.backgroundColor = "#f0f0f0"; iframe.style.minHeight = iframe.style.minHeight || "315px"; // Create placeholder message var placeholder = createPlaceholder("video"); // If iframe has parent, add placeholder if (iframe.parentElement && iframe.parentElement.style.position !== "absolute" && iframe.parentElement.style.position !== "relative") { iframe.parentElement.style.position = "relative"; } if (iframe.parentElement) { iframe.parentElement.appendChild(placeholder); iframe.setAttribute("data-placeholder-id", placeholder.className); } } // Function to restore blocked iframes function restoreBlockedIframes() { var iframes = document.querySelectorAll("iframe.optanon-blocked-iframe"); for (var i = 0; i < iframes.length; i++) { var iframe = iframes[i]; var blockedSrc = iframe.getAttribute("data-blocked-src"); var requiredGroups = (iframe.getAttribute("data-consent-required") || "").split(","); if (blockedSrc && hasConsent(requiredGroups)) { // Remove placeholder var placeholder = iframe.parentElement ? iframe.parentElement.querySelector(".optanon-video-placeholder") : null; if (placeholder) placeholder.remove(); // Restore iframe iframe.src = blockedSrc; iframe.removeAttribute("data-blocked-src"); iframe.removeAttribute("data-consent-required"); iframe.className = iframe.className.replace("optanon-blocked-iframe", "").trim(); iframe.style.backgroundColor = ""; iframe.style.minHeight = ""; } } } // Override createElement to catch dynamically created iframes var originalCreateElement = document.createElement; document.createElement = function(tagName) { var element = originalCreateElement.call(document, tagName); if (tagName.toLowerCase() === "iframe") { // Use setter to intercept src assignment var srcDescriptor = Object.getOwnPropertyDescriptor(element, "src") || Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "src"); Object.defineProperty(element, "src", { get: function() { return this.getAttribute("src"); }, set: function(value) { var rule = matchIframeRule(value); if (rule && !hasConsent(rule.groups)) { this.setAttribute("data-blocked-src", value); this.className += (this.className ? " " : "") + "optanon-blocked-iframe"; this.setAttribute("data-consent-required", rule.groups.join(",")); } else { srcDescriptor.set.call(this, value); } }, configurable: true }); } return element; }; // Hook DOM insertions for iframes and videos ["appendChild", "insertBefore", "replaceChild"].forEach(function (m) { var orig = Node.prototype[m]; Node.prototype[m] = function (child) { if (child) { if (child.tagName === "IFRAME") { try { blockIframe(child); } catch (e) {} } else if (child.tagName === "VIDEO") { try { blockVideo(child); } catch (e) {} } } var result = orig.apply(this, arguments); // Also check after insertion in case src is set after adding to DOM if (child) { if (child.tagName === "IFRAME") { setTimeout(function() { blockIframe(child); }, 0); } else if (child.tagName === "VIDEO") { setTimeout(function() { blockVideo(child); }, 0); } } return result; }; }); // Monitor existing iframes and videos on page load function blockExistingMedia() { var iframes = document.querySelectorAll("iframe"); for (var i = 0; i < iframes.length; i++) { blockIframe(iframes[i]); } var videos = document.querySelectorAll("video"); for (var j = 0; j < videos.length; j++) { blockVideo(videos[j]); } } // MutationObserver for iframes and videos added via innerHTML or other methods var mediaObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { mutation.addedNodes.forEach(function(node) { if (node.tagName === "IFRAME") { blockIframe(node); } else if (node.tagName === "VIDEO") { blockVideo(node); } // Check for iframes and videos in added subtree if (node.querySelectorAll) { var iframes = node.querySelectorAll("iframe"); for (var i = 0; i < iframes.length; i++) { blockIframe(iframes[i]); } var videos = node.querySelectorAll("video"); for (var j = 0; j < videos.length; j++) { blockVideo(videos[j]); } } }); }); }); // Start observing when DOM is ready if (document.body) { mediaObserver.observe(document.body, { childList: true, subtree: true }); blockExistingMedia(); } else { document.addEventListener("DOMContentLoaded", function() { mediaObserver.observe(document.body, { childList: true, subtree: true }); blockExistingMedia(); }); } // --- Block Bizible/Marketo pixel tracking images --- function blockTrackingPixels() { // Block img elements that are tracking pixels var images = document.querySelectorAll('img'); images.forEach(function(img) { var src = img.src || img.getAttribute('src') || ''; if (src.includes('bizible.com') || src.includes('bizibly.com') || src.includes('adobedc.net')) { if (!hasConsent(['C0004'])) { img.setAttribute('data-blocked-src', src); img.removeAttribute('src'); img.style.display = 'none'; } } }); } // Monitor for tracking pixels var pixelObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { mutation.addedNodes.forEach(function(node) { if (node.tagName === 'IMG') { var src = node.src || node.getAttribute('src') || ''; if (src.includes('bizible.com') || src.includes('bizibly.com') || src.includes('adobedc.net')) { if (!hasConsent(['C0004'])) { node.setAttribute('data-blocked-src', src); node.removeAttribute('src'); node.style.display = 'none'; } } } }); }); }); if (document.body) { pixelObserver.observe(document.body, { childList: true, subtree: true }); blockTrackingPixels(); } // --- Handle custom video implementations with click-to-load --- function interceptVideoButtons() { // Find all elements that look like they'll load a video on click var videoContainers = document.querySelectorAll('.js-video[data-video-url], .video[data-video-url]'); videoContainers.forEach(function(container) { var videoUrl = container.getAttribute('data-video-url'); if (!videoUrl) return; // Check if this is a YouTube or Vimeo URL that needs consent var needsConsent = false; var requiredGroups = []; if (/youtube\.com|youtu\.be/.test(videoUrl)) { needsConsent = true; requiredGroups = ["C0003"]; } else if (/vimeo\.com/.test(videoUrl)) { needsConsent = true; requiredGroups = ["C0003"]; } if (!needsConsent || hasConsent(requiredGroups)) return; // Find the play button within this container var playButton = container.querySelector('.js-videoPlay, button[type="button"]'); if (!playButton) return; // Store original click handler if it exists var originalOnclick = playButton.onclick; playButton.setAttribute('data-consent-required', requiredGroups.join(',')); playButton.setAttribute('data-original-video-url', videoUrl); // Replace click handler with consent check playButton.onclick = function(e) { e.preventDefault(); e.stopPropagation(); if (hasConsent(requiredGroups)) { // Restore original behavior if consent granted if (originalOnclick) { originalOnclick.call(this, e); } else { // Try to trigger the video load manually if no onclick was stored this.click(); } } else { // Show consent modal showVideoConsentModal(container, requiredGroups); } return false; }; // Also intercept addEventListener for this button var originalAddEventListener = playButton.addEventListener; playButton.addEventListener = function(type, listener, options) { if (type === 'click') { // Wrap the click listener var wrappedListener = function(e) { if (!hasConsent(requiredGroups)) { e.preventDefault(); e.stopPropagation(); showVideoConsentModal(container, requiredGroups); return false; } return listener.call(this, e); }; originalAddEventListener.call(this, type, wrappedListener, options); } else { originalAddEventListener.call(this, type, listener, options); } }; }); } // Function to show consent modal for custom video implementations function showVideoConsentModal(container, requiredGroups) { // Check if modal already exists var existingModal = container.querySelector('.optanon-video-consent-modal'); if (existingModal) { existingModal.style.display = 'block'; return; } // Create consent modal overlay var modal = document.createElement('div'); modal.className = 'optanon-video-consent-modal'; modal.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);display:flex;align-items:center;justify-content:center;z-index:1000;'; var modalContent = document.createElement('div'); modalContent.style.cssText = 'background:white;padding:30px;border-radius:8px;text-align:center;max-width:400px; margin: 10% auto;'; modalContent.innerHTML = '<h3 style="margin:0 0 15px 0;color:#11111;">Video consent required</h3>' + '<p style="margin:0 0 20px 0;color:#11111;">This video requires your consent to load content from third-party providers.</p>' + '<button onclick="window.OneTrust.ToggleInfoDisplay()" style="padding:12px 24px;background:#E4173F;color:white;border:none;border-radius:24px;cursor:pointer;font-size:16px;margin-right:10px;">Manage preferences</button>' + '<button onclick="this.closest(\'.optanon-video-consent-modal\').style.display=\'none\'" style="padding:12px 24px;background:#F7F7F7;color:#11111;border:none;border-radius:24px;cursor:pointer;font-size:16px;">Cancel</button>'; modal.appendChild(modalContent); container.style.position = 'relative'; container.appendChild(modal); } // Re-check video buttons after consent changes function recheckVideoButtons() { var buttons = document.querySelectorAll('[data-consent-required]'); buttons.forEach(function(button) { var requiredGroups = (button.getAttribute('data-consent-required') || '').split(','); if (hasConsent(requiredGroups)) { // Remove consent modal if it exists var container = button.closest('.js-video, .video'); if (container) { var modal = container.querySelector('.optanon-video-consent-modal'); if (modal) modal.remove(); } } }); } // Initialize video button interception if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { setTimeout(interceptVideoButtons, 100); // Small delay to ensure other scripts have initialized }); } else { setTimeout(interceptVideoButtons, 100); } // Re-run interception periodically to catch dynamically added videos setInterval(interceptVideoButtons, 2000); // --- Hook DOM insertions for dynamically-added scripts (your original bit) --- function handleScript(node) { var src = node.getAttribute("src") || ""; var rule = matchRule(src); if (!rule) return; // not targeted if (hasConsent(rule.groups)) return; // consent already granted node.setAttribute("data-gated-src", src); node.type = "text/plain"; node.className += (node.className ? " " : "") + "optanon-blocked"; } ["appendChild", "insertBefore"].forEach(function (m) { var orig = Node.prototype[m]; Node.prototype[m] = function (child) { if (child && child.tagName === "SCRIPT") { try { handleScript(child); } catch (e) {} } return orig.apply(this, arguments); }; }); // --- NEW: Patch document.write / writeln (covers your example) --- function gateHtml(html) { // normalize (strip surrounding whitespace) var s = String(html); // Find <script ... src="..."> and if URL matches a RULE without consent, // rewrite to type="text/plain" and mark for later restore. // This regex is intentionally simple; it handles typical cases. return s.replace( /<script\b([^>]*?)\bsrc\s*=\s*(['"])([^'"]+)\2([^>]*)>(?:<\/script>)?/gi, function (_m, pre, q, src, post) { var rule = matchRule(src || ""); if (!rule || hasConsent(rule.groups)) return _m; // leave as-is // ensure we keep original attrs, add our markers, and suppress execution var attrs = (pre || "") + " src=" + q + src + q + (post || ""); // remove existing type if present; we'll set text/plain attrs = attrs.replace(/\btype\s*=\s*(['"])[^'"]*\1/gi, ""); attrs += ' type="text/plain" class="optanon-blocked" data-gated-src="' + src.replace(/"/g, "&quot;") + '"'; return "\<script " + attrs + "\>\<\/script\>"; } ); } ["write", "writeln"].forEach(function (m) { var orig = document[m]; document[m] = function () { // Join arguments (browsers allow multiple) var html = Array.prototype.join.call(arguments, ""); var gated = gateHtml(html); return orig.call(document, gated); }; }); // Cookie blocking - Enhanced to catch iframe cookies const originalCookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie'); // Block postMessage from YouTube iframes before consent const originalPostMessage = window.postMessage; window.postMessage = function(message, targetOrigin) { if (targetOrigin && targetOrigin.includes('youtube.com') && !hasConsent(['C0003'])) { return; } return originalPostMessage.apply(this, arguments); }; const cookiePatterns = { C0003: [ // VWO cookies /_vwo/, // YouTube cookies - more comprehensive patterns /^YSC/, /^VISITOR_INFO/, /^VISITOR_PRIVACY/, /^PREF/, /^GPS/, /^CONSENT/, /_Secure-ROLLOUT/, /^LOGIN_INFO/, /^SIDCC/, /^SSID/, /^APISID/, /^SAPISID/, /^HSID/, /^SID/, /^DEVICE_INFO/, /^CONSISTENCY/, /^use_hitbox/, /^remote_sid/, // Vimeo cookies /^vuid/, /^player/, /^_abexps/, /^_gcl/, /^continuous_play/, /^has_logged_in/, // Calendly cookies (removed GA cookies as they're handled in GTM) //_calendly/, /^calendly/ ], C0004: [ // Existing patterns /gaconnector/, /_biz/, /_vis/, // Marketo/Bizible cookies - more comprehensive (includes _BUID) /_BUID/, /^_BUID$/, /^_biz_uid/, /^_biz_nA/, /^_biz_pendingA/, /^_biz_sid/, /^_biz_flagsA/, /^mkto_/, /^_mkto_trk/, /^_mkt_disp/, /^_mkt_trk/, // HubSpot cookies /__hs/, /hubspot/, /__hst/, /__hsc/, /__hssc/, /__hssrc/, // Bing cookies /_uet/, /MUID/, /_clck/, /_clsk/, // MSN cookies (often shared with Bing) /MSN/ ], C0005: [ // LinkedIn cookies /^li_/, /^lidc/, /^bcookie/, /^bscookie/, /^lang/, /^UserMatchHistory/, /^AnalyticsSyncHistory/ ] }; Object.defineProperty(Document.prototype, 'cookie', { get: function() { return originalCookieDescriptor.get.call(this); }, set: function(value) { const cookieName = value.split('=')[0].trim(); // Allow OneTrust cookies if (cookieName.startsWith('OptAnon')) { return originalCookieDescriptor.set.call(this, value); } // Allow all Cloudflare security cookies regardless of domain if (cookieName === '__cf_bm' || cookieName === '_cf_bm') { return originalCookieDescriptor.set.call(this, value); } // Check against patterns for (const category in cookiePatterns) { if (!hasConsent([category])) { for (const pattern of cookiePatterns[category]) { if (pattern.test(cookieName)) { return; } } } } return originalCookieDescriptor.set.call(this, value); }, configurable: true }); // --- Storylane: notify demos when consent is available --- function notifyStorylaneConsent() { // Using C0003 here – same group as YouTube / Calendly / Vimeo if (!hasConsent(["C0003"])) return; var storylaneDemos = document.querySelectorAll("iframe[name='sl-embed']"); for (var i = 0; i < storylaneDemos.length; i++) { var slDemo = storylaneDemos[i]; try { if (slDemo.contentWindow) { slDemo.contentWindow.postMessage( { message: "storylane-cookie-consent" }, "*" ); } } catch (e) { // swallow – don't break anything if one iframe is grumpy } } } // --- Force refresh after initial Accept All click --- function bindDirectAcceptRefresh() { function attach() { var acceptBtn = document.getElementById("onetrust-accept-btn-handler"); if (!acceptBtn || acceptBtn.getAttribute("data-refresh-bound") === "true") return; acceptBtn.setAttribute("data-refresh-bound", "true"); acceptBtn.addEventListener("click", function() { try { if (sessionStorage.getItem("__ot_accept_refresh_done") === "true") return; } catch (e) {} setTimeout(function() { try { sessionStorage.setItem("__ot_accept_refresh_done", "true"); } catch (e) {} location.reload(); }, 500); }); } // bind now if button already exists attach(); // keep trying briefly in case OneTrust injects banner slightly later var tries = 0; var maxTries = 40; var timer = setInterval(function() { tries++; attach(); if (tries >= maxTries || document.getElementById("onetrust-accept-btn-handler")) { clearInterval(timer); } }, 250); } // --- Consent change: restore anything now allowed --- window.addEventListener("OneTrustGroupsUpdated", function() { restoreAllEligible(); restoreBlockedIframes(); restoreBlockedVideos(); recheckVideoButtons(); notifyStorylaneConsent(); }); // Optional: if your snippet might run after some writes already happened // scan current DOM once: document.querySelectorAll("script[src]").forEach(function (n) { try { handleScript(n); } catch (e) {} }); bindDirectAcceptRefresh(); restoreAllEligible(); notifyStorylaneConsent(); // --- OPTIONAL SAFETY: stub Munchkin to avoid ReferenceError before load --- // This lets inline `Munchkin.init('302-WOS-863')` run without crashing. // The real library will overwrite this when allowed; you can replay if needed. (function () { if (!window.Munchkin) { var MK = function () {}; // placeholder MK.__otStub = true; // mark as our stub MK.__q = []; // queue MK.init = function () { MK.__q.push(["init", Array.prototype.slice.call(arguments)]); }; window.Munchkin = MK; } })(); })(); function OptanonWrapper() { } </script> <!-- OneTrust Cookies Consent Notice end for lightyear.cloud --> AP Automation: How to Get Stakeholder Buy-In
Free trial
AP Automation Benefits

How To Gain Buy-In From Stakeholders For AP Automation

You've done the research, you understand the problem, and you know AP automation is the right move for your business. But knowing the technology is right and getting everyone else on board are two very different things.

In fact, research consistently shows that around 70% of large-scale transformation projects do not succeed (McKinsey & Company), and the most cited reason isn't the technology. It's people. It's change management. It's the gap between a finance leader who can see the value clearly and a boardroom that isn't yet convinced.

Getting stakeholder buy-in is often harder than evaluating the software itself, and it's the step that determines whether a project moves forward or quietly disappears.

This guide covers the questions finance professionals ask most when building internal support for AP automation. Whether you're starting from scratch or trying to revive a stalled project, these answers will help you navigate the people side of the process.

Kasturi Banerjee

by Kasturi Banerjee

Digital Content Writer

Posted 30/04/2026

What is stakeholder buy-in?​

Stakeholder buy-in is the active support and approval from the key decision-makers needed to move a project forward. But it's more than just getting a signature on a budget request. There's a significant difference between a colleague who is passively aware of your AP automation project and one who is actively championing it. With stakeholder buy-in, the goal isn't just to avoid resistance. It's to build a coalition of people who are invested in the outcome. That's what turns a good idea into a delivered project.

Why do you need stakeholder buy-in?

AP automation isn't a decision made by one person. Without stakeholder buy-in, even the best AP automation project will stall, or die quietly before it ever gets off the ground. 78% of projects succeed with engaged stakeholders, but only 40% succeed with low stakeholder engagement. This means resistance from any of the stakeholders involved can be enough to slow momentum, delay sign-off, or terminate the project entirely. Budget approval, resource allocation, and a smooth implementation all require senior-level support.

Perhaps most importantly, without buy-in, even a successful pilot can fail to scale. You might prove the concept works in one part of the business and still find yourself back at square one, making the case all over again to stakeholders who were never fully on board in the first place.

Who should be involved in an AP automation decision from the start?

The honest answer: it depends on the size and structure of your business. In a smaller company, you could be navigating just 1 or 2 people. In a larger one, it could be 5 to 7 distinct stakeholders. 

As a starting point, most AP automation decisions will involve some version of the following:

  1. Finance Director — typically the internal champion. You're the one who understands the problem most clearly, owns the business case, and will be accountable for the outcome. 
  2. CFO or CEO — budget sign-off and strategic alignment. They don't need to understand the details, but they do need to understand why it matters to the business right now. 
  3. IT — system integration, security, and compliance. Bring them in early. IT stakeholders who feel consulted rather than informed are significantly easier to work with.
  4. Operations or procurement — process impact and supplier relationships. These teams live closest to the workflow you're changing. Involving them from the start reduces the risk of resistance.

The teams you involve early become the coalition that carries the project forward. The ones you loop in late become the ones who slow it down.

What do stakeholders actually want to know before approving AP automation?

Before any stakeholder commits their support or their budget, they're working through a set of questions:

  • Is this our problem right now?

Every stakeholder will weigh your proposal against competing proposals for budget and attention.

  • What will it cost, what will it save, and over what timeframe

Stakeholders outside finance will engage with numbers. A clear cost-benefit summary and the ROI will land better with them.

  • How disruptive will this be?

Most stakeholders will be quietly asking how much this affects their team and their existing systems. A phased implementation plan or pilot proposal can significantly reduce perceived risk.

  • Who else has done this, and what happened?

Case studies from businesses of a similar size or sector are often more persuasive than any internal analysis you can produce. 

 

How do you make the business case for AP automation when finance isn't the decision-maker?

The solution isn't to present more financial detail. It's to change the language.

  • Translate finance pain into business language: Manual invoice processing, approval bottlenecks, and reconciliation errors are finance problems. But the business consequences - delayed decisions, cash flow blind spots, audit exposure, and a team spending time on administration instead of analysis are leadership problems. Lead with those. 
  • Frame around outcomes that matter at the top: The outcomes that move senior decision-makers are visibility, control, compliance, and scalability. Can leadership see what's been approved and what's outstanding in real time? Are there controls in place to prevent duplicate payments or fraud? Can your current AP process support the business if it doubles in size? These are the questions your business case should answer.
  • Anchor to a specific trigger: A business case that floats in the abstract is easy to defer. One that connects to something happening in the business right now is much harder to ignore. An upcoming audit, a recent compliance concern, a growth milestone, or a regulatory change on the horizon. Find your trigger and build the case around it. 

How do you calculate the ROI of AP automation to present to senior leadership?

For a starting point, use our free AP automation ROI calculator to input your own numbers and generate a figure specific to your business.

The quickest way to build your ROI case is to start with what you're spending now. Multiply this by your monthly invoice volume. Then annualise it. That’s your baseline. 

Additionally, around 39% of manually processed invoices contain errors, each of which requires time to correct. So, further add duplicate payments, fraud exposure from weak controls, and supplier penalty charges, and the true cost of doing nothing compounds quickly.

From there, the savings are straightforward. Automated AP can reduce invoice processing costs to as low as $3 per invoice. When you convert the staff time saved into salary cost and add the softer gains like a faster month-end close, stronger audit readiness, and improved supplier relationships, the return becomes difficult to argue with.

What is the best stakeholder buy in strategy​?

Begin by mapping each stakeholder by influence and concern — a CFO wants to understand cost and risk, an IT lead wants to know about integration and security, and an Operations Manager wants to know how much disruption to expect. Tailor your message accordingly. 

Then have the informal conversations first, surface objections early, and arrive at the formal pitch with people already aligned rather than discovering resistance at the table. 

Finally, make it easier for them to say yes by proposing a phased rollout or a pilot in one part of the business. Start smaller, prove the value, and let the results do the rest of the convincing.

How to manage a lack of stakeholder buy in?

Before you do anything else, diagnose what you're actually dealing with. Is it low awareness or active resistance, or simple deprioritisation? The response to each is different.

Once you've diagnosed the problem, rebuild with evidence. Showing your stakeholders what the business is losing, or risking by delaying the decision, is often more persuasive than any future projection.

If stakeholders are non-committal, avoid leaving conversations open-ended. Instead, request a defined review window with a specific date to revisit the decision. It creates accountability without pressure. 

Then make the ask smaller. Rather than re-presenting the full business case, offer a reset: a short meeting, a live demonstration, or a focused look at the numbers specific to their part of the business. A low-risk entry point is almost always easier to agree to than starting the whole conversation again from scratch.

How to get AP automation buy-in from difficult stakeholders?

Difficult stakeholders are rarely being difficult for no reason. The most effective approach is to involve them in the problem-definition stage. When a stakeholder has helped identify the problem, they have a stake in the solution. 

Make it concrete by using real examples from your own business: the supplier invoice that went missing and triggered a late-payment penalty, the month-end close that took three days longer than it should have because of missing approvals. Specificity makes the case far more persuasive than any generic statistic. 

Finally, lower the barrier. Offer a demo, a cost comparison, or a contained pilot rather than asking for full commitment upfront. The easier you make it to take the first step, the harder it becomes to keep saying no.

How do you maintain stakeholder interest in AP automation when the project timeline stretches out?

  1. Schedule regular touchpoints: Even short ones work to maintain momentum. A brief monthly update is enough to keep the project on the radar and signal that progress is being made. 
  2. Share incremental proof: Share updated ROI figures, benchmarks from peer businesses, or data on how AP automation adoption is accelerating across your sector. New information gives stakeholders a reason to re-engage rather than simply being reminded that the project still exists. 
  3. Create natural urgency: When external deadlines create natural urgency — a regulatory change on the horizon, an upcoming audit cycle, or a financial year-end — use them. Urgency from outside the business is always more persuasive than that from inside it.

Final Thoughts

Stakeholder buy-in isn't a one-time ask; it's an ongoing process of education, alignment, and trust-building that runs parallel to the entire project. Your job isn't just to understand the value of AP automation; it's to translate that understanding into language that moves the right people to act. The deals that succeed aren't always the ones with the best technology fit. They're the ones where someone inside the business cared enough to champion it at every stage. Be that person.

Ready to take the next step? 

Kasturi Banerjee

By Kasturi Banerjee

Digital Content Writer