Google Tag Gateway (GTG) lets site operators load Google tags through their own first-party infrastructure instead of googletagmanager.com. This article explains what GTG is, how Kukie's Consent Mode v2 integration behaves when a Google tag is loaded via GTG, how to verify whether a tag is enrolled in GTG, and what remediation paths are available when late consent is detected on a GTG-loaded tag.
What is Google Tag Gateway?
Google Tag Gateway (GTG) lets you deploy Google tags through your own first-party infrastructure. A CDN, load balancer, or web server. Instead of loading the tag from googletagmanager.com, the tag loads from a subdomain of your own site, for example cdn.example.com/gtag/js?id=G-XXXX. Google offers GTG integrations with Cloudflare, Google Cloud Load Balancer, and other partners.
Google offers two main ways to deploy GTG:
One-click CDN integration
A partner CDN (Cloudflare being the primary one at launch) injects the GTG loader automatically when you flip a toggle in the CDN dashboard. The tag loads from a path on your own domain that the CDN controls. With one-click integrations, the injection position in your HTML is typically fixed by the CDN and cannot be easily overridden by the site operator. This means your Kukie script tag and the GTG-loaded Google tag may end up in an order you did not intend, and there is often no UI in the CDN dashboard to change it. This is why load-order issues are common specifically with CDN-injected GTG.
Manual GTG setup
You deploy the GTG loader yourself on your own web server, reverse proxy, or load balancer, following Google's manual setup guide. With manual setup, you control exactly where the GTG loader sits in your HTML, and you can guarantee that Kukie's script tag is positioned above it.
GTG and Consent Mode v2
GTG does not replace Consent Mode v2 or a Consent Management Platform. Consent signalling still happens through gtag('consent', 'default', ...) and gtag('consent', 'update', ...) commands. GTG changes the hostname from which a Google tag loads; it does not change when the tag executes relative to your CMP.
How to verify if a tag is enrolled in GTG
To confirm whether a Google tag on your site is loaded via Google Tag Gateway, run these four checks. Any one of them is sufficient; running all four gives highest confidence.
Check 1: Inspect the script's hostname in DevTools Network tab
- Open DevTools (F12 on Windows/Linux, Cmd+Option+I on macOS).
- Go to the Network tab.
- Reload the page.
- Filter requests for
gtag/jsorgtm.js. - Look at the request hostname.
Result interpretation:
- Hostname is
www.googletagmanager.com: NOT loaded via GTG (standard delivery). - Hostname is a subdomain of your own site (for example
cdn.example.com,analytics.example.com): likely loaded via GTG.
Check 2: Check the URL path and query string pattern
GTG-loaded tags preserve Google's standard URL path and query pattern. They only change the hostname. Look for:
/gtag/js?id=G-XXXXXXXXXX: Google Analytics or gtag/gtag/js?id=AW-XXXXXXXXX: Google Ads/gtm.js?id=GTM-XXXXXXX: Google Tag Manager
If the path and query match one of these patterns but the hostname is your own first-party subdomain, the tag is GTG-loaded.
Check 3: Check your CDN or infrastructure dashboard
If you use Cloudflare, log into the Cloudflare dashboard and navigate to the Google Tag Gateway section. If the feature is enabled there, your tags are loaded via GTG. If you use Google Cloud Load Balancer or another infrastructure provider with a GTG integration, check that provider's dashboard for an equivalent setting.
Check 4: Use Kukie's debug mode
Append ?kukie_debug=1 to any page where Kukie is installed. The console debug report lists each detected Google tag with its hostname. Tags loaded from first-party subdomains are flagged with a [GTG] badge in the tag listing.
Expected results:
| Hostname pattern | Kukie debug badge | GTG verdict |
|---|---|---|
www.googletagmanager.com/gtag/js?id=G-... |
none | not GTG |
cdn.your-site.com/gtag/js?id=G-... |
[GTG] |
GTG-loaded |
analytics.your-site.com/gtm.js?id=GTM-... |
[GTG] |
GTG-loaded |
How Kukie works with GTG-loaded tags
When a Google tag is loaded via GTG, Kukie's integration works the same way it does for standard googletagmanager.com-loaded tags:
- Kukie fires
gtag('consent', 'default', {...})with all parameters set todeniedandwait_for_update: 500before any Google tag initialises. - When the visitor interacts with the banner (or when a permissive consent model auto-grants), Kukie fires
gtag('consent', 'update', {...})with the appropriate state. - Google tags loaded via GTG read these consent signals the same way they do when loaded from
googletagmanager.com.
In short: GTG changes the origin from which the tag is served, not the mechanism by which consent signals reach it.
Script ordering with GTG
Because Kukie must set consent defaults BEFORE any Google tag executes, the script tag order in your <head> is critical:
<head>
<!-- Kukie.io CMP FIRST - always above any Google tag -->
<script src="https://cdn.kukie.io/s/{your-site-key}/c.js" async></script>
<!-- Then your GTG-loaded Google tag -->
<script async src="https://cdn.example.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
</head>
Replace {your-site-key} with the site key from the Kukie dashboard, cdn.example.com with the first-party subdomain your GTG provider configured, and G-XXXXXXXXXX with your Google tag ID.
Auto-block behaviour and GTG
Kukie's script auto-blocker matches Google tag loads by hostname pattern. When GTG is in use, the Google tag's hostname is a first-party subdomain of your own site rather than googletagmanager.com. This means the auto-blocker may not recognise the tag and will not prevent it from firing before consent. The Auto-block Scripts toggle lives in the Design tab of the Banner Editor.
Recommendation: When using GTG, position the Kukie script at the top of your
<head>so thatgtag('consent', 'default', 'denied')fires before the GTG-loaded tag initialises. This ensures Consent Mode v2 signals reach the tag in the correct order regardless of auto-blocking.
When late consent is detected on a GTG-loaded tag
If Kukie's debug mode (?kukie_debug=1) reports a ✗ FAIL verdict on a page where you have verified GTG enrollment using the checks in the previous section, the Consent Mode v2 default signal is being set after the Google tag has already executed. When Data Transmission Controls or Global Consent Defaults are enabled on the Google tag, measurement data will be dropped or modelled incorrectly.
You have three remediation paths. Each is technically valid; choose the one that best fits your infrastructure and operational constraints.
Option 1: Adopt Advanced Consent Mode (Google's U+C)
This is the recommended path for sites that want to keep their existing one-click CDN GTG integration without migrating tags.
Google refers to Advanced Consent Mode as U+C (Update plus Consent). In Advanced Consent Mode, Google tags are NOT blocked before consent. The tags load and execute, then read gtag('consent', 'default', ...) and gtag('consent', 'update', ...) signals at runtime to decide what measurement to send. Because the tags are not blocked, there is no pre-consent race between Kukie's auto-blocker and the GTG-loaded tag. Load order becomes less critical.
Steps in Kukie:
- Open the Kukie dashboard and navigate to your site's Banner Editor.
- Go to the Integrations tab and turn ON the "Google Consent Mode v2" toggle if it is not already enabled.
- Go to the Design tab and turn OFF the "Auto-block Scripts" toggle. This removes pre-consent tag blocking and leaves Consent Mode v2 signals as the sole mechanism controlling Google tag measurement behaviour.
Steps in Google:
- Enable Data Transmission Controls per tag in your Google Ads tag settings. See Data transmission controls (Google Ads).
- Configure Global Consent Defaults in your Google tag settings according to your measurement needs. See About Consent Mode (Tag Manager).
Why this is recommended for GTG-enabled tags: Advanced Consent Mode (U+C) is compatible with both one-click CDN GTG and manual GTG. It does not depend on Kukie's pre-consent auto-blocker, which cannot always match GTG-loaded tags on first-party subdomains. This makes U+C the most reliable mechanism for GTG-enabled measurement.
Option 2: Migrate tags into a GTM container and deploy GTM via GTG
This is the recommended path for sites that want centralised tag management.
Instead of loading individual Google tags (gtag.js, Google Ads, Floodlight) directly into your HTML, consolidate them into a single Google Tag Manager container. You then deploy the GTM container itself via GTG.
Why this helps: A GTM container has a single entry point (gtm.js). You control when GTM loads relative to Kukie's script in your HTML, and all downstream Google tags that fire inside the GTM container inherit the correct Consent Mode v2 state because Kukie has already called gtag('consent', 'default', ...) before GTM executes.
Steps:
- Create a Google Tag Manager container if you do not have one.
- Install the Kukie GTM Community Template inside your GTM container. See the Install Kukie via Google Tag Manager guide.
- Migrate any standalone gtag.js snippets, Google Ads conversion scripts, and Floodlight pixels into GTM tags within the container.
- Ensure the Kukie Consent Initialisation tag fires on Consent Initialisation (All Pages) with priority 100 so it runs before any other tag.
- In your CDN dashboard, switch the GTG integration to target GTM (
gtm.js) rather than individual gtag.js snippets. See Set up GTG in GTM with Cloudflare.
Option 3: Set up GTG manually where script import order is controlled
This is the recommended path for sites that want GTG but need full control over load order.
Instead of the one-click CDN injection, deploy the GTG loader on your own infrastructure (web server, reverse proxy, or load balancer) and place the Kukie script above it in your HTML.
Steps:
- Disable the one-click GTG toggle in your CDN dashboard if it is currently enabled.
- Follow Google's Google Tag Gateway setup guide to configure GTG on your own server, load balancer, or web proxy.
- Place the Kukie script tag at the top of your
<head>, before the manually deployed GTG loader. - Verify with Kukie's debug mode (
?kukie_debug=1) that the Timing Check verdict is✓ PASS.
Which remediation is recommended?
For most GTG-enabled sites, Advanced Consent Mode (Google's U+C) is the recommended mechanism. It is compatible with both manual GTG and one-click CDN GTG deployments, it does not depend on Kukie's pre-consent auto-blocker (which cannot always match tags loaded from first-party subdomains), and it aligns with Google's own guidance for sites using Data Transmission Controls or Global Consent Defaults. If you prefer centralised tag management, Option 2 (GTM migration) is a valid alternative. If you need full control over script load order, Option 3 (manual GTG) is the right path.
Diagnosing late-consent issues on GTG-loaded tags
Kukie's debug mode (?kukie_debug=1) detects late consent by comparing the timing of gtag('consent', 'default', ...) against the first activity from any Google tag in the dataLayer. This detection works for GTG-loaded tags because it measures timing via the dataLayer rather than matching on the tag's hostname.
However, the "detected Google tags" section of the debug report may not list your GTG-loaded tag when Kukie's heuristic path+query matcher does not recognise the URL pattern. If your debug report shows ✗ FAIL - Google tags fired BEFORE Kukie set consent defaults but the "detected tags" section appears empty, your tag is likely GTG-loaded. The fix is the same: move the Kukie script tag above the GTG-loaded tag in your <head>.
For the full debug-mode reference, see Consent Mode Debug Mode.
If you verify that the late-firing tag is GTG-enrolled, choose one of the three remediation paths described above.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
✗ FAIL timing with empty detected-tags list |
GTG-loaded tag on a first-party hostname that Kukie's detector did not match | Move the Kukie script above the GTG tag in your <head> |
✓ PASS timing but measurement is still dropped |
Consent default is firing but the update command is not reaching the GTG tag |
Verify Google Consent Mode v2 is enabled in the Banner Editor; confirm the consent signal maps to granted after the user accepts |
? Unable to determine timing |
No Google tag has pushed to dataLayer yet |
Reload the page and re-run debug mode; GTG tags may load asynchronously and need a few extra seconds |
| Network tab shows the GTG tag loading from an unexpected hostname | Your GTG deployment uses a non-obvious first-party subdomain (for example a CDN workers hostname) | This is expected. Kukie's timing check is hostname-agnostic, so the PASS/FAIL verdict is still accurate even when the detected-tags list is empty |
✗ FAIL timing on a GTG-enabled site, cannot change load order (CDN-injected) |
One-click CDN GTG injects the loader at a fixed position the site operator cannot override | Adopt Advanced Consent Mode (Option 1 in Remediation Paths), migrate to GTM via GTG (Option 2), or switch to manual GTG (Option 3) |
Dedicated Support
For GTG-specific issues, or if none of the three remediation paths above resolve your late-consent verdict, email google-support@kukie.io. Include:
- The affected site URL
- Output from
?kukie_debug=1showing the FAIL verdict - Which of the four GTG verification checks (Section How to verify if a tag is enrolled in GTG) confirmed enrollment
- Which remediation path you have attempted or are considering
Our target response time for Google Consent Mode and GTG issues is within 1 business day.
Related guides
- Google Consent Mode v2 overview
- Consent Mode Debug Mode
- Basic vs Advanced Consent Mode
- Google's Banner Requirements for Consent Mode
- Google Consent Mode: Basic vs Advanced - Google calls Advanced mode "U+C"