---
title: "Coexist with a CMP"
date: 2026-05-04
author: "GTM Kit"
---

# Coexist with a CMP

This guide shows you how to set up GTM Kit so it works with a Consent Management Platform (CMP) without double-firing or conflicting consent state.

## The two-rule summary

Two simple rules cover almost every CMP integration:

1. **Decide who owns Consent Mode v2.** Either GTM Kit emits the defaults, or your CMP does. Never both.
2. **Decide who loads the GTM container.** Either GTM Kit injects it, or your CMP holds it back until consent. Never both.

If you get those two rules right, everything else falls into place.

## Common CMPs and the right setup

The recommended configuration for the four CMPs most commonly used with GTM Kit:

### Cookiebot

Cookiebot emits Consent Mode v2 defaults itself when you enable Google Consent Mode in its settings. It also blocks scripts by attribute (`data-cookieconsent="ignore"`).

- **GTM Kit, Default Consent State:** **Off**.
- **GTM Kit, Inject Container Code:** keep on. Cookiebot does not block GTM, and from 2.10 GTM Kit adds `data-cookieconsent="ignore"` to its helper scripts itself so Cookiebot’s auto-blocking lets them through. Individual tags are still gated by Consent Mode.
- In Cookiebot: enable **Google Consent Mode** in the dashboard.

### Complianz

Complianz integrates with the WordPress Consent API and emits Consent Mode v2 defaults itself.

- **GTM Kit, Default Consent State:** **Off**.
- **GTM Kit, Inject Container Code:** keep on. Complianz reads consent state from the user’s choices and signals tags via Consent Mode.
- In Complianz: confirm **Google Consent Mode v2** is enabled under **Integrations**.

### CookieYes

CookieYes emits Consent Mode v2 defaults when configured.

- **GTM Kit, Default Consent State:** **Off**.
- **GTM Kit, Inject Container Code:** keep on.
- In CookieYes: enable **Google Consent Mode** in **Settings, Advanced**.

### Cookie Information (Danish CMP)

Cookie Information emits Consent Mode v2 defaults.

- **GTM Kit, Default Consent State:** **Off**.
- **GTM Kit, Inject Container Code:** keep on.
- In Cookie Information: confirm **Google Consent Mode** is enabled in the platform.

## CMP script attributes

When a CMP plugin scans your page and adds `data-cookieconsent="ignore"` (Cookiebot), `data-cmp-ab="1"` (Iubenda), or `data-cookie-consent="ignore"` (CookieYes) to scripts it doesn’t recognise, those scripts are gated until consent is given. GTM Kit’s helper scripts shouldn’t be gated; they only push to `window.dataLayer`, they don’t set cookies or send data anywhere themselves.

**Settings → Consent → CMP script attributes** lets you tell GTM Kit to add the right ignore attribute itself, so the CMP’s scanner sees it and lets the scripts through.

- **Cookiebot.** Adds `data-cookieconsent="ignore"`.
- **Iubenda.** Adds `data-cmp-ab="1"`.
- **CookieYes.** Adds `data-cookie-consent="ignore"`.
- **Custom.** Add a custom attribute name and value for any other CMP. Names accept letters, digits, underscores, and hyphens. Other characters are stripped at save.

On fresh installs we detect Cookiebot, Iubenda, or CookieYes and pre-select the matching toggle. Upgraders from pre-2.10 keep Cookiebot on by default so the previously hardcoded `data-cookieconsent="ignore"` attribute is preserved.

## Why “off” is the right answer for all four

All four CMPs above emit `gtag('consent', 'default', ...)` themselves. If GTM Kit also emits a default block, the second one overrides the first depending on script load order. The override is unpredictable across browsers and visit conditions, which means consent state silently varies for some visitors.

The fix is to let only one source declare defaults. Your CMP is the better choice because it knows the user’s region (it has IP geolocation), the user’s stored preference (cookie history), and the legal text shown in the banner. GTM Kit only knows what is in the settings page.

## When you should turn GTM Kit’s Consent Mode on

Enable **Default Consent State** in GTM Kit only if your CMP does *not* emit Consent Mode v2 defaults. Reasons this happens:

- The CMP is older and only supports v1.
- The CMP supports v2 but your subscription tier does not include it.
- You are using a homegrown consent banner or a basic plugin that just sets cookies.

In those cases, GTM Kit’s defaults are the only ones present and the master toggle should be on.

## Container injection: who loads GTM?

The default for both GTM Kit and most CMPs is “I load the container.” Both being on means the container loads twice. Pick one.

The answer depends on whether your CMP is “blocking before consent” or “permissive.”

**Blocking CMPs** (some Cookiebot tiers, some OneTrust modes): the CMP wants to hold the GTM script until consent is given. In those cases:

- **GTM Kit, Inject Container Code:** **Off**.
- The CMP loads the snippet itself, after consent.

**Permissive CMPs** (the recommended default for Cookiebot, Complianz, CookieYes, Cookie Information): the GTM container loads on every page, but tags inside it check Consent Mode before firing.

- **GTM Kit, Inject Container Code:** **On**.
- The CMP signals consent state via `gtag('consent', 'update', ...)` and individual tags decide whether to fire.

The permissive approach is what Google’s own documentation recommends and what most CMPs default to. Tags that need consent skip silently; tags that do not need consent (e.g. session security) fire on every load.

## Verify the setup works

In a fresh incognito window:

1. Open your site. View source.
2. There should be exactly **one** `gtag('consent', 'default', ...)` block. If you see two, both GTM Kit and the CMP are emitting; turn one off.
3. The GTM container `<script>` should appear **once**. If you see two, both GTM Kit and the CMP are injecting; turn one off.
4. The DevTools console should show no errors related to `gtag`, `dataLayer`, or `Cookiebot/Complianz/cmp`.

Click “Reject all” in the CMP banner and confirm Google tags do not fire (use GTM Tag Assistant). Click “Accept all” and confirm tags now fire.

## Common issues

**Cookiebot blocks GTM Kit’s data layer pushes.** Cookiebot scans scripts and can prefix them with `data-cookieconsent="ignore"`. If GTM Kit’s helper scripts (dataLayer, integrations) are scanned and gated, events stop pushing. Add an exception in Cookiebot, or i*n GTM Kit, go to* **Settings → Consent → CMP script attributes** *and turn on* **Cookiebot***. This adds* `data-cookieconsent="ignore"` *to GTM Kit’s helper scripts so Cookiebot’s auto-blocking lets them through.*

**Two default blocks load and tags behave differently in different browsers.** Classic symptom of dual emission. Audit and remove one.

**The CMP banner shows but Consent Mode is never updated.** The CMP is misconfigured. Open its settings and confirm “Google Consent Mode” is enabled. Check the CMP’s documentation for the specific toggle; the wording varies.

## For CMPs we don’t support yet: register a signal source

When your CMP isn’t in the list above, you can teach GTM Kit to read consent from it directly by registering a signal source. The registered source takes over from the option-backed default, so you don’t have to flip the master toggle off.

Sources register with a priority. Higher priority wins. The reserved tiers are:

- `gtmkit_default` at priority 10: the option-backed fallback.
- Named CMP integrations at priority 80.
- `wp_consent_api` at priority 100.

To override the default, register at priority above 10. To sit below a named tier, pick a priority below it.

```
add_filter(
    'gtmkit_consent_signal_sources',
    static function ( array $sources ): array {
        $sources['my_cmp'] = [
            'id'        => 'my_cmp',
            'priority'  => 90,
            'is_active' => static fn(): bool => function_exists( 'my_cmp_is_loaded' )
                && my_cmp_is_loaded(),
            'read'      => static function (): array {
                $cmp = my_cmp_get_state();
                return [
                    'analytics_storage' => $cmp['stats']     ? 'granted' : 'denied',
                    'ad_storage'        => $cmp['marketing'] ? 'granted' : 'denied',
                    // ... fill the remaining five categories.
                ];
            },
        ];
        return $sources;
    }
);
```

`read` callables must return `granted` or `denied` for each of the seven Consent Mode v2 categories: `ad_personalization`, `ad_storage`, `ad_user_data`, `analytics_storage`, `personalization_storage`, `functionality_storage`, `security_storage`. Missing keys default to `denied`.

## Related articles

- [Turn on Google Consent Mode v2 defaults](https://gtmkit.com/documentation/turn-on-google-consent-mode-v2-defaults/)
- [Disable container injection](https://gtmkit.com/documentation/disable-container-injection/)
- [Push consent updates from custom code](https://gtmkit.com/documentation/push-consent-updates-from-custom-code/)
- [Conflicts with cache and consent plugins](https://gtmkit.com/documentation/conflicts-with-cache-and-consent-plugins/)