1(function () { 2 'use strict'; 3 4 var DEBUG = !!(window.guideTrackingConfig && window.guideTrackingConfig.debug); 5 var TAG = '[GuideTracking]'; 6 7 function log() { 8 if (!DEBUG) return; 9 var args = Array.prototype.slice.call(arguments); 10 args.unshift(TAG); 11 console.log.apply(console, args); 12 } 13 14 function warn() { 15 if (!DEBUG) return; 16 var args = Array.prototype.slice.call(arguments); 17 args.unshift(TAG); 18 console.warn.apply(console, args); 19 } 20 21 // One entry per detected guide: { id, name, pdf, signupBlock, thanksBlock, signupFired } 22 var guides = []; 23 24 function slugify(str) { 25 return (str || '') 26 .toLowerCase() 27 .normalize('NFKD').replace(/[\u0300-\u036f]/g, '') // strip accents 28 .replace(/[^a-z0-9]+/g, '_') 29 .replace(/^_+|_+$/g, ''); 30 } 31 32 function pdfFallbackId(href) { 33 var file = (href || '').split('/').pop() || ''; 34 return slugify(file.replace(/\.[a-z0-9]+$/i, '')); 35 } 36 37 function isVisible(el) { 38 return !!(el && (el.offsetWidth || el.offsetHeight || el.getClientRects().length)); 39 } 40 41 function push(eventName, guide) { 42 window.dataLayer = window.dataLayer || []; 43 window.dataLayer.push({ event: eventName, guide_id: guide.id, guide_name: guide.name }); 44 } 45 46 // Build the guide registry from every signup block on the page. 47 function discoverGuides() { 48 guides = []; 49 var signupBlocks = document.querySelectorAll('.newsletter-form-holder'); 50 51 var seenIds = {}; 52 53 signupBlocks.forEach(function (signupBlock, index) { 54 // The thanks block normally lives inside the signup holder (next to 55 // .form-content); fall back to a following sibling for other layouts. 56 var thanksBlock = signupBlock.querySelector('.thanks'); 57 if (!thanksBlock) { 58 thanksBlock = signupBlock.nextElementSibling; 59 while (thanksBlock && !thanksBlock.classList.contains('thanks')) { 60 thanksBlock = thanksBlock.nextElementSibling; 61 } 62 } 63 if (!thanksBlock) { 64 warn('signup block #' + index + ': no matching .thanks block found (inside or as sibling), skipping', signupBlock); 65 return; 66 } 67 68 var link = thanksBlock.querySelector('a.wp-block-button__link[href]'); 69 if (!link) { 70 warn('signup block #' + index + ': .thanks block has no download link, skipping', thanksBlock); 71 return; 72 } 73 74 var pdf = link.getAttribute('href'); 75 var heading = signupBlock.querySelector('h3'); 76 var name = heading ? heading.textContent.trim() : pdf; 77 var id = heading ? slugify(name) : pdfFallbackId(pdf); 78 if (!id) id = pdfFallbackId(pdf); 79 80 if (seenIds[id]) { 81 warn('duplicate guide_id "' + id + '" detected (guide: "' + name + '") â events may merge with an earlier guide. Consider a more distinct heading.'); 82 } 83 seenIds[id] = true; 84 85 guides.push({ 86 id: id, 87 name: name, 88 pdf: pdf, 89 signupBlock: signupBlock,
90 thanksBlock: thanksBlock, 91 signupFired: false 92 }); 93 94 log('form detected â guide_id:', id, '| guide_name:', name, '| guide_pdf:', pdf); 95 }); 96 } 97 98 // Re-resolve each guide's thanks block by its stable PDF href, in case 99 // inline scripts / blocks get relocated at runtime by the site's JS 100 // optimization layer. 101 function findThanksBlockByPdf(pdf) { 102 var link = document.querySelector('.thanks a.wp-block-button__link[href="' + pdf + '"]'); 103 return link ? link.closest('.thanks') : null; 104 } 105 106 function checkSignups() { 107 guides.forEach(function (guide) { 108 if (guide.signupFired) return; 109 var thanksBlock = findThanksBlockByPdf(guide.pdf) || guide.thanksBlock; 110 if (isVisible(thanksBlock)) { 111 guide.signupFired = true; 112 push('guide_signup', guide); 113 } 114 }); 115 } 116 117 function init() { 118 discoverGuides(); 119 120 if (!guides.length) { 121 warn('no guides detected on this page â tracking inactive'); 122 return; 123 } 124 125 checkSignups(); 126 127 new MutationObserver(checkSignups).observe(document.body, { 128 childList: true, 129 subtree: true, 130 attributes: true, 131 attributeFilter: ['style', 'class'] 132 }); 133 134 document.addEventListener('click', function (e) { 135 var link = e.target.closest('.thanks a.wp-block-button__link[href]'); 136 if (!link) return; 137 var pdf = link.getAttribute('href'); 138 var guide = guides.filter(function (g) { return g.pdf === pdf; })[0]; 139 if (!guide) { 140 warn('download click on unrecognized link, no matching guide:', pdf); 141 return; 142 } 143 log('download click detected for guide:', guide.id); 144 push('guide_download', guide); 145 }); 146 } 147 148 if (document.readyState === 'loading') { 149 document.addEventListener('DOMContentLoaded', init); 150 } else { 151 init(); 152 } 153})();
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.