← back to Re Flyer Aggregator
ad-intel: catch GTM-injected pixels (fetch+scan gtm.js containers, tag via_gtm) so paid-advertiser count isn't undercounted by static HTML; viewer stat now discloses unreachable + via-GTM counts (Cody gate) (TK-10708)
f042cb6327d7c4631ee4d80cdefd03499074aa2e · 2026-08-19 17:55:08 -0700 · Steve Abrams
Files touched
M public/advertising/index.htmlM scripts/broker-ad-signals.mjs
Diff
commit f042cb6327d7c4631ee4d80cdefd03499074aa2e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Aug 19 17:55:08 2026 -0700
ad-intel: catch GTM-injected pixels (fetch+scan gtm.js containers, tag via_gtm) so paid-advertiser count isn't undercounted by static HTML; viewer stat now discloses unreachable + via-GTM counts (Cody gate) (TK-10708)
---
public/advertising/index.html | 3 ++-
scripts/broker-ad-signals.mjs | 13 ++++++++++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/public/advertising/index.html b/public/advertising/index.html
index 93bf29b..da2fe22 100644
--- a/public/advertising/index.html
+++ b/public/advertising/index.html
@@ -66,7 +66,8 @@ function render(){
<td>${flyerCell(r)}</td>
<td style="color:#8A5A00;white-space:nowrap" title="${r.scanned_at||''}">${fmtWhen(r.scanned_at)}</td></tr>`).join('');
const adv=rows.filter(r=>r.paid_count>0).length,fl=rows.filter(r=>r.flyer_count>0).length;
- document.getElementById('stat').textContent=`${rows.length} brokers · ${adv} advertising · ${fl} with flyers`;
+ const errored=DATA.filter(r=>r.error).length, gtm=rows.filter(r=>(r.via_gtm||[]).length).length;
+ document.getElementById('stat').textContent=`${rows.length} scanned · ${adv} advertising${gtm?` (${gtm} via GTM)`:''} · ${fl} with flyers${errored?` · ${errored} unreachable`:''}`;
}
document.querySelectorAll('th').forEach(th=>th.onclick=()=>{const k=th.dataset.k;if(k==='_plats')return;if(sortK===k)sortDir*=-1;else{sortK=k;sortDir=(k==='firm'||k==='domain')?1:-1;}render();});
document.getElementById('q').oninput=render;document.getElementById('filt').onchange=render;
diff --git a/scripts/broker-ad-signals.mjs b/scripts/broker-ad-signals.mjs
index 3ead72d..96f425c 100644
--- a/scripts/broker-ad-signals.mjs
+++ b/scripts/broker-ad-signals.mjs
@@ -75,7 +75,18 @@ for (const t of targets) {
try {
const res = await fetch('https://' + t.domain + '/', { headers: { 'User-Agent': UA }, redirect: 'follow', signal: AbortSignal.timeout(15000) });
const html = await res.text();
- for (const p of PLATS) rec[p] = AD[p].test(html);
+ // GTM injects pixels client-side that never appear in raw HTML — fetch the container(s) and scan them too.
+ const gtmIds = [...new Set((html.match(/GTM-[A-Z0-9]+/g) || []))].slice(0, 3);
+ let gtmBlob = '';
+ for (const id of gtmIds) {
+ try {
+ const g = await fetch(`https://www.googletagmanager.com/gtm.js?id=${id}`, { headers: { 'User-Agent': UA }, signal: AbortSignal.timeout(10000) });
+ if (g.ok) gtmBlob += '\n' + await g.text();
+ } catch {}
+ }
+ rec.gtm_ids = gtmIds;
+ const scan = html + gtmBlob;
+ for (const p of PLATS) { rec[p] = AD[p].test(scan); if (rec[p] && !AD[p].test(html)) (rec.via_gtm = rec.via_gtm || []).push(p); }
rec.paid_count = PLATS.filter(p => rec[p]).length;
rec.google_analytics = google_analytics.test(html);
rec.statcounter = statcounter.test(html);
← 24ceb01 auto-data-snapshot: 2026-08-19T17:51:58 (1 data files) — pub
·
back to Re Flyer Aggregator
·
ingest-public-deals: fix LIMIT NaN crash when run without -- c127446 →