1/** 2 * Efficiently watches for elements and triggers ad displays using Intersection Observer 3 */ 4(function() { 5 // Early exit if no relevant page type 6 const isProductLandingPage = document.querySelector('.page-node-type-cbis-product-landing-page') !== null; 7 const isProductListPage = document.querySelector('.node--type-cbis-product-list.display-with-ads') !== null; 8 9 if (!isProductLandingPage && !isProductListPage) { 10 console.log('No relevant ad containers on this page, exiting ad watcher'); 11 return; 12 } 13 14 console.log(`Ads watcher initialized for ${isProductLandingPage ? 'product landing page' : 'product list'}`); 15 16 // Configuration mapping selectors to watch for - only include relevant ones 17 const adSelectors = isProductLandingPage ? [ 18 '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-1', 19 '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-2', 20 '.page-node-type-cbis-product-landing-page .ads-wrapper-plp-3' 21 ] : [ 22 '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe1', 23 '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe2', 24 '.node--type-cbis-product-list.display-with-ads .ads-wrapper-list-swipe3' 25 ]; 26 27 // Set timeout based on page type 28 const timeoutDuration = isProductLandingPage ? 90000 : 40000; 29 30 // Helper function to display the ad 31 function displayAdForElement(element) { 32 const id = element.firstElementChild?.id; 33 if (id && typeof googletag !== 'undefined') { 34 googletag.cmd.push(function() { 35 googletag.display(id); 36 }); 37 } 38 } 39 40 // Create a single DOM mutation observer to look for ad containers 41 const mutationObserver = new MutationObserver((mutations) => { 42 checkForAdContainers(); 43 }); 44 45 // Start the mutation observer 46 mutationObserver.observe(document.body, { 47 childList: true, 48 subtree: true 49 }); 50 51 // Set timeout for observers 52 setTimeout(() => { 53 if (mutationObserver) { 54 mutationObserver.disconnect(); 55 console.log(`Ads watcher timed out after ${timeoutDuration/1000} seconds, disconnecting observer.`); 56 57 // Force check one last time when timing out to catch any missed ads 58 checkForAdContainers(true); 59 } 60 }, timeoutDuration); 61 62 // Function to check for ad containers and set up Intersection Observers 63 function checkForAdContainers(isFinalCheck = false) { 64 adSelectors.forEach(selector => { 65 const containers = document.querySelectorAll(selector); 66 67 containers.forEach(container => { 68 // Skip if this container already has an observer 69 if (container.dataset.adObserved) { 70 return; 71 } 72 73 // Mark as observed 74 container.dataset.adObserved = 'true'; 75 76 // On final check, display ads regardless of visibility 77 if (isFinalCheck) { 78 displayAdForElement(container); 79 return; 80 } 81 82 // Create an Intersection Observer for this container 83 const intersectionObserver = new IntersectionObserver((entries) => { 84 entries.forEach(entry => { 85 if (entry.isIntersecting) { 86 displayAdForElement(entry.target); 87 intersectionObserver.unobserve(entry.target); 88 } 89 }); 90 }, { 91 rootMargin: '200px', // Load ads when they're within 200px of viewport 92 threshold: 0.01 93 }); 94 95 // Start observing this container 96 intersectionObserver.observe(container); 97 }); 98 }); 99 } 100
101 // Check for containers immediately 102 checkForAdContainers(); 103 104 // Setup scroll and resize handlers 105 let scrollTimeout; 106 window.addEventListener('scroll', () => { 107 clearTimeout(scrollTimeout); 108 scrollTimeout = setTimeout(() => { 109 checkForAdContainers(); 110 }, 100); // Debounce scroll events 111 }); 112 113 // Also check on window resize 114 let resizeTimeout; 115 window.addEventListener('resize', () => { 116 clearTimeout(resizeTimeout); 117 resizeTimeout = setTimeout(() => { 118 checkForAdContainers(); 119 }, 200); // Debounce resize events 120 }); 121 122 // Additional checks at specific intervals to catch lazy-loaded content 123 setTimeout(checkForAdContainers, 2500); // Quick initial check 124 setTimeout(checkForAdContainers, 10000); // Check after 10 seconds 125 126 // For product landing pages, do even more delayed checks 127 if (isProductLandingPage) { 128 setTimeout(checkForAdContainers, 30000); // Check after 30 seconds 129 setTimeout(checkForAdContainers, 60000); // Check after 60 seconds 130 } 131})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.