Integrate OptinStack with Google Tag Manager
By OptinStack Team - Jun 28, 2026 - 7 min read
Use this guide when your site manages tags through Google Tag Manager and you want OptinStack to control when measurement, advertising, personalization, and other trackers can run. The setup has two jobs: OptinStack collects and stores the visitor's choices, and GTM uses those choices to set Google Consent Mode v2 and control tags in your container.
Consent Mode is not a banner and does not collect consent by itself. OptinStack provides the consent banner, preferences dialog, consent record, tracker blocking, and consent-change events. The GTM template translates that state into GTM and Google consent signals.
For the technical signal mapping and runtime behavior, see the Google Consent Mode v2 docs reference.
How the integration works
The OptinStack runtime runs on your site and maintains four consent categories: necessary, analytics, marketing, and preferences. It stores the visitor's consent record in a first-party technical record named optinstack, exposes the current state through window.OptinStack, blocks or releases direct scripts and iframes by category, and emits dataLayer events that you can use as GTM triggers.
The OptinStack GTM template is the GTM-side bridge. It sets default consent during GTM's Consent Initialization phase, reads any existing OptinStack consent record, subscribes to live OptinStack consent changes, and updates GTM with the matching Consent Mode v2 values. It can also inject the OptinStack runtime through GTM, but direct installation in the page head is recommended for most sites.
Prerequisites
- A Google Tag Manager web container installed on your site.
- An OptinStack project with your domain configured and a Site ID from the dashboard install screen.
- Access to the official downloadable OptinStack GTM template. It is not currently published in the Community Template Gallery.
- A decision on your default consent state by region. Many consent-required regions use denied defaults for optional categories until the visitor makes a choice.
Choose an installation path
| Path | Use when | Notes |
|---|---|---|
| Install the OptinStack runtime directly in the site head and use the GTM template for Consent Mode | You can edit the site head or your platform lets you place scripts early | Recommended. The runtime can block direct trackers as early as possible, while the GTM template initializes consent before other GTM tags. |
| Load the OptinStack runtime through the GTM template | You cannot edit the site head and must manage everything through GTM | Supported, but test carefully. GTM must load before the runtime can run, so anything that fires before the container/template runs cannot be blocked by the runtime. |
| Runtime only, without the GTM template | You do not need a full GTM consent setup | The runtime has a built-in Consent Mode bridge, but the GTM template is preferred for container-wide defaults because it runs during Consent Initialization. |
When you install the runtime directly and also use the GTM template, both layers can update Google consent state: the runtime emits its built-in gtag consent bridge, and the template uses GTM's native consent APIs for defaults, regional settings, ads data redaction, URL passthrough, and live updates. The values should match, but debugging tools may show redundant consent updates. Keep only one CMP or custom consent implementation active so OptinStack remains the single source of consent truth.
Step 1: Install the OptinStack runtime
For the strongest enforcement, paste the runtime snippet from your OptinStack dashboard as early as possible in the site head, before the GTM container snippet and before any direct third-party scripts.
<script src="https://api.optinstack.com/v1/js/runtime/stable/optinstack.js" data-optinstack-sdk="consent" data-optinstack-site="YOUR_SITE_ID"></script>The data-optinstack-site value tells the runtime which project configuration to load. The runtime fetches your site configuration, resolves the visitor's applicable policy and region, honors Global Privacy Control when configured, blocks direct scripts, iframes, storage writes, and known tracker records by category, then loads the banner and preferences UI.
Do not rely on GTM alone to block trackers that are hard-coded above the GTM container or loaded by your platform before GTM starts. Those trackers need the OptinStack runtime placed earlier in the page or moved into GTM with consent checks.
Step 2: Add the OptinStack GTM template
- Open your GTM container and go to Templates.
- In Tag Templates, choose New, open the template editor menu, and import the official downloadable OptinStack template. It is not currently published in the Community Template Gallery.
- Review the permissions. The template writes GTM consent state, reads the
optinstackconsent record, setsads_data_redactionandurl_passthrough, reads the OptinStack global API, and optionally injects the OptinStack runtime fromapi.optinstack.com. - Save the template to your workspace.
Step 3: Create the OptinStack consent tag
- Go to Tags and create a new tag.
- Choose the OptinStack template as the tag type and name it OptinStack Consent Mode.
- Set the trigger to Consent Initialization - All Pages. This trigger is required because consent defaults must be available before normal pageview, initialization, and custom event triggers run.
- Save the tag, then use Preview mode before publishing.
Do not fire the OptinStack consent tag on All Pages or a later custom trigger. Google recommends the Consent Initialization trigger for tags that set or update consent state, and the OptinStack template is designed for that timing.
Step 4: Configure every template field
| Field | Recommended value | What it does |
|---|---|---|
| Enable Google Consent Mode v2 | On | Lets the template set default consent and update GTM when OptinStack consent changes. Turn it off only if another implementation owns Google consent state. |
| Wait for update | 500 ms | Adds wait_for_update to default consent calls. This gives the runtime a short window to read an existing choice or receive a new choice before consent-aware Google tags proceed with the default state. |
| Redact ads data | Dynamic | Controls ads_data_redaction. Dynamic enables redaction when marketing consent is denied and disables it when marketing consent is granted. |
| Enable URL passthrough | Off unless needed | Sets url_passthrough for consent-aware Google tags. Consider it for Google Ads/Floodlight measurement when ad_storage may be denied, then test redirects and analytics URL cleanup. |
| Default Consent State: Region | Blank global row plus optional regional rows | Blank applies globally. Regional rows accept comma-separated region codes such as DE, FR, US, or supported subregions like US-CA where your Google setup uses them. |
| Default Consent State: Preferences | Usually denied in consent-required regions | Maps to functionality_storage and personalization_storage. |
| Default Consent State: Analytics | Usually denied in consent-required regions | Maps to analytics_storage. |
| Default Consent State: Marketing | Usually denied in consent-required regions | Maps to ad_storage, ad_user_data, and ad_personalization. |
| Load the OptinStack runtime through GTM | Off by default | When enabled, the template injects the OptinStack runtime from api.optinstack.com. Use only if you cannot place the runtime directly in the site head. |
| Site ID | Your OptinStack Site ID | Required only when runtime injection is enabled. The injected script receives data-optinstack-site with this value. |
Configure default consent by region
Add at least one blank Region row as your global default. Then add regional rows only where the default needs to differ. Google applies the most specific matching region default, and the blank row applies to visitors not covered by a regional row.
If you do not configure a blank global row, the OptinStack template falls back to denied for analytics, marketing, preferences, and granted for security_storage. This is safe, but explicit defaults are easier to audit and troubleshoot.
Keep the template defaults aligned with the policy you configured in OptinStack. The defaults are used before a visitor has made a choice on the current page. After a stored or new OptinStack choice is available, the template updates GTM with that visitor-specific state.
Consent Mode v2 signal mapping
| Google consent signal | OptinStack category | Granted when |
|---|---|---|
ad_storage | marketing | The visitor grants marketing consent. |
ad_user_data | marketing | The visitor grants marketing consent. This is part of Consent Mode v2 for advertising data use. |
ad_personalization | marketing | The visitor grants marketing consent. This controls personalized advertising use cases such as remarketing. |
analytics_storage | analytics | The visitor grants analytics consent. |
functionality_storage | preferences | The visitor grants preferences consent. |
personalization_storage | preferences | The visitor grants preferences consent. |
security_storage | necessary | Always granted. Necessary consent is an OptinStack invariant. |
How the template keeps GTM in sync
- On Consent Initialization, the template calls GTM's
setDefaultConsentStateAPI for each configured region row. - If an existing OptinStack consent record is present, the template reads it immediately and calls updateConsentState with the stored choices.
- When the runtime is available, the template subscribes to
window.OptinStack.subscribe,window.OptinStack.on('choices'), orwindow.OptinStack.events.on('consent-updated'), depending on which surface is available. It falls back to polling the current choices if needed. - Each time choices change, the template maps OptinStack categories to Google Consent Mode signals and calls
updateConsentStateagain. - The template also sets
ads_data_redactionandurl_passthroughthrough GTM'sgtagSetAPI when those options are enabled.
OptinStack dataLayer events
The runtime pushes GTM-friendly events to window.dataLayer. Each event is pushed as an object with only an event property, for example { event: 'optinstack_analytics_accepted' } . Use these events as GTM Custom Event triggers.
| Event | When it fires | Typical use |
|---|---|---|
optinstack_gpc_signal_detected | On runtime initialization when Global Privacy Control is active | Debug or segment GPC-aware behavior. |
optinstack_consent_updated | Every time consent state changes after the runtime updates choices | Re-evaluate tags or run consent-change logic. |
optinstack_necessary_accepted | The first time necessary consent is granted on a page load | Rarely needed because necessary is always granted. |
optinstack_analytics_accepted | The first time analytics is granted on a page load | Fire analytics tags that should wait until analytics consent is granted. |
optinstack_marketing_accepted | The first time marketing is granted on a page load | Fire ads, pixels, remarketing, or conversion tags that should wait for marketing consent. |
optinstack_preferences_accepted | The first time preferences is granted on a page load | Fire personalization and functionality tags that should wait for preferences consent. |
optinstack_unclassified_accepted | The first time every enabled category is granted on a page load | Fire a tag only after all enabled optional categories are granted. |
The accepted events fire once per page load. If a visitor turns a category off and then on again during the same page load, the category-specific accepted event does not fire a second time. Use optinstack_consent_updated when you need to respond to every change.
Configure tags, triggers, variables, and consent settings
Enable Consent Overview
In GTM, go to Admin, Container Settings, and enable Consent Overview. This gives you one place to review which tags have consent settings configured and which tags still need attention.
Google tags with built-in consent checks
Google tag, GA4, Google Ads, Floodlight, and Conversion Linker tags understand Consent Mode signals. If you want advanced Consent Mode, these tags can load with denied defaults and adapt behavior until consent is granted. If your policy requires basic Consent Mode, add Additional Consent Checks so the tag does not fire until the required consent types are granted.
Third-party tags without built-in checks
For tags that do not understand Google Consent Mode, open Tag Configuration, Advanced Settings, Consent Settings, and choose Require additional consent for tag to fire. Add the consent types that match the tag's purpose. Then use an OptinStack Custom Event trigger so the tag can fire on the first page after consent is granted.
| Tag type | Trigger | Additional consent checks |
|---|---|---|
| GA4 pageview in advanced Consent Mode | Initialization or All Pages after the OptinStack consent tag | Usually no additional checks because GA4 has built-in checks. Add analytics_storage if your policy requires basic mode. |
| Non-Google analytics tag | Custom Event: optinstack_analytics_accepted | analytics_storage |
| Google Ads conversion in advanced Consent Mode | Conversion trigger after the OptinStack consent tag | Built-in checks use ad_storage, ad_user_data, and ad_personalization. Add additional checks for basic mode. |
| Meta, LinkedIn, or other ad pixel | Custom Event: optinstack_marketing_accepted or your conversion event plus consent checks | ad_storage, ad_user_data, ad_personalization |
| Personalization or A/B testing tool | Custom Event: optinstack_preferences_accepted | functionality_storage and/or personalization_storage |
| Tag that must respond to every consent edit | Custom Event: optinstack_consent_updated | The consent types required by that tag |
Additional Consent Checks are evaluated when a tag's trigger fires. A tag that already missed its All Pages trigger usually will not fire later just because consent changed. Pair consent-gated non-Google tags with OptinStack custom event triggers such as optinstack_analytics_accepted or optinstack_marketing_accepted.
Most GTM setups do not need custom variables because Consent Mode and Additional Consent Checks handle the gating. If you need a variable for advanced logic, read the public runtime state from window.OptinStack.choices.
function() {
return !!(window.OptinStack && window.OptinStack.choices && window.OptinStack.choices.analytics);
}Google Consent Mode v2 and advertising products
Consent Mode v2 adds ad_user_data and ad_personalization alongside ad_storage and analytics_storage. OptinStack maps all three advertising signals to the marketing category. When marketing is denied, Google advertising tags should treat advertising storage, advertising user data, and personalized advertising as denied.
This matters for Google Ads conversion tracking, enhanced conversions, remarketing, Floodlight, and other advertiser-related products. Consent Mode changes how supported Google tags behave; it does not replace your responsibility to obtain valid consent or configure tag firing according to your policy.
Use Dynamic ads data redaction when you want ad click identifiers redacted whenever marketing consent is denied. Use URL passthrough only after testing same-domain navigation, redirects, and analytics reporting, because Google may append parameters such as gclid, dclid, gclsrc, _gl, and wbraid to links.
Global Privacy Control
When Global Privacy Control is active and your OptinStack policy honors it, the runtime defaults optional categories according to your GPC behavior. It also pushes optinstack_gpc_signal_detected to dataLayer. Because the GTM template default runs before the runtime can evaluate the browser signal, configure conservative default rows for regions where GPC or consent requirements apply.
Let visitors reopen preferences
Add a footer or privacy-page link that reopens the OptinStack preferences dialog. This lets visitors change or withdraw consent later, and the GTM template will update consent state when their choices change.
<button type="button" onclick="window.dispatchEvent(new CustomEvent('optinstack:open-preferences', { bubbles: true }))">
Consent preferences
</button>Control trackers outside GTM
GTM consent settings only control tags inside the GTM container. Scripts, iframes, maps, widgets, or platform integrations inserted directly into the page still need OptinStack runtime enforcement. Use dashboard tracker rules from your scan results, or mark direct elements with data-optinstack-categories when you know the category.
<script data-optinstack-categories="analytics" src="https://example.com/analytics.js"></script>Test the implementation
- Open GTM Preview mode and load your site in a fresh browser profile.
- Confirm that the OptinStack consent tag fires on Consent Initialization before other tags.
- Open Google Tag Assistant and check the earliest Consent event. Verify that ad_storage, ad_user_data, ad_personalization, analytics_storage, functionality_storage, personalization_storage, and security_storage have the expected default values.
- Interact with the OptinStack banner. In Tag Assistant, verify that a later Consent event updates the same signals to match the visitor's choices.
- In GTM Preview, inspect tags that should be blocked before consent and confirm their consent checks and triggers behave as expected.
- Run an OptinStack scan after publishing to confirm direct trackers and GTM-loaded trackers are categorized correctly.
Troubleshooting
| Issue | Likely cause | Fix |
|---|---|---|
| Tag Assistant shows no consent defaults | The OptinStack template tag did not fire on Consent Initialization | Move the OptinStack consent tag to Consent Initialization - All Pages and publish the container. |
| Default consent is set too late | The consent tag fires after other tags, or another tag sends data before defaults are available | Use the Consent Initialization trigger and place the runtime before GTM when possible. Do not use a Custom HTML gtag consent command as your GTM consent bridge. |
| Consent updates do not appear after banner interaction | The runtime is missing, the Site ID is wrong, or the template cannot reach window.OptinStack | Verify the runtime snippet or runtime injection setting, check the Site ID, and confirm window.OptinStack exists in the browser console. |
| A third-party tag does not fire after consent is granted | The tag only has an All Pages trigger, so it missed its trigger before consent was granted | Add an OptinStack Custom Event trigger such as optinstack_marketing_accepted or optinstack_analytics_accepted. |
| A tag fires before consent | The tag lacks Additional Consent Checks, has a trigger that runs before consent, or is hard-coded outside GTM | Set the correct required consent types, use OptinStack event triggers, and move direct scripts under runtime control. |
| Regional defaults do not match expectations | The region row is missing, too broad, or there is no global fallback | Add a blank global row, then add regional rows for exceptions. Test with Tag Assistant using simulated locations. |
| Duplicate or conflicting consent states | Multiple CMPs or custom tags are setting Consent Mode defaults and updates | Use one consent authority. Remove old Custom HTML consent commands or other CMP templates that conflict with OptinStack. |
Official references
- Google Tag Manager consent mode support
- Google's guide to creating consent mode templates with GTM consent APIs
- Set up Consent Mode on websites
- Troubleshoot Consent Mode with Tag Assistant
- Google Consent Mode overview
- Google Ads: About Consent Mode
Related articles
Set up Google Consent Mode v2
Map OptinStack's four consent categories onto Google Consent Mode v2 and keep them in sync as visitors choose.
Basic vs Advanced Google Consent Mode
Compare Basic and Advanced Google Consent Mode, including tag loading, cookieless pings, GTM settings, verification, and when each mode makes sense.
Block trackers before they load
How OptinStack blocks trackers before they load, how scripts are tagged to consent categories, and how to allowlist essential scripts.
Install OptinStack on your site
Add the OptinStack script tag, load it without slowing your page, and confirm the consent banner renders.
How visitor consent is stored and re-asked
How visitor consent is stored locally and synced to the server, when the banner re-asks, and how consent expires.
How helpful was this article?