1/* content/custom/js/ad-age-treatment.js â Knowalot site-specific. 2 * 3 * Stamps data-tag-for-age-treatment="1" (TFAT â child treatment) onto every 4 * <ins class="adsbygoogle"> before AdSense requests an ad for it. 5 * 6 * WHY THIS FILE EXISTS 7 * Knowalot is a child-directed site. Google's Tag For Age Treatment disables 8 * interest-based advertising and remarketing for the tagged request, and a 9 * per-request tag takes precedence over any site-level setting. The shared 10 * CMS renderer (lib/AdSenseManager.php :: renderInsForFormats) does not emit 11 * the attribute and must not be edited from this site, so we add it here. 12 * 13 * Values, per Google: "1" = child, "2" = teen, "0" = no age treatment. 14 * This is BELT-AND-BRACES, not the primary control â the site should also be 15 * tagged as child-directed in the Google dashboard. 16 * 17 * WHY THE TIMING WORKS 18 * Both template and custom scripts are emitted as <script defer>, and 19 * CustomAssets tags are emitted AFTER the template block (see the {{{assets.js}}} 20 * then {{{custom.js}}} order in the head template). Deferred scripts execute in 21 * document order once the DOM is fully parsed, so at the moment this file runs: 22 * 23 * - every server-rendered <ins> is already in the DOM, and 24 * - template/js/ads.js has executed but has only REGISTERED its 25 * window.addEventListener('load', pushPending) handler â no 26 * adsbygoogle.push() has fired yet. 27 * 28 * So the synchronous stampAll() below is what actually guarantees correctness. 29 * The observer and the push wrapper are defence in depth for <ins> elements 30 * that might be inserted later, or for a future change to script ordering. 31 */ 32(function () { 33 'use strict'; 34 35 /* "1" = child-directed treatment. Change to "2" for teen treatment, or 36 "0" to disable, if the site's audience designation ever changes. */ 37 var AGE_TREATMENT = '1'; 38 39 var ATTR = 'data-tag-for-age-treatment'; 40 var SELECTOR = 'ins.adsbygoogle'; 41 42 /** Stamp every un-stamped ad slot. Cheap and safe to call repeatedly. */ 43 function stampAll() { 44 var slots = document.querySelectorAll(SELECTOR); 45 for (var i = 0; i < slots.length; i++) { 46 if (!slots[i].hasAttribute(ATTR)) { 47 slots[i].setAttribute(ATTR, AGE_TREATMENT); 48 } 49 } 50 return slots.length; 51 } 52 53 /* 1. The one that matters â runs before ads.js's window.load push. */ 54 stampAll(); 55 56 /* 2. Catch any <ins> injected into the DOM after this point (a late 57 server-emitted block, or a future auto-inject placement). Stamping 58 happens synchronously inside the mutation callback, which fires 59 before the browser can dispatch window.load. */ 60 var observer = null; 61 if (window.MutationObserver) { 62 try { 63 observer = new MutationObserver(function () { stampAll(); }); 64 observer.observe(document.documentElement, { childList: true, subtree: true }); 65 } catch (e) { observer = null; } 66 } 67 68 /* 3. Last line of defence: stamp at the moment anything is pushed to the 69 AdSense queue, so no request can leave untagged even if 1 and 2 both 70 somehow missed a slot. Wrapping the queue array's push is safe â it 71 is the documented AdSense pattern to create it if absent, and we 72 always call through to the original. */ 73 try { 74 var queue = (window.adsbygoogle = window.adsbygoogle || []); 75 if (!queue.__kwAgeTreatmentWrapped && typeof queue.push === 'function') { 76 var originalPush = queue.push; 77 queue.push = function () { 78 try { stampAll(); } catch (e) { /* never block an ad request */ } 79 return originalPush.apply(this, arguments); 80 }; 81 queue.__kwAgeTreatmentWrapped = true; 82 } 83 } catch (e) { 84 /* Queue frozen or replaced by the AdSense loader â step 1 already 85 covered every server-rendered slot, so this is not fatal. */ 86 } 87 88 /* Stop observing once ads.js has pushed; anything added later would not 89 be requested by ads.js anyway. */ 90 window.addEventListener('load', function () { 91 stampAll(); 92 if (observer) { 93 setTimeout(function () { try { observer.disconnect(); } catch (e) {} }, 5000); 94 } 95 }); 96}());
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.