PageSourceSearch

https://www.haberler.com/mstatic/assets/js/ads.js?v=2

js haberler.com collected 2026-09-24 08:29:50 UTC 29,246 bytes, 605 lines download raw bytes

1
2(function () {
3    "use strict";
4
5    if (window.__hbAdsLoaded) { return; }
6    window.__hbAdsLoaded = true;
7
8    window.googletag = window.googletag || { cmd: [] };
9    if (!document.querySelector('script[src*="securepubads.g.doubleclick.net/tag/js/gpt.js"]')) {
10        var gptScript = document.createElement("script");
11        gptScript.async = true;
12        gptScript.src = "https://securepubads.g.doubleclick.net/tag/js/gpt.js";
13        document.head.appendChild(gptScript);
14    }
15
16    function onReady(fn) {
17        if (document.readyState === "loading") {
18            document.addEventListener("DOMContentLoaded", fn, { once: true });
19        } else {
20            fn();
21        }
22    }
23
24    /* ============================== BANNER ============================== */
25
26    // Slot envanteri GAM/YM paneli tag ciktisiyla birebir ayni tutulur
27    // (Haberler_Desktop_Adunits / Haberler_Mobile_Adunits, 2026-08-31);
28    // fark olusursa otorite panel ciktisidir. collapseDiv slot bazinda degil,
29    // sayfa seviyesinde tek politika (GAM audit Fix 6): dolum gelmeyen her
30    // slot kapanir.
31    var BANNER_SETS = {
32        home_desktop: [
33            { unit: "/1007216/Haberler//Desktop/AnaSayfa_970x250_1", sizes: [[728, 90], [970, 250], [468, 60], [970, 90]], div: "ana_masthead_1056x250" },
34            { unit: "/1007216/Haberler//Desktop/AnaSayfa_970x250_2", sizes: [[728, 90], [468, 60], [970, 90], [970, 250]], div: "ana_masthead_1056x250_2" },
35            { unit: "/1007216/Haberler//Desktop/AnaSayfa_300x600", sizes: [[300, 600], [120, 600], [160, 600]], div: "ana_desktop_300x600" },
36            { unit: "/1007216/Haberler//Desktop/AnaSayfa_160x600_Sol", sizes: [[160, 600], [120, 600]], div: "ana_160x600_sol" },
37            { unit: "/1007216/Haberler//Desktop/AnaSayfa_160x600_Sag", sizes: [[160, 600], [120, 600]], div: "ana_160x600_sag" }
38        ],
39        home_mobile: [
40            { unit: "/1007216/Haberler//Mobile/AnaSayfa_Masthead", sizes: [[320, 50], [320, 100], [300, 100]], div: "ana_masthead_320x100_reklam_divi" },
41            { unit: "/1007216/Haberler//Mobile/AnaSayfa_336x280_1", sizes: [[300, 250], [200, 200], [250, 250], [336, 280]], div: "ana_mobile_336x280_1" }
42        ],
43        // nwsKeywords icinde "Dünya Kupası" gectiginde masthead/kuleler ayri
44        // config ile (prebid_takim_dunyakupasi_configv5.js) WC slotlarina doner.
45        detail_desktop: [
46            { unit: "/1007216/Haberler//Desktop/DetaySayfa_970x250", sizes: [[970, 250], [970, 90], [468, 60], [728, 90]], div: "detay_masthead_1056x250", k
46at: true },
47            { unit: "/1007216/Haberler//Desktop/DetaySayfa_300x600", sizes: [[160, 600], [300, 600], [120, 600]], div: "detay_desktop_300x600", kat: true },
48            { unit: "/1007216/Haberler//Desktop/DetaySayfa_336x280", sizes: [[200, 200], [300, 250], [336, 280], [250, 250]], div: "native_desktop_300x250", kat: true },
49            { unit: "/1007216/Haberler//Desktop/DetaySayfa_160x600_Sol", sizes: [[160, 600], [120, 600]], div: "detay_160x600_sol", kat: true },
50            { unit: "/1007216/Haberler//Desktop/DetaySayfa_160x600_Sag", sizes: [[160, 600], [120, 600]], div: "detay_160x600_sag", kat: true }
51        ],
52        detail_mobile: [
53            { unit: "/1007216/Haberler//Mobile/DetaySayfa_Masthead", sizes: [[320, 50], [300, 100], [320, 100]], div: "detay_masthead_320x100", kat: true },
54            { unit: "/1007216/Haberler//Mobile/DetaySayfa_336x280_1", sizes: [[300, 250], [250, 250], [336, 280], [200, 200]], div: "detay_mobile_336x280_1", kat: true },
55            { unit: "/1007216/Haberler//Mobile/DetaySayfa_336x280_2", sizes: [[200, 200], [250, 250], [300, 250], [336, 280]], div: "inpage_reklam", kat: true }
56        ]
57    };
58
59    // Kirilim, markup'in div yazan gate'i ile ayni olmak zorunda: scrw >= 970
60    // (Default.aspx ana_masthead ve HaberDetayNew.aspx masthead/336 gate'leri).
61    // Eski 1024/768 secimleri 769-1024 araliginda markup'ta olmayan div'lerin
62    // setini secip masthead'i dusuruyordu (GAM audit Issue F).
63    function bannerSet() {
64        var page = window.hbAds && window.hbAds.page;
65        if (page !== "home" && page !== "detail") { return null; }
66        var w = (typeof window.scrw === "number" && window.scrw > 0) ? window.scrw : window.innerWidth;
67        if (page === "home") {
68            return (w >= 970) ? BANNER_SETS.home_desktop : BANNER_SETS.home_mobile;
69        }
70        return (w >= 970) ? BANNER_SETS.detail_desktop : BANNER_SETS.detail_mobile;
71    }
72
73    // GAM audit Fix 3: display atlanirsa artik sessiz degil, GA'da izlenebilir.
74    function canary(divId) {
75        try {
76            window.dataLayer = window.dataLayer || [];
77            window.dataLayer.push({ event: "ad_div_missing", slotId: divId });
78        } catch (e) { }
79    }
80
81    // GAM audit Issue G: catch'ler sayfayi korur ama hatayi yutmasin.
82    function adError(where, e) {
83        try {
84            window.dataLayer = window.dataLayer || [];
85            window.dataLayer.push({ event: "ad_error", where: where, msg: String(e).slice(0, 120) });
86        } catch (e2) { }
87    }
88
89    function initBanners() {
90        var set = bannerSet();
91        if (!set) { return; }
92
93        window.googletag = window.googletag || { cmd: [] };
94        window.googletag.cmd.push(function () {
95            var g = window.googletag;
96            var kat = (typeof window.Haber_Kat !== "undefined" && window.Haber_Kat !== null) ? window.Haber_Kat : "";
97            var defined = [];
98
99            set.forEach(function (s) {
100                if (!document.getElementById(s.div)) {
101                    canary(s.div);
102                    return;
103                }
104                try {
105                    var slot = g.defineSlot(s.unit, s.sizes, s.div);
106                    if (!slot) { return; }
107                    if (s.kat) { slot.setConfig({ targeting: { Haber_Kat: [kat] } }); }
108                    slot.addService(g.pubads());
109                    defined.push(s.div);
110                } catch (e) { adError("define:" + s.div, e); }
111            });
112
113            g.setConfig({ collapseDiv: "ON_NO_FILL" });
114
115            g.pubads().enableSingleRequest();
116            g.enableServices();
117
118            defined.forEach(function (id) {
119                try { g.display(id); } catch (e) { adError("display:" + id, e); }
120            });
121        });
122    }
123
124    /* =========================== INTERSTITIAL ===========================
125     * interstitial_v5.js'ten tasindi (Admatic <-> GAM rotasyonu).
126     *
127     * Behaviour
128     *   - GAM_SHARE of pageviews get the new GAM interstitial, the rest Admatic.
129     *   - Hard cutoff: after CUTOFF the GAM branch is dead and 100% goes to
130     *     Admatic. No code change, no midnight deploy.
131     *   - If GAM cannot be served (GPT never becomes ready), we fall back to
132     *     Admatic rather than showing nothing.
133     *
134     * QA / diagnostics
135     *   - ?adtest=gam | ?adtest=admatic  force a provider (bypasses split+cutoff)
136     *   - ?addebug=1                     turn the stage log on without a deploy
137     *   - Both flags stick to the session, because a web interstitial only
138     *     renders on the NEXT navigation - by then the query string is gone and
139     *     the console has been cleared. Clear with ?adtest=off / ?addebug=0.
140     *   - The stage log is mirrored into sessionStorage, so after the navigation
141     *     that actually shows (or fails to show) the ad you can call
142     *     interstitialLog() in the console and read the whole sequence,
143     *     including the entries from the previous page.
144     *   - Logging is always on for localhost.
145     *
146     * Page context
147     *   - gpt.js is loaded once by this file's own loader at the top of the
148     *     IIFE; pages carry no gpt.js tag of their own.
149     *   - enableSingleRequest()/enableServices() are called by the banner
150     *     module above, NOT here. Both run after DOMContentLoaded, so
151     *     pubadsReady flips shortly after gpt.js arrives. We wait for it
152     *     instead of enabling the service ourselves: calling enableServices()
153     *     first would make the banner module's later enableSingleRequest() a
154     *     no-op and drop SRA for every banner slot.
155     *   - The Admatic <ins class="adm-ads-area"> tags are always in the markup;
156     *     they simply stay inert when showad.min.js is not loaded.
157     * ==================================================================== */
158    function initInterstitial() {
159
160        /* ------------------------------- CONFIG ------------------------------- */
161
162        var CONFIG = {
163            // Share of users that see the NEW GAM interstitial. 0.10 = 10%,
164            // i.e. the remaining 90% keeps getting Admatic.
165            // Change this one number to re-balance (0 = all Admatic, 1 = all GAM).
166            GAM_SHARE: 0.70,
167
168            // Stop serving GAM after this moment: 2 Sep 2026, 23:59:59 Istanbul.
169            // Explicit +03:00 offset => identical instant for every visitor.
170            CUTOFF: "2026-09-02T23:59:59+03:00",
171
172            URL_MATCH: "-haberi",
173
174            ADMATIC_SRC: "https://static.cdn.admatic.com.tr/showad/showad.min.js",
175
176            // Web Interstitial ad units. These are served through
177            // googletag.enums.OutOfPageFormat.INTERSTITIAL, so they have no div
178            // container of their own - GPT owns the overlay.
179            GAM: {
180                desktop: { unit: "/29678983/Haberler_Desktop_Interstitial_GPD_2025" },
181                mobile: { unit: "/29678983/Haberler_Mobile_Interstitial_GPD_2025" }
182            },
183
184            // Below this width => mobile. 768 matches the membrana tag in
185            // Main.master, which uses `scrw >= 768` for desktop.
186            MOBILE_BREAKPOINT: 768,
187
188            // Also treat Main.master's UA check (cihaz_mobilmi) as a mobile signal.
189            // Set false to key off width alone, exactly like the membrana tag.
190            USE_UA_SIGNAL: true,
191
192            // How long to wait for GPT/enableServices before giving up on GAM and
193            // falling back to Admatic (ms). The banner module runs at
194            // DOMContentLoaded but gpt.js is async and can arrive late on slow
195            // networks, so this stays generous: a short window silently sent
196            // almost every GAM pageview to Admatic.
197            PUBADS_WAIT_MS: 8000,
198
199            // How often to report "still waiting for pubads" while polling (ms).
200            WAIT_REPORT_EVERY_MS: 1000,
201
202            // When to audit the Admatic <ins> tags for a rendered creative (ms
203            // after showad.min.js is appended).
204            ADMATIC_CHECK_MS: 4000,
205
206            DEBUG: false
207        };
208
209        var STORE_KEY = "__interstitial_stages";
210        var FLAG_DEBUG = "__interstitial_debug";
211        var FLAG_ADTEST = "__interstitial_adtest";
212
213        /* ------------------------------- HELPERS ------------------------------ */
214
215        var t0 = Date.now();
216
217        function queryParam(name) {
218            var m = new RegExp("[?&]" + name + "=([^&#]*)").exec(window.location.search);
219            return m ? decodeURIComponent(m[1]) : null;
220        }
221
222        function session(key, value) {
223            try {
224                if (value === undefined) { return window.sessionStorage.getItem(key); }
225                if (value === null) { window.sessionStorage.removeItem(key); return null; }
226                window.sessionStorage.setItem(key, value);
227                return value;
228            } catch (e) { return null; }        // private mode / storage disabled
229        }
230
231        // A web interstitial renders on the next navigation, so a query-string-only
232        // flag would be lost exactly when it matters. Sticky for the session.
233        function stickyFlag(storageKey, queryName, offValues) {
234            var q = queryParam(queryName);
235            if (q === null) { return session(storageKey); }
236            if (offValues.indexOf(q) !== -1) { session(storageKey, null); return null; }
237            return session(storageKey, q);
238        }
239
240        var isLocal = /^(localhost|127\.0\.0\.1|\[::1\])$/.test(window.location.hostname) ||
241            /\.local$/.test(window.location.hostname);
242
243        var debugFlag = stickyFlag(FLAG_DEBUG, "addebug", ["0", "off", "false"]);
244        var debugOn = CONFIG.DEBUG || isLocal || debugFlag === "1";
245
246        // Every stage goes through here: console for the current page, plus
247        // sessionStorage so the sequence survives the navigation that renders the
248        // interstitial. Read it back with interstitialLog().
249        function stage(name, detail) {
250            var entry = {
251                t: Date.now() - t0,
252                page: window.location.pathname,
253                stage: name,
254                detail: detail === undefined ? null : detail
255            };
256
257            if (debugOn) {
258                try {
259                    var raw = session(STORE_KEY);
260                    var all = raw ? JSON.parse(raw) : [];
261                    all.push(entry);
262                    if (all.length > 300) { all = all.slice(-300); }
263                    session(STORE_KEY, JSON.stringify(all));
264                } catch (e) { }
265
266                if (window.console && console.log) {
267                    var prefix = "[interstitial +" + entry.t + "ms] " + name;
268                    if (detail === undefined) { console.log(prefix); }
269                    else { console.log(prefix, detail); }
270                }
271            }
272        }
273
274        // Console helper: the full sequence, including the previous page's stages.
275        window.interstitialLog = function () {
276            var raw = session(STORE_KEY);
277            var all = raw ? JSON.parse(raw) : [];
278            if (window.console && console.table) { console.table(all); }
279            return all;
280        };
281        window.interstitialLogClear = function () { session(STORE_KEY, null); return true; };
282
283        function onBodyReady(fn) {
284            if (document.body) { fn(); return; }
285            document.addEventListener("DOMContentLoaded", fn, { once: true });
286        }
287
288        // Main.master defines these in <head>, long before this async file runs:
289        //   scrw          -> viewport width (what the membrana tag keys off)
290        //   cihaz_mobilmi -> UA-based mobile flag
291        // Reusing them keeps the interstitial consistent with the rest of the
292        // page's ad logic instead of inventing a second device rule.
293        function detectDevice() {
294            var width = (typeof scrw === "number" && scrw > 0) ? scrw : window.innerWidth;
295            var uaMobile = CONFIG.USE_UA_SIGNAL && (typeof cihaz_mobilmi !== "undefined") && cihaz_mobilmi === true;
296            var device = (uaMobile || width < CONFIG.MOBILE_BREAKPOINT) ? "mobile" : "desktop";
297            stage("device-detected", { device: device, scrw: width, cihaz_mobilmi: uaMobile });
298            return device;
299        }
300
301        // googletag.pubadsReady flips to true only once enableServices() has run
302        // and PubAdsService is operational. This module is unordered relative to
303        // gpt.js arrival, so display() before that point would silently fail to
304        // fetch.
305        function whenPubadsReady(cb) {
306            var started = Date.now();
307            var lastReport = 0;
308
309            stage("gpt-wait-start", {
310                gptPresent: !!window.googletag,
311                apiReady: !!(window.googletag && window.googletag.apiReady),
312                pubadsReady: !!(window.googletag && window.googletag.pubadsReady),
313                timeoutMs: CONFIG.PUBADS_WAIT_MS
314            });
315
316            (function poll() {
317                var waited = Date.now() - started;
318
319                if (window.googletag && window.googletag.pubadsReady) {
320                    stage("gpt-ready", { waitedMs: waited });
321                    cb(true);
322                    return;
323                }
324
325                if (waited > CONFIG.PUBADS_WAIT_MS) {
326                    // Which link of the chain is missing tells you where to look:
327                    // no googletag at all  -> gpt.js blocked (adblock) or 404
328                    // apiReady, !pubadsReady -> banner module never ran
329                    //                           enableServices() in time
330                    stage("gpt-timeout", {
331                        waitedMs: waited,
332                        gptPresent: !!window.googletag,
333                        apiReady: !!(window.googletag && window.googletag.apiReady),
334                        pubadsReady: false,
335                        hint: !window.googletag || !window.googletag.apiReady
336                            ? "gpt.js yuklenmedi (adblock / network)"
337                            : "banner modulu enableServices() cagirmadi"
338                    });
339                    cb(false);
340                    return;
341                }
342
343                if (waited - lastReport >= CONFIG.WAIT_REPORT_EVERY_MS) {
344                    lastReport = waited;
345                    stage("gpt-waiting", {
346                        waitedMs: waited,
347                        apiReady: !!(window.googletag && window.googletag.apiReady)
348                    });
349                }
350
351                setTimeout(poll, 50);
352            })();
353        }
354
355        /* ------------------------------ PROVIDERS ----------------------------- */
356
357        function runAdmatic(reason) {
358            stage("admatic-selected", { reason: reason });
359
360            // showad.min.js looks for the <ins class="adm-ads-area"> tags, which
361            // live in the body. Appending after the body exists keeps the old
362            // (working) ordering instead of racing the markup.
363            onBodyReady(function () {
364                var tags = document.querySelectorAll("ins.adm-ads-area");
365                stage("admatic-ins-tags", {
366                    count: tags.length,
367                    slots: [].map.call(tags, function (el) { return el.getAttribute("data-ad-slot"); })
368                });
369
370                if (!tags.length) {
371                    // Server-side gate did not render the markup (kripto sponsorluk
372                    // donemi, wrong status code, different master).
373                    stage("admatic-no-markup", "ins.adm-ads-area yok - sunucu tarafi gate kapali");
374                }
375
376                var s = document.createElement("script");
377                s.src = CONFIG.ADMATIC_SRC;
378                s.async = true;
379                s.onload = function () {
380                    stage("admatic-script-loaded");
381                    setTimeout(auditAdmatic, CONFIG.ADMATIC_CHECK_MS);
382                };
383                s.onerror = function () {
384                    stage("admatic-script-error", "showad.min.js yuklenemedi (adblock / network)");
385                };
386                document.body.appendChild(s);
387                stage("admatic-script-appended", CONFIG.ADMATIC_SRC);
388            });
389        }
390
391        // "Script yuklendi ama reklam gelmedi" ile "script hic yuklenmedi" ayrimi.
392        function auditAdmatic() {
393            var tags = document.querySelectorAll("ins.adm-ads-area");
394            var filled = 0;
395            var report = [].map.call(tags, function (el) {
396                var hasCreative = !!el.querySelector("iframe, img, div") || el.children.length > 0;
397                if (hasCreative) { filled++; }
398                return {
399                    slot: el.getAttribute("data-ad-slot"),
400                    children: el.children.length,
401                    hasCreative: hasCreative
402                };
403            });
404
405            stage(filled ? "admatic-filled" : "admatic-empty", {
406                checkedAfterMs: CONFIG.ADMATIC_CHECK_MS,
407                filled: filled,
408                of: tags.length,
409                tags: report
410            });
411        }
412
413        function runGam() {
414            stage("gam-selected");
415
416            // Safety net only - gpt.js is loaded elsewhere, but it may not have
417            // created the stub yet.
418            window.googletag = window.googletag || { cmd: [] };
419
420            whenPubadsReady(function (ready) {
421                if (!ready) {
422                    // GPT never became operational (blocked, slow, or the banner module
423                    // did not run on this page). We deliberately do NOT call
424                    // enableServices() ourselves - if the banner module later calls
425                    // enableSingleRequest(), SRA would be dropped for every banner slot.
426                    // Falling back to Admatic keeps the impression instead of losing it.
427                    runAdmatic("gpt-timeout-fallback");
428                    return;
429                }
430
431                var target = CONFIG.GAM[detectDevice()];
432
433                window.googletag.cmd.push(function () {
434                    var pubads = window.googletag.pubads();
435
436                    stage("gam-defining-slot", {
437                        unit: target.unit,
438                        format: "OutOfPageFormat.INTERSTITIAL",
439                        initialLoadDisabled: !!(pubads.isInitialLoadDisabled && pubads.isInitialLoadDisabled())
440                    });
441
442                    // Web Interstitial format. Passing a div id here instead of the
443                    // format enum defines a legacy/custom out-of-page slot, which
444                    // never matches an ad unit configured as a web interstitial in
445                    // GAM - the request goes out and comes back empty. This is the
446                    // same shape interstitial_260310.js uses.
447                    var slot = window.googletag.defineOutOfPageSlot(
448                        target.unit,
449                        window.googletag.enums.OutOfPageFormat.INTERSTITIAL
450                    );
451
452                    if (!slot) {
453                        // Unsupported environment (e.g. an in-app webview) or the
454                        // format is not enabled for this unit.
455                        stage("gam-slot-null", "defineOutOfPageSlot null dondu - format bu ortamda/unit'te desteklenmiyor");
456                        runAdmatic("gam-slot-null-fallback");
457                        return;
458                    }
459
460                    slot.addService(pubads);
461                    stage("gam-slot-defined", { unit: target.unit });
462
463                    attachGamEvents(pubads, slot, target.unit);
464
465                    // No enableSingleRequest()/enableServices() here - the banner
466                    // module owns those. This slot is defined afterwards and sits on a
467                    // different network code (/29678983/ vs /1007216/), so GPT fetches
468                    // it in its own request. That is expected and leaves the banner
469                    // batch untouched.
470                    //
471                    // display() takes the slot object: an interstitial has no div.
472                    window.googletag.display(slot);
473                    stage("gam-display-called");
474
475                    // If anything on the page runs disableInitialLoad(), display()
476                    // alone will not fetch.
477                    if (pubads.isInitialLoadDisabled && pubads.isInitialLoadDisabled()) {
478                        pubads.refresh([slot]);
479                        stage("gam-refresh-called", "initial load disabled -> refresh([slot])");
480                    }
481
482                    // The overlay itself only appears on the next navigation, not on
483                    // load. An empty screen right after load is GPT behaviour, not a
484                    // bug - the stages above are what tell you whether it is armed.
485                    stage("gam-armed", "interstitial hazir - bir sonraki sayfa gecisinde gosterilir");
486                });
487            });
488        }
489
490        // The stages that answer "reklam cagrildi mi, doldu mu?".
491        //   slotRequested        -> istek GAM'e gitti
492        //   slotResponseReceived -> cevap dondu
493        //   slotRenderEnded      -> isEmpty:true  = eslesen line item yok (no fill)
494        //                           isEmpty:false = creative geldi
495        //   slotOnload           -> creative'in kendisi yuklendi
496        //   impressionViewable   -> kullanici gordu
497        // Bu listener'lar sadece bizim slot'umuzu raporlar; sayfadaki banner
498        // slot'larini gurultu yapmasin diye filtreliyoruz.
499        function attachGamEvents(pubads, slot, unit) {
500            function mine(event) { return event.slot === slot; }
501
502            pubads.addEventListener("slotRequested", function (event) {
503                if (mine(event)) { stage("gam-slot-requested", { unit: unit }); }
504            });
505
506            pubads.addEventListener("slotResponseReceived", function (event) {
507                if (mine(event)) { stage("gam-response-received", { unit: unit }); }
508            });
509
510            pubads.addEventListener("slotRenderEnded", function (event) {
511                if (!mine(event)) { return; }
512                stage(event.isEmpty ? "gam-empty-no-fill" : "gam-rendered", {
513                    unit: unit,
514                    isEmpty: event.isEmpty,
515                    size: event.size,
516                    creativeId: event.creativeId,
517                    lineItemId: event.lineItemId,
518                    advertiserId: event.advertiserId,
519                    campaignId: event.campaignId,
520                    isBackfill: event.isBackfill,
521                    hint: event.isEmpty
522                        ? "istek gitti, GAM bos dondu: eslesen line item / creative yok"
523                        : "creative geldi"
524                });
525            });
526
527            pubads.addEventListener("slotOnload", function (event) {
528                if (mine(event)) { stage("gam-creative-loaded", { unit: unit }); }
529            });
530
531            pubads.addEventListener("impressionViewable", function (event) {
532                if (mine(event)) { stage("gam-impression-viewable", { unit: unit }); }
533            });
534
535            stage("gam-events-attached");
536        }
537
538        /* -------------------------------- MAIN -------------------------------- */
539
540        stage("script-start", {
541            url: window.location.href,
542            debugSource: CONFIG.DEBUG ? "CONFIG.DEBUG" : (isLocal ? "localhost" : (debugFlag ? "?addebug" : "off")),
543            readyState: document.readyState
544        });
545
546        if (window.location.href.indexOf(CONFIG.URL_MATCH) === -1) {
547            stage("abort-url-mismatch", CONFIG.URL_MATCH + " icermeyen URL");
548            return;
549        }
550
551        var cutoffTs = Date.parse(CONFIG.CUTOFF);
552        var expired = !isNaN(cutoffTs) && Date.now() > cutoffTs;
553
554        // Sticky, like the debug flag: the split decision has to survive the
555        // navigation on which the interstitial actually renders.
556        var override = stickyFlag(FLAG_ADTEST, "adtest", ["off", "0", "none"]);
557
558        var useGam;
559        var reason;
560        if (override === "gam") {
561            useGam = true;             // QA override bypasses the split and the cutoff
562            reason = "override=gam";
563        } else if (override === "admatic") {
564            useGam = false;
565            reason = "override=admatic";
566        } else if (expired) {
567            useGam = false;
568            reason = "cutoff gecti (" + CONFIG.CUTOFF + ")";
569        } else {
570            var roll = Math.random();
571            useGam = roll < CONFIG.GAM_SHARE;
572            reason = "rastgele bolusum: " + roll.toFixed(3) + " < " + CONFIG.GAM_SHARE + " ? " + useGam;
573        }
574
575        stage("provider-chosen", {
576            provider: useGam ? "GAM" : "Admatic",
577            reason: reason,
578            expired: expired,
579            gamShare: CONFIG.GAM_SHARE,
580            override: override
581        });
582
583        if (useGam) { runGam(); } else { runAdmatic(reason); }
584    }
585
586    /* -------------------------------- MAIN -------------------------------- */
587
588    // QA: ?adtest=gam|admatic (veya onun session'a yapismis degeri) sunucu
589    // bayragi olmadan da interstitial modulunu acar - lokalde / TR disinda
590    // test icin. Uretim trafiginde gate yine window.hbAds.interstitialAllowed.
591    function qaOverrideActive() {
592        try {
593            if (/[?&]adtest=(gam|admatic)(&|#|$)/.test(window.location.search)) { return true; }
594            var v = window.sessionStorage.getItem("__interstitial_adtest");
595            return v === "gam" || v === "admatic";
596        } catch (e) { return false; }
597    }
598
599    onReady(function () {
600        try { initBanners(); } catch (e) { adError("initBanners", e); }
601        try {
602            if ((window.hbAds && window.hbAds.interstitialAllowed) || qaOverrideActive()) { initInterstitial(); }
603        } catch (e) { adError("initInterstitial", e); }
604    });
605})();

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.