Webclat / Signals
Signals  /  QA  /  GTM-15

How does Google Tag Gateway (first-party tag proxying) scope apply across subdomains, and how do I exclude specific pages?

Answer in brief

Google Tag Gateway (first-party tag proxying, whether Cloudflare's built-in integration or a self-hosted reverse-proxy pattern) is scoped to whatever hostname route or Worker binding you configure - it is not automatically inherited by every subdomain on the same root domain, and a subdomain on a separate Cloudflare zone needs its own explicit route. Page-level exclusion works the same way: add a more specific route or an in-proxy path check that bypasses the rewrite, rather than expecting GTM itself to know which pages should skip the gateway.

Why this happens

Cloudflare's Google Tag Gateway is implemented as a Worker bound to a route pattern at the zone level. If the root domain's route is configured for example.com/* but a subdomain like shop.example.com sits on a different zone, or the pattern simply does not list it, requests from that subdomain never get proxied - they fall back to loading gtm.js directly from Google's own servers, so tag delivery there is not first-party even though the rest of the site is.

The opposite failure looks like a route that is too broad: if the pattern matches every path on every bound hostname, pages you actually want to exclude - a staging path, a page under a stricter Content-Security-Policy, a page already served through a different proxy - get swept into the gateway with no built-in opt-out. GTM's own trigger and tag logic has no visibility into this layer at all; the routing decision happens before a request ever reaches GTM's JavaScript, in the CDN or reverse-proxy configuration.

Fix it

  1. Audit which hostnames actually need first-party tag delivery - work from the property's live subdomain list, not an assumption that a root-domain rule covers everything under it.
  2. In Cloudflare, check the Worker route bound to the Google Tag Gateway integration and confirm it explicitly lists each subdomain that needs it (www.example.com/*, shop.example.com/*) - a route does not cross zone boundaries even under the same Cloudflare account.
  3. For a subdomain on a separate zone, add a second Worker route bound to that zone specifically; do not assume the primary domain's route extends to it.
  4. For page-level exclusion, add a more specific route that matches the excluded path and either passes the request straight through to origin unmodified, or add a path check inside the Worker script itself that skips the rewrite for that path.
  5. If self-hosting the proxy logic instead of using Cloudflare's built-in integration, apply the same exclusion rule in whatever layer is doing the URL rewrite (an nginx location block, a Fastly VCL condition, a custom Worker) - exclusion belongs in the proxy layer, not inside GTM.
  6. Redeploy and purge cache for every affected path - a stale cached response can make both a working exclusion and a broken one look identical during testing.

How to verify it worked

  • Open the Network tab on a page that should be inside the proxy scope and confirm the tag-library request loads from your own domain (not www.googletagmanager.com) and returns 200 with a JavaScript content type.
  • Load a page you deliberately excluded and confirm the opposite: the request goes straight to Google's own domain rather than being rewritten - if it is still proxied, the exclusion rule is not matching that path.
  • Check for any custom header your Worker adds on a successfully proxied request, to rule out a stale edge-cached response masquerading as a fresh pass-through.
  • Run GTM's own Preview mode on both an included and an excluded page and confirm tags fire identically - the routing change should be invisible to GTM's trigger and tag logic when implemented correctly.

Want This Checked On Your Own Setup?

Send us the platform and the symptom and we will tell you whether this is the fix, or whether something else in your pipeline is masquerading as it.

Talk To The Practice