Block direct Google Analytics until consent
Last updated: October 4, 2026
This example is for one direct GA4 measurement ID with CYBEXO Web CMP 1.5.30 or later, using a direct Web TCF or Google-ready property. Confirm that version is available on your installation before using the example. It waits for a completed or validated saved Analytics choice, loads Google only after a grant, and disables Analytics immediately on withdrawal. It then reloads after the CMP completes saving, so the next page starts with Google blocked. If the public consent API is absent or fails, it stays blocked. Saved-choice restoration in other regional implementations is outside this example’s qualified scope.
This is publisher tag-blocking code; the dashboard Consent Mode switch does not install it for you. It does not cover GTM, Google Ads, Floodlight, Google tag gateway, connected Google destinations, or another plugin’s Google installation. Remove your previous GA4 script/configuration and route your manual GA4 events through this helper. Verify that your Google tag has no additional destinations and that no other integration loads it. Avoid Google preconnect/prefetch hints before consent.
Google’s Basic Consent Mode definition requires Google tags to remain blocked when consent has not been granted. The example keeps the denied/default and later update commands in the local queue until a grant permits the tag to load. A regional automatic grant without a completed visitor choice does not open this gate.
1. Add the helper before the CMP
Section titled “1. Add the helper before the CMP”Download cybexo-basic-analytics.js, review it, and serve it from /assets/cybexo-basic-analytics.js on your site. Keep the helper and its initialization synchronous and before the asynchronous CMP loader. Replace the two placeholder IDs below with your property’s App ID and your GA4 measurement ID.
For Basic Consent Mode, publish Consent Mode on and install this complete block first in <head> on every page:
<script src="/assets/cybexo-basic-analytics.js"></script><script> window.siteAnalytics = window.cybexoCreateBasicAnalytics({ measurementId: 'G-YOURMEASUREMENTID' }); window.dataLayer = window.dataLayer || []; window.gtag = window.gtag || function () { window.dataLayer.push(arguments); }; window.gtag('set', 'developer_id.dZTNmYW', true); if (!window.__nxgCMDefaultSet) { window.gtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', wait_for_update: 500 }); window.__nxgCMDefaultSet = true; }</script><script src="https://cmp.cybexo.com/tcf-bootstrap.js"></script><script async id="cybexo-cmp" data-settings-id="CYB-YOUR_APP_ID" data-consent-mode="on" data-api-url="https://api.cybexo.io" data-assets-url="https://cmp.cybexo.com" src="https://cmp.cybexo.com/loader.js"></script>Do not add a separate Google script after this block. The helper supplies the script and the GA4 config command when permitted. It disables automatic initial page-view dispatch and advertising features for this one destination. Review your GA4 Enhanced Measurement configuration separately; it can create additional events after a permitted load.
For a nonce-based Content Security Policy, add your response’s nonce to each required script element and pass the same value as nonce in cybexoCreateBasicAnalytics. The helper applies it to the Google script it creates. Configure your existing CSP for the specific CMP and Google resources; do not broadly allow arbitrary scripts.
2. Full Consent Mode off alternative
Section titled “2. Full Consent Mode off alternative”To stop CYBEXO Google default/update commands entirely, publish Consent Mode off, remove the whole on installation, and use this block instead. Also remove separately installed Google commands and gtag_enable_tcf_support = true. The helper still uses the independent Analytics decision and still blocks the Google script until affirmative consent.
<script src="/assets/cybexo-basic-analytics.js"></script><script> window.siteAnalytics = window.cybexoCreateBasicAnalytics({ measurementId: 'G-YOURMEASUREMENTID' });</script><script src="https://cmp.cybexo.com/tcf-bootstrap.js"></script><script async id="cybexo-cmp" data-settings-id="CYB-YOUR_APP_ID" data-consent-mode="off" data-api-url="https://api.cybexo.io" data-assets-url="https://cmp.cybexo.com" src="https://cmp.cybexo.com/loader.js"></script>Full off is a tag-blocking alternative, not an implementation of Google’s Consent Mode APIs. On a permitted load the helper queues only GA4 initialization/configuration; it does not fabricate consent commands. TCF continues to serve applicable advertising choices, with the CMP’s advertiser-consent-mode inference disabled. Do not turn inference back on elsewhere.
3. Send permitted manual events
Section titled “3. Send permitted manual events”Use this wrapper instead of calling gtag('event', ...) directly:
const requested = window.siteAnalytics.event('consent_probe', { debug_mode: true});// false: blocked or the Google script is not loaded yet; nothing was buffered.// true: the event was queued for the configured destination, not proof of delivery.The helper always rechecks the public CMP state before sending. In TCF, effective Analytics permission also requires the applicable Google vendor755 consent; an Analytics checkbox alone cannot override a vendor refusal. An event attempted before consent or while loading is discarded; it is never replayed after acceptance. When you need a page-view event, request page_view through the same wrapper once the script is loaded. siteAnalytics.getState() reports blocked, loading, loaded, error, or reloading for your integration UI. Do not treat loaded alone as permission; the event wrapper performs the current consent check.
4. Withdrawal and failure behavior
Section titled “4. Withdrawal and failure behavior”The helper sets Google’s per-measurement-ID disable flag synchronously when Analytics is refused. It blocks later manual events, waits until the CMP reports that the choice save has finished, then reloads once. A denied reload never requests the Google script. A back/forward-cache restoration also reloads to revalidate the current choice.
Reloading can interrupt unsaved work elsewhere on your page. Account for that interaction in your site’s design before adoption. Do not remove the reload and assume deleting a script element unloads executed JavaScript. An in-flight request cannot be recalled, and an already loaded Google tag may send a consent-transition ping; verify actual network behavior. This example promises no initial Google load before a grant and no helper-issued manual events after withdrawal, not a universal zero-request claim for the withdrawal transition.
An unavailable CMP, invalid consent state or Google-script error leaves the gate closed. The helper does not retry a failed Google script in the same document. A Google loading failure does not justify bypassing the consent gate.
5. Qualify your installation
Section titled “5. Qualify your installation”Capture Network with Preserve log, and separately inspect Google requests by page-load interval:
| Case | Expected result |
|---|---|
| Fresh session, no choice; initial Reject All; denied reload | No Google tag or collection request. Helper events return false. |
| Accept All or explicit Analytics grant | One Google script load. In Basic mode, queued denied defaults and the grant update precede js/config. A manual event can deliver once loaded. |
| Change only an unrelated purpose | Analytics choice stays intact; no second Google script. |
| Analytics off / Reject All | Disable flag becomes true immediately. No further helper event is queued. Reload follows completed saving; the denied document requests no Google script. |
| Loader, configuration or required vendor list unavailable | No new grant or Google load. Remove the test block and check normal recovery. |
| Restored valid Analytics grant / invalid old saved choice | Valid grant may load once; invalid context stays blocked until a fresh choice. |
| Full-off installation | No CYBEXO Google consent commands; advertiser inference is off. The independent Analytics gate still works. |
Verify collection responses as well as queued commands. Retain the before-choice, after-grant, withdrawal-transition and denied-reload intervals separately so an older accepted request is not mistaken for a new denied request. See the public state contract and Consent Mode validation.