<!-- 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 || "").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; } // Function to create placeholder element function createPlaceholder(type) { var placeholder = document.createElement("div"); placeholder.className = "optanon-video-placeholder"; 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>Book a call</p><p>Please accept cookies to book a call.</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 // This catches self-hosted videos that might still drop cookies if (!needsBlocking && video.hasAttribute("data-require-consent")) { needsBlocking = true; rule = { groups: ["C0003"] }; } if (!needsBlocking) return; if (rule && hasConsent(rule.groups)) return; // Store original sources and block the video video.setAttribute("data-consent-required", rule.groups.join(",")); 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 var placeholder = createPlaceholder("video"); // Position parent if needed if (video.parentElement) { if (video.parentElement.style.position !== "absolute" && video.parentElement.style.position !== "relative") { video.parentElement.style.position = "relative"; } video.parentElement.appendChild(placeholder); video.setAttribute("data-placeholder-id", "optanon-video-placeholder"); } } // 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 var placeholder = video.parentElement ? video.parentElement.querySelector(".optanon-video-placeholder") : null; if (placeholder) placeholder.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) { 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); } video.removeAttribute("data-blocked-sources"); } // Restore video attributes video.setAttribute("controls", "true"); video.removeAttribute("data-blocked"); video.removeAttribute("data-consent-required"); video.className = video.className.replace("optanon-blocked-video", "").trim(); video.style.backgroundColor = ""; video.style.minHeight = ""; video.style.minWidth = ""; // Reload video video.load(); } } } // 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;">Cookie 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 }); // --- Consent change: restore anything now allowed --- window.addEventListener("OneTrustGroupsUpdated", function() { restoreAllEligible(); restoreBlockedIframes(); restoreBlockedVideos(); recheckVideoButtons(); }); // 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) {} }); restoreAllEligible(); // --- 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 --> Company Blog | Page 1
Free trial

Top tips on how to streamline processes for your clients or finance teams

Filter By:
Lightyear announces new Advanced Reporting Engine
Feature Release

Lightyear announces new Advanced Reporting Engine

Read article on Lightyear announces new Advanced Reporting Engine
Lightyear announces new advanced Reporting Engine
Feature Release

Lightyear announces new advanced Reporting Engine

Read article on Lightyear announces new advanced Reporting Engine
app check
Feature Release

Reasons & Tips to Select a Business Expenditure App

Read article on Reasons & Tips to Select a Business Expenditure App
Chris Gregg, CEO & Founder of Lightyear
Feature Release

Belfast-Born Fintech Company Expands Customer Offering by Adding Expense Management to its Platform

Read article on Belfast-Born Fintech Company Expands Customer Offering by Adding Expense Management to its Platform
automating lady
Feature Release

Breaking Barriers by Automating Employee Expense Management

Read article on Breaking Barriers by Automating Employee Expense Management
cutting costs
Feature Release

Cut Costs and Errors with AI Data Extraction for Finance Teams

Read article on Cut Costs and Errors with AI Data Extraction for Finance Teams
Yearly Roundup 2023
Feature Release

Yearly Roundup 2023

Read article on Yearly Roundup 2023
August Product Releases 2023
Feature Release

August Product Releases 2023

Read article on August Product Releases 2023
Processing Tab Visual Updates
Feature Release

Processing Tab Visual Updates

Read article on Processing Tab Visual Updates
July 2023 Product Updates
Feature Release

Lightyear Product Updates

Read article on Lightyear Product Updates
Purchase Orders on the Mobile App
Feature Release

April 2023 Product Update

Read article on April 2023 Product Update
January 2023 Product Updates
Feature Release

January 2023 Product Updates

Read article on January 2023 Product Updates
feature-release-november-2022
Feature Release

November 2022 Product Updates

Read article on November 2022 Product Updates
August Product Releases 2023
Feature Release

Advanced Reporting Release

Read article on Advanced Reporting Release
June Product Updates
Feature Release

June Product Updates

Read article on June Product Updates
Feature Release

Product Updates: Q2 2020​

Read article on Product Updates: Q2 2020​
March 2022 Product Updates
Feature Release

March Product Updates

Read article on March Product Updates
December 2021 Product Updates
Feature Release

December Product Updates

Read article on December Product Updates
October 2021 Product Updates
Feature Release

October 2021 Product Updates

Read article on October 2021 Product Updates
August 2021 Product Updates Sorting and Filtering​
Feature Release

August 2021 Product Updates Sorting and Filtering​

Read article on August 2021 Product Updates Sorting and Filtering​
Feature Release

Q2 2021 Product Updates 3 Way matching has arrived

Read article on Q2 2021 Product Updates 3 Way matching has arrived
Feature Release

Product Updates: Q1 2021

Read article on Product Updates: Q1 2021
Feature Release

Introducing Lightyear Purchasing with 3 way matching

Read article on Introducing Lightyear Purchasing with 3 way matching
Product Updates: Q3 2020
Feature Release

Product Updates: Q3 2020

Read article on Product Updates: Q3 2020
Feature Release

Seamlessly Connect Teams & Suppliers With New Collaboration Features

Read article on Seamlessly Connect Teams & Suppliers With New Collaboration Features
August Product Releases 2023
Feature Release

Feature release July 2020

Read article on Feature release July 2020
Feature Release

Product Updates: Instant Messaging and Notifications

Read article on Product Updates: Instant Messaging and Notifications
Feature Release February 2020
Feature Release

Feature Release February 2020

Read article on Feature Release February 2020
Feature Release

Product Updates: October 2019

Read article on Product Updates: October 2019
Product Updates: Q4 2019 Roundup
Feature Release

Product Updates: Q4 2019 Roundup

Read article on Product Updates: Q4 2019 Roundup