PageSourceSearch

https://radiocomercial.pt/scripts/ad-placements.js?v=1.2

js radiocomercial.pt collected 2026-10-02 02:46:03 UTC 8,326 bytes, 172 lines download raw bytes

1/* ============================================================
2   ad-placements.js — CLEAN-ROOM (pagina /teste)
3   Helper para inserir <ad-placement> (custom element do TagBundle)
4   SEM espalhar markup e includes SSI pela pagina.
5
6   Dois modos:
7     1) DECLARATIVO — poe no HTML apenas:
8            <div data-ad="leaderboard-1" data-format="Billboard"></div>
9        e este script expande-o para o <ad-placement> completo.
10     2) IMPERATIVO — RCAds.insert('#alvo', { id:'leaderboard-9', format:'Billboard' });
11
12   Porque funciona: <ad-placement> e um Web Component do SDK TagBundle;
13   auto-renderiza quando entra no DOM, desde que o SDK ja tenha corrido
14   o .init(). Em dev (.local) o gate NAO chama init, por isso o elemento
15   aparece no DOM mas SEM anuncio — comportamento esperado, nao e bug.
16
17   Atributos data-* suportados no modo declarativo:
18     data-ad        (obrigatorio) id do slot        -> id + adunit
19     data-format    Billboard | Mrec | Halfpage ... -> format   (def: Billboard)
20     data-adunit    override do adunit              (def: BMAP_Comercial/<id>)
21     data-refresh   "true"/"false"                  (def: false)
22     data-lazyload  "true"/"false"                  (def: true)
23     data-targeting string GAM                      (def: type=premium;obs=123)
24
25   ATENCAO -- NUNCA ESCREVER A TAG ad-placement DENTRO DE UM COMENTARIO HTML
26   -------------------------------------------------------------------------
27   Escreve-se "ad-placement" em texto, SEM os sinais de maior/menor.
28   Porque: o gerador de paginas estaticas
29   (S:\AutomaticPageGenerationPy, shrink_content e clean_adplacement) limpa o
30   interior dos anuncios renderizados com uma regex do tipo
31   "abre-tag ad-placement ... qualquer coisa ... fecha-tag ad-placement".
32   Essa regex nao sabe o que e um comentario: se o comentario tiver a tag
33   escrita por extenso, o motor arranca ALI e come tudo ate ao fecho do
34   anuncio SEGUINTE -- incluindo o "-->" do proprio comentario. O comentario
35   fica sem fecho e engole o markup a seguir.
36   Foi isso que aconteceu no /noticias: o leaderboard-1 e o out-of-page
37   ficavam DENTRO de um comentario na pagina gerada (out-of-page = 0
38   ocorrencias no HTML final), e a pub "as vezes nao aparecia" -- so os slots
39   mais abaixo na pagina sobreviviam.
40   E a mesma armadilha do tcf-listener.js, noutra forma: ali era o nome da
41   API de consentimento a apagar um script inline, aqui e o nome da tag a
42   apagar markup. Regra geral: nos comentarios nao se escrevem os nomes que
43   o gerador procura.
44
45   RESERVA DE ESPACO DO BILLBOARD DO TOPO (anti layout shift)
46   -------------------------------------------------------------------------
47   O billboard do topo esta ACIMA do header. Sem altura reservada, o slot
48   media 0px e ao chegar o anuncio empurrava o header e o menu 250px para
49   baixo: quem ia clicar no hamburguer acabava a clicar na pub. Medido na
50   homepage de producao: CLS 0.4693 e o menu de y=80 para y=330.
51
52   A RESERVA NAO ESTA AQUI, DE PROPOSITO. Esta em CSS estatico no global.css
53   (selector div[data-ad="leaderboard-1"], que ja vem no HTML do servidor) e
54   e ligada por um script sincrono no head, no config.xsl. Tentei primeiro
55   faze-la aqui, marcando o elemento por JS, e medi o resultado: ficou PIOR
56   que o bug. O JS so corre depois da primeira pintura, logo a reserva
57   passava a ser ela propria um segundo salto de 250px -- CLS de 0.2847 para
58   0.4622, em todas as cargas, mesmo nas que nao tinham anuncio.
59   Licao: reserva de espaco tem de vir do HTML/CSS da primeira pintura;
60   por JS chega sempre tarde.
61
62   O que sobra para este script e SO o colapso: quando o GAM diz que o slot
63   veio vazio, tira-se o espaco. E por EVENTO, nunca por temporizador --
64   medi anuncios a chegar aos 941ms mas tambem aos 13897ms, porque a pub
65   espera pelo consentimento do CMP, e um temporizador curto colapsaria o
66   espaco justo a tempo de o anuncio empurrar o header outra vez.
67   O registo vai pelo googletag.cmd, que aceita callbacks antes de o SDK
68   existir; um addEventListener directo perdia os eventos.
69   ============================================================ */
70(function (w, d) {
71    'use strict';
72
73    var DEFAULTS = {
74        format: 'Billboard',
75        refresh: 'false',
76        lazyload: 'true',
77        targeting: 'type=premium;obs=123'
78    };
79
80    // Constroi o elemento <ad-placement> a partir de um objecto de opcoes.
81    function build(opts) {
82        if (!opts || !opts.id) { console.warn('RCAds: falta o "id" do ad'); return null; }
83        var ad = d.createElement('ad-placement');
84        ad.id = opts.id;
85        ad.setAttribute('adunit', opts.adunit || ('BMAP_Comercial/' + opts.id));
86        ad.setAttribute('format', opts.format || DEFAULTS.format);
87        ad.setAttribute('refresh', String(opts.refresh != null ? opts.refresh : DEFAULTS.refresh));
88
89        var lazy = opts.lazyload != null ? opts.lazyload : DEFAULTS.lazyload;
90        if (lazy !== false && lazy !== 'false') ad.setAttribute('lazyload', 'true');
91
92        var targeting = opts.targeting != null ? opts.targeting : DEFAULTS.targeting;
93        if (targeting) ad.setAttribute('targeting', targeting);
94
95        if (opts.className) ad.className = opts.className;
96        return ad;
97    }
98
99    // Insere um ad dentro de um alvo (selector CSS ou elemento).
100    function insert(target, opts) {
101        var host = typeof target === 'string' ? d.querySelector(target) : target;
102        if (!host) { console.warn('RCAds: alvo nao encontrado ->', target); return null; }
103        var ad = build(opts);
104        if (ad) host.appendChild(ad);
105        return ad;
106    }
107
108    // Expande todos os placeholders [data-ad] da pagina (idempotente).
109    function expand(root) {
110        var scope = root || d;
111        var nodes = scope.querySelectorAll('[data-ad]');
112        Array.prototype.forEach.call(nodes, function (node) {
113            if (node.getAttribute('data-ad-done') === '1') return;
114            var ad = build({
115                id:        node.getAttribute('data-ad'),
116                format:    node.getAttribute('data-format'),
117                adunit:    node.getAttribute('data-adunit'),
118                refresh:   node.getAttribute('data-refresh'),
119                lazyload:  node.getAttribute('data-lazyload'),
120                targeting: node.getAttribute('data-targeting')
121            });
122            if (ad) { node.appendChild(ad); node.setAttribute('data-ad-done', '1'); }
123        });
124    }
125
126    // ---------------- colapso do billboard do topo, se vier vazio ----------
127
128    var ID_TOPO   = 'leaderboard-1';
129    var CLS_VAZIO = 'rc-pub-vazio';
130
131    // O espaco reservado esta no div[data-ad] do markup (o .text-center), nao
132    // no <ad-placement>: e o div que ocupa o lugar no fluxo, e assim o slot em
133    // si continua a medir o anuncio, sem min-height a mentir sobre a altura.
134    function divDoTopo() {
135        return d.querySelector('div[data-ad="' + ID_TOPO + '"]');
136    }
137
138    // Colapsa quando o GAM diz que o slot veio vazio, e devolve o espaco se um
139    // refresh trouxer anuncio (o leaderboard-1 tem refresh de 30s).
140    function ouvirGam() {
141        var alvo = divDoTopo();
142        if (!alvo) return;
143        w.googletag = w.googletag || { cmd: [] };
144        w.googletag.cmd.push(function () {
145            try {
146                w.googletag.pubads().addEventListener('slotRenderEnded', function (e) {
147                    var id;
148                    try { id = e.slot.getSlotElementId(); } catch (err) { return; }
149                    if (id !== ID_TOPO) return;
150                    alvo.classList.toggle(CLS_VAZIO, !!e.isEmpty);
151                });
152            } catch (err) {
153                console.warn('RCAds: nao consegui ouvir o slotRenderEnded ->', err);
154            }
155        });
156    }
157
158    function arrancar() {
159        expand();
160        ouvirGam();
161    }
162
163    // API publica
164    w.RCAds = { insert: insert, build: build, expand: expand };
165
166    // Auto-expandir assim que o DOM estiver pronto.
167    if (d.readyState === 'loading') {
168        d.addEventListener('DOMContentLoaded', arrancar);
169    } else {
170        arrancar();
171    }
172})(window, document);

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.