1/* WordPress Cookie One Plugin JavaScript */ 2(function() { 3 'use strict'; 4 5 // Wait for jQuery to be available 6 function waitForjQuery(callback) { 7 if (typeof jQuery !== 'undefined') { 8 callback(jQuery); 9 } else { 10 setTimeout(function() { 11 waitForjQuery(callback); 12 }, 50); 13 } 14 } 15 16 waitForjQuery(function($) { 17 // Get settings from WordPress localized script 18 const settings = window.cookieOneSettings || {}; 19 20 /* ---------- CONFIG ---------- */ 21 const CONSENT_NAME = 'wp_cr_consent_v1'; 22 const CONSENT_EXPIRES_DAYS = parseInt(settings.cookieExpiry) || 365; 23 24 /* Default consent structure */ 25 const defaultConsent = { 26 essential: true, 27 functional: false, 28 analytics: false, 29 targeting: false, 30 timestamp: new Date().toISOString() 31 }; 32 33 /* ---------- STORAGE HELPERS ---------- */ 34 function setCookie(name, value, days) { 35 const expires = new Date(Date.now() + days*24*60*60*1000).toUTCString(); 36 document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; SameSite=Lax`; 37 } 38 39 function getCookie(name) { 40 const cookies = document.cookie.split('; ').reduce((acc, pair) => { 41 const [k, ...v] = pair.split('='); 42 acc[k] = decodeURIComponent(v.join('=')); 43 return acc; 44 }, {}); 45 return cookies[name] || null; 46 } 47 48 function saveConsent(consentObj){ 49 try { 50 const payload = JSON.stringify(consentObj); 51 setCookie(CONSENT_NAME, payload, CONSENT_EXPIRES_DAYS); 52 localStorage.setItem(CONSENT_NAME, payload); 53 54 // Trigger WordPress action 55 $(document).trigger('cookieOneChanged', [consentObj]); 56 } catch(e) { 57 console.warn('Unable to persist consent:', e); 58 } 59 } 60 61 function loadConsent(){ 62 try { 63 const c = getCookie(CONSENT_NAME) || localStorage.getItem(CONSENT_NAME); 64 if(!c) return null; 65 return JSON.parse(c); 66 } catch(e) { 67 console.warn('Unable to read consent:', e); 68 return null; 69 } 70 } 71 72 function clearConsent(){ 73 document.cookie = CONSENT_NAME + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 74 localStorage.removeItem(CONSENT_NAME); 75 $(document).trigger('cookieOneCleared'); 76 } 77 78 /* ---------- UI ELEMENTS ---------- */ 79 let banner, acceptAllBtn, rejectAllBtn, customizeBtn, backdrop, modal, modalSaveBtn, modalRejectBtn, modalCloseBtn, toggles; 80 81 function initElements() { 82 banner = document.getElementById('cookieBanner'); 83 acceptAllBtn = document.getElementById('acceptAllBtn'); 84 rejectAllBtn = document.getElementById('rejectAllBtn'); 85 customizeBtn = document.getElementById('customizeBtn'); 86 backdrop = document.getElementById('cookieModalBackdrop'); 87 modal = document.getElementById('cookieModal'); 88 modalSaveBtn = document.getElementById('modalSaveBtn'); 89 modalRejectBtn = document.getElementById('modalRejectBtn'); 90 modalCloseBtn = document.getElementById('modalCloseBtn'); 91 toggles = Array.from(document.querySelectorAll('.consent-toggle')); 92 } 93 94 /* Apply dynamic styles from WordPress settings */ 95 function applyDynamicStyles() { 96 if (settings.primaryColor) { 97 // Set both variables to ensure compatibility 98 document.documentElement.style.setProperty('--cowp-primary-color', settings.primaryColor); 99 document.documentElement.style.setProperty('--cowp-accent', settings.primaryColor); 100 101 // Convert hex to RGB for use in rgba() 102 const hex = settings.primaryColor.replace('#', ''); 103 const r = parseInt(hex.substr(0, 2), 16); 104 const g = parseInt(hex.substr(2, 2), 16); 105 const b = parseInt(hex.substr(4, 2), 16); 106 document.documentElement.style.setProperty('--cowp-accent-rgb', `${r}, ${g}, ${b}`); 107 108 // Also apply the color directly to banner for immediate effect 109 if (banner) { 110 banner.style.setProperty('--cowp-accent', settings.primaryColor); 111 } 112 } 113 114 if (settings.bannerPosition && banner) { 115 banner.classList.add('position-' + settings.bannerPosition); 116 } 117 } 118
119 /* Update banner text from WordPress settings */ 120 function updateBannerText() { 121 if (settings.bannerTitle && document.getElementById('cookieTitle')) { 122 document.getElementById('cookieTitle').textContent = settings.bannerTitle; 123 } 124 if (settings.bannerText && document.getElementById('cookieDesc')) { 125 document.getElementById('cookieDesc').innerHTML = settings.bannerText; 126 } 127 if (settings.acceptAllText && acceptAllBtn) { 128 acceptAllBtn.textContent = settings.acceptAllText; 129 } 130 if (settings.rejectAllText && rejectAllBtn) { 131 rejectAllBtn.textContent = settings.rejectAllText; 132 } 133 if (settings.customizeText && customizeBtn) { 134 customizeBtn.textContent = settings.customizeText; 135 } 136 } 137 138 /* Toggle visual handling */ 139 function setToggleVisual(toggle, checked){ 140 const label = toggle.closest('label.switch'); 141 if(checked) label.classList.add('on'); else label.classList.remove('on'); 142 toggle.checked = !!checked; 143 label.setAttribute('aria-pressed', checked ? 'true' : 'false'); 144 } 145 146 /* Focus trap for modal */ 147 let lastFocusedBeforeModal = null; 148 function openModal(){ 149 lastFocusedBeforeModal = document.activeElement; 150 backdrop.classList.add('show'); 151 backdrop.setAttribute('aria-hidden', 'false'); 152 banner.setAttribute('aria-hidden', 'true'); 153 154 // Set toggles based on loaded consent 155 const current = loadConsent() || defaultConsent; 156 toggles.forEach(t=>{ 157 const key = t.dataset.consentKey; 158 if (key === 'essential') { 159 setToggleVisual(t, true); 160 t.closest('label.switch').classList.add('on'); 161 } else { 162 setToggleVisual(t, !!current[key]); 163 } 164 }); 165 166 modal.focus(); 167 document.addEventListener('keydown', handleModalKeydown); 168 trapFocus(modal); 169 170 // WordPress action 171 $(document).trigger('cookieModalOpened'); 172 } 173 174 function closeModal(){ 175 backdrop.classList.remove('show'); 176 backdrop.setAttribute('aria-hidden', 'true'); 177 banner.setAttribute('aria-hidden', 'false'); 178 document.removeEventListener('keydown', handleModalKeydown); 179 releaseTrap(); 180 try { lastFocusedBeforeModal && lastFocusedBeforeModal.focus(); } catch(e){} 181 182 $(document).trigger('cookieModalClosed'); 183 } 184 185 function handleModalKeydown(e){ 186 if(e.key === 'Escape') closeModal(); 187 } 188 189 /* Simple focus trap implementation */ 190 let focusableElements = []; 191 let firstFocusable = null, lastFocusable = null; 192 193 function trapFocus(container){ 194 focusableElements = Array.from(container.querySelectorAll('a[href], button:not([disabled]), textarea, input:not([disabled]), select, [tabindex]:not([tabindex="-1"])')); 195 196 if(focusableElements.length){ 197 firstFocusable = focusableElements[0]; 198 lastFocusable = focusableElements[focusableElements.length -1]; 199 firstFocusable.focus(); 200 container.addEventListener('keydown', handleTrapKey); 201 } 202 } 203 204 function handleTrapKey(e){ 205 if(e.key !== 'Tab') return; 206 if(e.shiftKey && document.activeElement === firstFocusable){ 207 e.preventDefault(); 208 lastFocusable.focus(); 209 } else if(!e.shiftKey && document.activeElement === lastFocusable){ 210 e.preventDefault(); 211 firstFocusable.focus(); 212 } 213 } 214 215 function releaseTrap(){ 216 modal.removeEventListener('keydown', handleTrapKey); 217 } 218 219 /* ---------- CONSENT ACTIONS ---------- */ 220 function applyConsent(consent) { 221 consent.timestamp = new Date().toISOString(); 222 saveConsent(consent); 223 hideBanner(); 224 225 // Execute side-effects based on enabled features 226 if (settings.enableAnalytics === '1' && consent.analytics) { 227 enableAnalytics(); 228 } else { 229 disableAnalytics(); 230 } 231 232 if (settings.enableTargeting === '1' && consent.targeting) { 233 enableTargeting(); 234 } else { 235 disableTargeting(); 236 } 237 238 document.documentElement.setAttribute('data-consent', JSON.stringify(consent)); 239 240 // WordPress action 241 $(document).trigger('cookieOneApplied', [consent]); 242 } 243 244 function acceptAll() { 245 const consent = Object.assign({}, defaultConsent, { 246 essential: true, 247 functional: true, 248 analytics: settings.enableAnalytics === '1', 249 targeting: settings.enableTargeting === '1' 250 }); 251 applyConsent(consent); 252 } 253 254 function rejectAll() { 255 const consent = Object.assign({}, defaultConsent, { 256 essential: true, // Always keep essential 257 functional: false,
258 analytics: false, 259 targeting: false 260 }); 261 applyConsent(consent); 262 } 263 264 /* ---------- BANNER LOGIC ---------- */ 265 function showBanner() { 266 if (banner) { 267 banner.classList.add('show'); 268 banner.setAttribute('aria-hidden', 'false'); 269 270 // Force apply colors after banner is shown 271 applyDynamicStyles(); 272 273 $(document).trigger('cookieBannerShown'); 274 } 275 } 276 277 function hideBanner(){ 278 if (banner) { 279 banner.classList.remove('show'); 280 banner.setAttribute('aria-hidden', 'true'); 281 $(document).trigger('cookieBannerHidden'); 282 } 283 } 284 285 function initConsentOnLoad(){ 286 window.__cr_consent_analytics = false; 287 window.__cr_consent_targeting = false; 288 289 const saved = loadConsent(); 290 if(saved){ 291 applyConsent(saved); 292 } else { 293 disableAnalytics(); 294 disableTargeting(); 295 showBanner(); 296 } 297 } 298 299 /* ---------- Enhanced Cookie Management ---------- */ 300 const ANALYTICS_COOKIES = [ 301 '_ga', '_gid', '_gat', '_gtag_', '_gcl_', '_utm_', '__utma', '__utmb', 302 '__utmc', '__utmz', '__utmt', '_dc_gtm_', '_gac_', '_gat_gtag_UA_', 303 '_ga_', 'AMP_TOKEN', '__utmv', '__utmx', '__utmxx' 304 ]; 305 306 const MARKETING_COOKIES = [ 307 '_fbp', '_fbc', 'fr', '_gcl_au', '_gcl_aw', '_gcl_dc', '_gcl_gb', 308 '_gcl_gf', '_gcl_ha', 'IDE', 'test_cookie', 'DSID', 'NID', 309 '__Secure-3PAPISID', '__Secure-3PSID', '__Secure-3PSIDCC', 310 '_pinterest_sess', '_pinterest_ct_ua', '_pin_unauth', 'pd', 311 'personalization_id', 'guest_id', 'ct0', '_twitter_sess' 312 ]; 313 314 function blockCookiesByPattern(patterns) { 315 patterns.forEach(pattern => { 316 // Remove existing cookies matching pattern 317 const cookies = document.cookie.split(';'); 318 cookies.forEach(cookie => { 319 const name = cookie.split('=')[0].trim(); 320 if (name.includes(pattern) || name.startsWith(pattern)) { 321 deleteCookie(name); 322 } 323 }); 324 }); 325 } 326 327 function deleteCookie(name, domain = null) { 328 const domains = domain ? [domain] : ['', window.location.hostname, '.' + window.location.hostname]; 329 const paths = ['/', '']; 330 331 domains.forEach(d => { 332 paths.forEach(p => { 333 document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${p}; domain=${d}`; 334 }); 335 }); 336 } 337 338 function preventCookieStorage() { 339 // Override document.cookie setter to block unwanted cookies 340 const originalCookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie'); 341 if (originalCookieDescriptor) { 342 Object.defineProperty(document, 'cookie', { 343 get: originalCookieDescriptor.get, 344 set: function(value) { 345 const cookieName = value.split('=')[0].trim(); 346 const consent = loadConsent(); 347 348 // Allow essential cookies always 349 const isEssential = !ANALYTICS_COOKIES.some(pattern => cookieName.includes(pattern)) && 350 !MARKETING_COOKIES.some(pattern => cookieName.includes(pattern)); 351 352 if (isEssential) { 353 originalCookieDescriptor.set.call(this, value); 354 return; 355 } 356 357 // Check consent for analytics cookies 358 if (ANALYTICS_COOKIES.some(pattern => cookieName.includes(pattern))) { 359 if (consent && consent.analytics) { 360 originalCookieDescriptor.set.call(this, value); 361 } else { 362 console.log('Blocked analytics cookie:', cookieName); 363 } 364 return; 365 } 366 367 // Check consent for marketing cookies 368 if (MARKETING_COOKIES.some(pattern => cookieName.includes(pattern))) { 369 if (consent && consent.targeting) { 370 originalCookieDescriptor.set.call(this, value); 371 } else { 372 console.log('Blocked marketing cookie:', cookieName); 373 } 374 return; 375 } 376 377 // Default: allow the cookie 378 originalCookieDescriptor.set.call(this, value); 379 }, 380 configurable: true 381 }); 382 } 383 } 384 385 /* ---------- Analytics control ---------- */ 386 function enableAnalytics(){ 387 // Update Google Consent Mode first 388 if(window.gtag) { 389 try { 390 window.gtag('consent', 'update', {
391 'analytics_storage': 'granted' 392 }); 393 } catch(e){} 394 } 395 396 const scripts = Array.from(document.querySelectorAll('script[type="text/plain"][data-consent="analytics"]')); 397 scripts.forEach(s=>{ 398 if (!s.dataset.loaded) { 399 const real = document.createElement('script'); 400 if (s.src) real.src = s.src; 401 if (s.dataset.async !== undefined) real.async = true; 402 if (s.textContent && s.textContent.trim()) real.textContent = s.textContent; 403 s.parentNode.insertBefore(real, s); 404 s.dataset.loaded = '1'; 405 } 406 }); 407 408 const inline = document.querySelectorAll('script[type="text/plain"][data-consent="analytics-init"]'); 409 inline.forEach(s=>{ 410 if (!s.dataset.loaded) { 411 try { 412 const script = document.createElement('script'); 413 script.textContent = s.textContent; 414 document.head.appendChild(script); 415 s.dataset.loaded = '1'; 416 } catch(e){ 417 console.error('Error enabling analytics init', e); 418 } 419 } 420 }); 421 422 window.__cr_consent_analytics = true; 423 $(document).trigger('analyticsEnabled'); 424 } 425 426 function disableAnalytics(){ 427 window.__cr_consent_analytics = false; 428 429 // Update Google Analytics consent 430 if(window.gtag) { 431 try { 432 window.gtag('consent', 'update', { 433 'analytics_storage': 'denied' 434 }); 435 } catch(e){} 436 } 437 438 // Comprehensively remove all analytics cookies 439 blockCookiesByPattern(ANALYTICS_COOKIES); 440 441 // Also remove any Google Analytics cookies by exact pattern matching 442 const cookies = document.cookie.split(';'); 443 cookies.forEach(cookie => { 444 const name = cookie.split('=')[0].trim(); 445 if (name.match(/^_ga/) || name.match(/^_gid/) || name.match(/^_gat/) || name.match(/^__utm/)) { 446 deleteCookie(name); 447 } 448 }); 449 450 $(document).trigger('analyticsDisabled'); 451 } 452 453 /* ---------- Marketing/Targeting control ---------- */ 454 function enableTargeting(){ 455 // Update Google Consent Mode first 456 if(window.gtag) { 457 try { 458 window.gtag('consent', 'update', { 459 'ad_storage': 'granted', 460 'ad_user_data': 'granted', 461 'ad_personalization': 'granted' 462 }); 463 } catch(e){} 464 } 465 466 // Grant Facebook Pixel consent 467 if(window.fbq) { 468 try { 469 window.fbq('consent', 'grant'); 470 } catch(e){} 471 } 472 473 const scripts = Array.from(document.querySelectorAll('script[type="text/plain"][data-consent="targeting"]')); 474 scripts.forEach(s=>{ 475 if (!s.dataset.loaded) { 476 const real = document.createElement('script'); 477 if (s.src) real.src = s.src; 478 if (s.dataset.async !== undefined) real.async = true; 479 if (s.textContent && s.textContent.trim()) real.textContent = s.textContent; 480 s.parentNode.insertBefore(real, s); 481 s.dataset.loaded = '1'; 482 } 483 }); 484 485 const inline = document.querySelectorAll('script[type="text/plain"][data-consent="targeting-init"]'); 486 inline.forEach(s=>{ 487 if (!s.dataset.loaded) { 488 try { 489 const script = document.createElement('script'); 490 script.textContent = s.textContent; 491 document.head.appendChild(script); 492 s.dataset.loaded = '1'; 493 } catch(e){ 494 console.error('Error enabling targeting init', e); 495 } 496 } 497 }); 498 499 window.__cr_consent_targeting = true; 500 $(document).trigger('targetingEnabled'); 501 } 502 503 function disableTargeting(){ 504 window.__cr_consent_targeting = false;
505 506 // Comprehensively remove all marketing/targeting cookies 507 blockCookiesByPattern(MARKETING_COOKIES); 508 509 // Remove Facebook tracking cookies specifically 510 const fbCookies = document.cookie.split(';'); 511 fbCookies.forEach(cookie => { 512 const name = cookie.split('=')[0].trim(); 513 if (name.match(/^_fb/) || name.match(/^fr$/) || name.includes('facebook')) { 514 deleteCookie(name); 515 } 516 }); 517 518 // Revoke Facebook Pixel consent 519 if(window.fbq) { 520 try { 521 window.fbq('consent', 'revoke'); 522 } catch(e){} 523 } 524 525 // Update Google Ads consent 526 if(window.gtag) { 527 try { 528 window.gtag('consent', 'update', { 529 'ad_storage': 'denied', 530 'ad_user_data': 'denied', 531 'ad_personalization': 'denied' 532 }); 533 } catch(e){} 534 } 535 536 $(document).trigger('targetingDisabled'); 537 } 538 539 /* ---------- UI WIRING ---------- */ 540 function wireUpEvents() { 541 if (acceptAllBtn) { 542 acceptAllBtn.addEventListener('click', () => { acceptAll(); }); 543 } 544 545 if (rejectAllBtn) { 546 rejectAllBtn.addEventListener('click', () => { rejectAll(); }); 547 } 548 549 if (customizeBtn) { 550 customizeBtn.addEventListener('click', () => { openModal(); }); 551 } 552 553 if (modalSaveBtn) { 554 modalSaveBtn.addEventListener('click', () => { 555 const consent = Object.assign({}, defaultConsent); 556 toggles.forEach(t => { 557 const key = t.dataset.consentKey; 558 if (key === 'essential') { 559 consent[key] = true; // Always true for essential 560 } else { 561 consent[key] = !!t.checked; 562 } 563 }); 564 applyConsent(consent); 565 closeModal(); 566 }); 567 } 568 569 if (modalRejectBtn) { 570 modalRejectBtn.addEventListener('click', () => { 571 rejectAll(); 572 closeModal(); 573 }); 574 } 575 576 if (modalCloseBtn) { 577 modalCloseBtn.addEventListener('click', () => { 578 closeModal(); 579 }); 580 } 581 582 // Toggle handling 583 document.querySelectorAll('label.switch').forEach(lbl=>{ 584 if (lbl.classList.contains('disabled')) return; 585 586 lbl.addEventListener('click', (e)=>{ 587 const input = lbl.querySelector('input[type="checkbox"]'); 588 const key = input.dataset.consentKey; 589 590 if (key === 'essential') return; // Essential cookies cannot be toggled 591 592 const newVal = !input.checked; 593 setToggleVisual(input, newVal); 594 }); 595 596 lbl.addEventListener('keydown', (e)=>{ 597 if(e.key === 'Enter' || e.key === ' '){ 598 e.preventDefault(); 599 lbl.click(); 600 } 601 }); 602 }); 603 604 // Init toggle visuals 605 toggles.forEach(t => { 606 if (t.dataset.consentKey !== 'essential') { 607 setToggleVisual(t, false); 608 } 609 }); 610 } 611 612 /* ---------- Public API ---------- */ 613 window.CrConsent = { 614 getConsent: function(){ return loadConsent() || defaultConsent; }, 615 hasConsentFor: function(category){ 616 const c = this.getConsent(); 617 return !!(c && c[category]); 618 }, 619 revokeConsent: function(){ clearConsent(); showBanner(); }, 620 setConsent: function(obj){ 621 const c = Object.assign({}, defaultConsent, obj); 622 applyConsent(c); 623 }, 624 showBanner: showBanner, 625 hideBanner: hideBanner, 626 openModal: openModal, 627 closeModal: closeModal 628 }; 629 630 /* ---------- Global consent checkers ---------- */ 631 window.__cr_consent_analytics = false;
632 window.__cr_consent_targeting = false; 633 634 window.hasAnalyticsConsent = function() { 635 const consent = loadConsent(); 636 return consent && consent.analytics === true; 637 }; 638 639 window.hasTargetingConsent = function() { 640 const consent = loadConsent(); 641 return consent && consent.targeting === true; 642 }; 643 644 /* ---------- Initialization ---------- */ 645 $(document).ready(function(){ 646 // Initialize cookie prevention first 647 preventCookieStorage(); 648 649 initElements(); 650 applyDynamicStyles(); 651 updateBannerText(); 652 wireUpEvents(); 653 initConsentOnLoad(); 654 655 // Start continuous cookie monitoring 656 startCookieMonitoring(); 657 }); 658 659 /* ---------- Immediate Cookie Cleanup (runs before DOM ready) ---------- */ 660 // Run immediate cleanup for existing cookies without consent 661 (function immediateCleanup() { 662 const consent = loadConsent(); 663 664 // If no consent exists, block all tracking cookies immediately 665 if (!consent) { 666 // Define inline blocking patterns for immediate use 667 const analyticsPatterns = ['_ga', '_gid', '_gat', '__utm', '_gcl_']; 668 const marketingPatterns = ['_fbp', '_fbc', 'IDE', 'test_cookie']; 669 670 [...analyticsPatterns, ...marketingPatterns].forEach(pattern => { 671 const cookies = document.cookie.split(';'); 672 cookies.forEach(cookie => { 673 const name = cookie.split('=')[0].trim(); 674 if (name.includes(pattern) || name.startsWith(pattern)) { 675 document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/`; 676 document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${window.location.hostname}`; 677 document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.${window.location.hostname}`; 678 } 679 }); 680 }); 681 } 682 })(); 683 684 /* ---------- Continuous Cookie Monitoring ---------- */ 685 function startCookieMonitoring() { 686 // Check and clean unwanted cookies every 5 seconds 687 setInterval(() => { 688 const consent = loadConsent(); 689 690 // If no consent or analytics not allowed, clean analytics cookies 691 if (!consent || !consent.analytics) { 692 blockCookiesByPattern(ANALYTICS_COOKIES); 693 } 694 695 // If no consent or targeting not allowed, clean marketing cookies 696 if (!consent || !consent.targeting) { 697 blockCookiesByPattern(MARKETING_COOKIES); 698 } 699 }, 5000); 700 } 701 702 // Helper for conditional execution 703 window.runIfConsent = function(category, fn){ 704 const c = loadConsent(); 705 if(c && c[category]) { 706 try { fn(); } catch(e){ console.error(e); } 707 } 708 }; 709 710 /* ---------- Google Consent Mode v2 Integration ---------- */ 711 function initGoogleConsentMode() { 712 // Initialize Google Tag Manager Consent Mode v2 with denied defaults 713 if (typeof gtag !== 'undefined') { 714 gtag('consent', 'default', { 715 'ad_storage': 'denied', 716 'ad_user_data': 'denied', 717 'ad_personalization': 'denied', 718 'analytics_storage': 'denied', 719 'functionality_storage': 'granted', 720 'security_storage': 'granted', 721 'personalization_storage': 'denied', 722 'wait_for_update': 2000 723 }); 724 } 725 726 // Create gtag function if it doesn't exist yet 727 if (typeof gtag === 'undefined') { 728 window.dataLayer = window.dataLayer || []; 729 function gtag(){dataLayer.push(arguments);} 730 window.gtag = gtag; 731 gtag('js', new Date()); 732 733 gtag('consent', 'default', { 734 'ad_storage': 'denied', 735 'ad_user_data': 'denied', 736 'ad_personalization': 'denied',
737 'analytics_storage': 'denied', 738 'functionality_storage': 'granted', 739 'security_storage': 'granted', 740 'personalization_storage': 'denied', 741 'wait_for_update': 2000 742 }); 743 } 744 } 745 746 // Initialize Google Consent Mode immediately 747 initGoogleConsentMode(); 748 749 }); // End of waitForjQuery callback 750})(); // End of IIFE
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.