<!-- 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 --> How AP Automation Helps AU Hospitality Businesses Control Spend
Free trial
AP Automation Benefits

How AP Automation Helps AU Hospitality Businesses Control Spend

Cost pressures across Australia continue to rise. CPI has increased 3.4% in the 12 months to November 2025, where food inflation: 3.3% annually (up from 3.2% in October), meals out and takeaway: 3.6% annually (driven by labour and ingredient costs), and meat and seafood: 3.8% (beef and lamb up more than 10% due to strong export demand). This is making hospitality businesses face higher costs across food, utilities and essential services. When margins are already tight, there’s little room to absorb unnecessary spending or payment errors. 

In this environment, every dollar counts. Your team need tools that let them keep a close eye on spending, prevent errors before they happen, and maintain smooth day-to-day operations without slowing anyone down. Staying on top of costs isn’t just about reacting, it’s about being proactive, spotting issues early, and making informed decisions that protect margins and help your business thrive.

Here are 3 major ways Lightyear helps control spend and protect margins. 

Hospitality
Kasturi Banerjee

by Kasturi Banerjee

Digital Content Writer

Posted 21/10/2025

How Lightyear Helps Control Spend

Keeping costs under control can feel like a constant battle. 

1. Structured approval workflows 

In hospitality, invoices come in fast and often. When every invoice needs the same level of approval, teams get stuck chasing sign-offs. When approvals are too loose or unauthorised, it costs time, money, and confidence.

Structured approval workflows give you confidence that every invoice is checked before money leaves the business. Lightyear makes this easy by letting you build approval workflows that reflect how your business really operates. You can set value-based approval thresholds: invoices under $500 go to the department head, and those over $500 go to the CFO. This is especially important in hospitality. It prevents small, recurring purchases from slowing down operations while ensuring that large supplier payments, contract changes, or unexpected costs receive the right level of financial oversight. You can set approvers by cost centre, department or supplier details. 

When an invoice comes in, it automatically routes to the right person. Approvals happen in one place, with full visibility over what’s approved, what’s pending and what’s overdue. Every activity is logged automatically, leaving a clear audit trail. That means less chasing, fewer errors, and complete confidence that spend is controlled before payment is released.

2. Price Increase Detection

In hospitality, supplier prices change often, and not always with notice. A small increase in high-frequency items like food, beverages, or cleaning supplies can quietly add up across venues and weeks. Without line-by-line checks, these increases usually go unnoticed until your margins are already impacted.

Lightyear’s automatic price checker scans your invoices, price-checks each line item against your agreed supplier pricing, and instantly alerts you to any inconsistencies. This gives you early visibility of unexpected increases so you can stay on budget. With full historical pricing data at your fingertips, you can renegotiate with confidence and make sure you’re never overpaying for recurring goods or services without management knowing. You also get a clear view of spending patterns across suppliers and locations, helping you plan and stay on top of inflationary or seasonal cost pressures, rather than reacting after the fact. This means less time chasing mistakes, fewer surprises, and total confidence that every dollar leaving the business is the right one.

3. Fraud Prevention

A large number of invoices from the same suppliers, especially for perishable goods like food and beverages, means it’s easier for fraudulent invoices or payment diversion to take place unnoticed, particularly when bank details change, or invoices arrive from unfamiliar email addresses.

Lightyear helps protect your business by putting practical controls around how invoices are processed. It flags supplier bank detail changes, helping you prevent misdirected payments. Lightyear also highlights invoices coming from email addresses outside your approved supplier list, so you’re alerted to potentially fraudulent submissions. It also adds an extra layer of login security, ensuring that only authorised users can access the system and approvals remain protected. You stay in control of who can see, approve and pay invoices through clearly defined user roles and permissions, so not everyone has the same level of access. Lightyear also detects potential duplicate invoices before payment is made, helping you avoid costly errors. The result is reduced exposure to internal and external risk and stronger protection of your margins.

Final Thoughts

Rising costs mean you can’t afford reactive spend control. An AP automation system like Lightyear provides your team with real-time visibility into where money is being spent. It provides structured approvals, price increase detection, and built-in fraud controls. These work together to protect already-tight margins. The result? Stronger cost control, fewer surprises, and more confidence in every payment, even in inflationary conditions.

Explore how Lightyear AP automation can help your hospitality business.

Kasturi Banerjee

By Kasturi Banerjee

Digital Content Writer