Pixel Auditor/Help/How detection works

How detection works

The four-layer detection architecture: globals, scripts, network, JS hooks.

Pixel Auditor uses four parallel detection strategies. Whichever fires first wins; subsequent confirmations are merged. Every layer runs at document_start, before the page's own scripts execute, so nothing slips past.

Layer 1 — JavaScript global scanning

Watches the global object for known platform signatures the moment they're defined: window.gtag, window.google_tag_manager, window.fbq, window._fbq, window._uetq, window.UET, window.clarity, window._linkedin_partner_id, window._linkedin_data_partner_ids, window.lintrk, plus globals for major server-side / vendor-API SDKs detected as part of SST classification.

Layer 2 — DOM script scanning

Parses every <script> tag's src and content against platform-specific regexes. Catches:

  • googletagmanager.com/gtm.js, gtag/js, analytics.js
  • connect.facebook.net/.../fbevents.js
  • snap.licdn.com/li.lms-analytics/insight.min.js
  • bat.bing.com/bat.js, clarity.ms/tag
  • Inline event-tracking blocks containing fbq('init',, gtag('config',, etc.

A MutationObserver watches for dynamically injected <script> nodes after page load — Pixel Auditor catches lazy-loaded tags injected by your CMP, by GTM, or by a feature flag.

Layer 3 — Network interception

Patches native browser APIs at document_start. Originals are preserved as _fetch, _open/_send, _Image, _beacon and always called through.

  • window.fetch — catches GA4 /g/collect, Meta /tr, Bing bat.bing.com, etc.
  • XMLHttpRequest.open / send — same pattern
  • new Image() — image-beacon pixels (1×1 GIFs)
  • navigator.sendBeacon — page-unload tracking

Layer 4 — JS API hooks

Wraps tag SDK functions while preserving identity. Each hook captures, then passes through:

// Pixel Auditor's interception is a thin wrapper: const original = window.gtag; window.gtag = function(...args) { PixelAuditor.capture(args); // log it return original.apply(this, args); // pass through };
  • dataLayer.push() — every GTM/GA4 event, routed by send_to prefix (G-, AW-, MC-)
  • gtag() — both gtag('event', …) and gtag('consent', …)
  • fbq() — Meta track / trackCustom, iterating all initialized pixels
  • uetq.push(), UET constructor — Bing UET (array queue + instance)
  • clarity() — Microsoft Clarity JS calls

Re-scan timing

The four layers run at 0 ms (document_start), then re-scan at 800 ms, 2.5 s, and 5 s to catch async-loaded tags. The MutationObserver runs continuously.

why Real-world tag setups load tags from multiple sources at different times. A single scan misses anything CMP-gated; multiple scans catch everything without polling.

Deduplication

The same fire can be captured by multiple layers (network + JS hook). Pixel Auditor deduplicates with a 400 ms window keyed by tagId + eventName + extractedId, plus null-ID suppression to handle body-parse failures cleanly. → Duplicate detection

Dynamic re-routing (gtag.js)

gtag.js routes GA4, Google Ads, and Merchant Center hits through the same /g/collect endpoint. Pixel Auditor reads the tid parameter prefix to attribute correctly:

G-*Google Analytics 4
AW-*Google Ads
MC-*Google Merchant Center
UA-*Universal Analytics (retired)