[object Object]

← back to Re Flyer Aggregator

ad scanner: biggest firms first (agent_count) + Google Analytics & StatCounter detection + list advertisers found (TK-10708)

57d51c370950b308d30d5893bca6397d0ce3dff1 · 2026-08-19 16:08:06 -0700 · Steve Abrams

Files touched

Diff

commit 57d51c370950b308d30d5893bca6397d0ce3dff1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 19 16:08:06 2026 -0700

    ad scanner: biggest firms first (agent_count) + Google Analytics & StatCounter detection + list advertisers found (TK-10708)
---
 scripts/broker-ad-signals.mjs | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/scripts/broker-ad-signals.mjs b/scripts/broker-ad-signals.mjs
index c5d34bc..9b243ec 100644
--- a/scripts/broker-ad-signals.mjs
+++ b/scripts/broker-ad-signals.mjs
@@ -32,13 +32,17 @@ const SIG = {
   reddit_pixel: /redditstatic\.com\/ads\/pixel\.js|rdt\(\s*['"]init['"]/i,
   bing_uet: /bat\.bing\.com|\buetq\b/i,
   snap_pixel: /sc-static\.net\/scevent|snaptr\(\s*['"]init['"]/i,
-  google_analytics: /gtag\(\s*['"]config['"]\s*,\s*['"]G-|GTM-[A-Z0-9]+|google-analytics\.com\/analytics\.js/i, // measurement, not paid
+  // measurement / analytics (NOT paid ads) — Steve asked to also flag GA + StatCounter
+  google_analytics: /gtag\(\s*['"]config['"]\s*,\s*['"]G-|GTM-[A-Z0-9]+|google-analytics\.com\/analytics\.js|googletagmanager\.com\/gtag/i,
+  statcounter: /statcounter\.com|sc_project|c\d+\.statcounter\.com|StatCounter/i,
 };
 const PAID = ['google_ads', 'meta_pixel', 'tiktok_pixel', 'pinterest_tag', 'linkedin_insight', 'twitter_pixel', 'reddit_pixel', 'bing_uet', 'snap_pixel'];
+const MEASURE = ['google_analytics', 'statcounter'];
 
 // distinct commercial broker domains from the usre firm registry
+// biggest firms first (highest agent_count) — most likely to advertise
 const rows = execFileSync('psql', ['usre', '-t', '-A', '-c',
-  `SELECT DISTINCT website FROM firm WHERE hq_state='${STATE}' AND asset_class='commercial' AND website IS NOT NULL AND website<>'' LIMIT ${N * 3}`],
+  `SELECT website FROM firm WHERE hq_state='${STATE}' AND asset_class='commercial' AND website IS NOT NULL AND website<>'' ORDER BY agent_count DESC NULLS LAST LIMIT ${N * 4}`],
   { encoding: 'utf8' }).trim().split('\n').filter(Boolean);
 const domainOf = u => { try { return new URL(u.startsWith('http') ? u : 'https://' + u).hostname.replace(/^www\./, ''); } catch { return null; } };
 const domains = [...new Set(rows.map(domainOf).filter(Boolean))].slice(0, N);
@@ -55,7 +59,8 @@ for (const d of domains) {
     sig.scanned_at = new Date().toISOString();
     prior[d] = sig;
     const on = PAID.filter(k => sig[k]).map(k => k.replace('_pixel', '').replace('_tag', '').replace('_insight', '').replace('_uet', '').replace('_ads', '-ads'));
-    console.log(`  ${sig.paid_ads_count ? '💰' : '  '} ${d.padEnd(34)} ${on.join(', ') || '(no paid pixels)'}`);
+    const meas = MEASURE.filter(k => sig[k]).map(k => k === 'google_analytics' ? 'GA' : 'StatCounter');
+    console.log(`  ${sig.paid_ads_count ? '💰' : '  '} ${d.padEnd(34)} ${on.join(', ') || '—'}${meas.length ? '   [' + meas.join(',') + ']' : ''}`);
   } catch (e) {
     prior[d] = { error: e.message.slice(0, 40), scanned_at: new Date().toISOString() };
     console.log(`  ⚠ ${d.padEnd(34)} ${e.message.slice(0, 30)}`);
@@ -65,4 +70,8 @@ for (const d of domains) {
 }
 const scanned = Object.values(prior).filter(v => !v.error);
 const advertisers = scanned.filter(v => v.paid_ads_count > 0).length;
-console.log(`\nDone. ${scanned.length} scanned, ${advertisers} run paid ads. -> data/broker-ad-signals.json`);
+const ga = scanned.filter(v => v.google_analytics).length, sc = scanned.filter(v => v.statcounter).length;
+console.log(`\nDone. ${scanned.length} scanned · ${advertisers} run PAID ads · ${ga} Google Analytics · ${sc} StatCounter. -> data/broker-ad-signals.json`);
+// list the advertisers found
+for (const [dom, v] of Object.entries(prior)) if (v.paid_ads_count > 0)
+  console.log(`  💰 ${dom}: ${PAID.filter(k => v[k]).join(', ')}`);

← 7d35a29 ad-social-tracker on CA CRE brokers: slow rate-limited front  ·  back to Re Flyer Aggregator  ·  auto-data-snapshot: 2026-08-19T16:13:26 (1 data files) — dat fb372dc →