PageSourceSearch

https://www.knowalot.org/custom/js/ad-age-treatment.js?v=202606082152

js knowalot.org collected 2026-10-08 20:49:45 UTC 4,327 bytes, 96 lines download raw bytes

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.