Introduction: Why Storage Choice Matters More Than It Looks

Most teams now have a consent banner and a CMP in place. The legal boxes are ticked, the banner shows up, and users can accept or reject cookies. Job done… right? Not quite

Behind the scenes, how you store the consent state and how you pass it to Google Tag Manager and Consent Mode – has a direct impact on:

In practice, there are two main ways CMPs persist a user’s choice:

  1. First‑party cookie

  2. localStorage

 From the CMP’s perspective, both work. From a measurement perspective, they behave differently, and those differences matter.

This article breaks down:

1. First‑Party Cookies vs localStorage: Same Goal, Different Behaviour

Both mechanisms are used to “remember” that a user has accepted, rejected, or customized their consent. But under the hood they work quite differently.

1.1 First‑party cookie – key properties

Implications for consent:

1.2 localStorage – key properties

Implications for consent:

1.3 Behaviour when users “clean up” their browser

This is one of the big practical differences:

There’s no universally “better” option; it’s a trade‑off between UX stability and strict linkage between cookie presence and consent.

2. Implementing Consent with First‑Party Cookies (GTM Example)

There are many valid ways to wire a CMP, GTM and Consent Mode together.
The setup below is one concrete example, using:

2.1 Assumptions

For this example, let’s assume:

cmp_consent=ad_storage=granted|analytics_storage=denied|ad_user_data=denied|ad_personalization=denied

You can adapt names and formats to your own CMP.
As for the sake of an example, we will be using the Simo Ahava Consent mode template to configure consent.

2.2 Step 1 – Let the CMP write the consent cookie

This part is usually handled in the CMP UI or script configuration, not in GTM.
Typical configuration in your CMP:

2.3 Step 2 – Expose the cookie to GTM via a 1st‑party cookie variable

Now we make GTM aware of that cookie.

  1. Go to Variables → New

  2. Variable type: 1st‑Party Cookie

  3. Name it: Cookie – cmp_consent

  4. Cookie name: cmp_consent

This variable will now return a string such as:

ad_storage=granted|analytics_storage=granted|ad_user_data=granted|ad_personalization=granted

whenever the cookie exists.

202512 Local Storage vs FirstParty Cookies Cookie cmp consent

2.4 Step 3 – Extract each consent value with Regex variables

Right now {{Cookie – cmp_consent}} returns a full string, e.g.:

ad_storage=granted|analytics_storage=denied|ad_user_data=denied|ad_personalization=denied

Simo’s Consent Mode template expects four variables, one per consent signal, each returning exactly granted or denied.

A simple way to get there is to use Regex Table variables.

2.4.1 Create Regex – ad_storage

  1. Go to Variables → New

  2. Type: Regex Table

  3. Name: Regex – ad_storage

  4. Input variable: {{Cookie – cmp_consent}}

  5. For Pattern, fill in “(^|\|)ad_storage=granted(\||$)”

  6. As output, fill the table with “granted

  7. As default value, put “denied

So if the cookie contains ad_storage=granted, this variable returns granted.
If the field is missing or malformed, it falls back to denied.

202512 Local Storage vs FirstParty Cookies Regex ad storage


2.4.2 Create Regex – analytics_storage

Same idea:

  1. Variables → New → Regex Table

  2. Name: Regex – analytics_storage

  3. Input variable: {{Cookie – cmp_consent}}

  4. For Pattern, fill in “(^|\|)analytics_storage=granted(\||$)

  5. As output, fill the table with “granted

  6. As default value, put “denied

2.4.3 Create Regex – ad_user_data and Regex – ad_personalization

Repeat for the two V2‑specific signals.

ad_user_data

ad_personalization

 At this point you have four variables:

Each returns granted or denied, exactly as Simo’s template requires.

2.5 Step 4 – Configure the Simo Ahava Consent Mode tag

Now we plug those variables into the Consent Mode (Google tags) tag template.

2.5.1 Add the template to your container

  1. In GTM, go to Templates → Search Gallery

  2. Search for “Consent Mode (Google tags)

  3. Add the template by Simo Ahava

You’ll now have a new tag type available.

2.5.2 Create the “default” Consent Mode tag

  1. Go to Tags → New

  2. Tag type: Consent Mode (Google tags)

  3. Name: Consent Mode – default (from cookie)

Configure:

Leave wait_for_update as you see fit (e.g. 500–1000ms) depending on how your CMP behaves.

       4. Trigger: Consent Initialization – All Pages

When this tag fires:

2.5.3 Optional: “update” Consent Mode tag

Most CMPs also push a dataLayer event once the user saves their preferences, e.g.:

dataLayer.push({
event: 'cmp_consent_updated'
});


If your CMP does not call Consent Mode itself, you can:

  1. Create a second tag with the same template: Consent Mode – update (from cookie)

  2. Command type: update

  3. Use the same four Regex variables (they now read the new cookie value after the user’s choice)

  4. Trigger: Custom Event → event name: cmp_consent_updated

This keeps your whole Consent Mode configuration inside GTM and driven by the CMP cookie.

2.6 Practical example: from CMP selection to working Consent Mode

To make this concrete, imagine this flow:

This is just one possible pattern, but it nicely shows how 1st‑party cookies + Regex variables + Simo’s template fit together.

3. Implementing Consent with localStorage (GTM Example)

The same philosophy applies when your CMP stores consent in localStorage instead of a cookie.

Again, this is just one way to do it; the idea is to show how you can:

3.1 Assumptions

For this example, let’s assume:

ad_storage=granted|analytics_storage=denied|ad_user_data=denied|ad_personalisation=denied

(If your CMP uses JSON, the logic is similar – you’d just adjust the extraction.)

3.2 Step 1 – Ensure the CMP writes to localStorage

In the CMP UI / config:

3.3 Step 2 – Read localStorage in GTM with a JavaScript variable

  1. Go to Variables → New

  2. Type: Custom JavaScript

  3. Name: JS – cmpConsent (localStorage)

  4. Code:

function () {
try {
var raw = window.localStorage.getItem('cmpConsent');
return raw || '';
} catch (e) {
return '';
}
}

This variable returns the full string, e.g.:

ad_storage=granted|analytics_storage=denied|ad_user_data=denied|ad_personalisation=denied

whenever the user has previously made a choice.

3.4 Step 3 – Extract each consent value via Regex variables

You can now repeat the same Regex pattern approach, but using the localStorage variable as input.

3.4.1 Regex – ad_storage (LS)

  1. Variables → New → Regex Table

  2. Name: Regex – ad_storage (LS)

  3. Input variable: {{JS – cmpConsent (localStorage)}}

  4. For Pattern, fill in “(^|\|)ad_storage=granted(\||$)

  5. As output, fill the table with “granted

  6. As default value, put “denied

3.4.2 Regex – analytics_storage (LS)

Same pattern:

3.4.3 Regex – ad_user_data (LS) and Regex – ad_personalization (LS)

Again, each variable now returns exactly granted or denied.

3.5 Step 4 – Configure the Consent Mode tag for localStorage

You can either:


Typical setup:

  1. Tags → New

  2. Type: Consent Mode (Google tags)

  3. Name: Consent Mode – default (from localStorage)

Fields:

Trigger: Consent Initialization – All Pages

If the CMP also triggers cmp_consent_updated when the user changes their mind and writes new localStorage values, you can:

3.6 Practical example: LocalStorage keeping consent stable

Example user journey:

The user does not see the banner again (if your CMP considers consent still valid), and your measurement remains consistent despite cookie clearing.

Conclusion

Whether your CMP stores consent in a first‑party cookie or in localStorage, the crucial part is how that signal is translated into Google Tag Manager and Consent Mode. First‑party cookies give you early, server‑visible consent that’s easy to reuse in sGTM and back‑end systems, while localStorage prioritises UX stability by surviving most cookie clean‑ups.

The implementations in this article – using GTM cookie variables, JavaScript/localStorage variables, Regex extraction and the Simo Ahava Consent Mode template – are just one way to stitch everything together. They illustrate the key idea: choose a single source of truth for consent, normalise it in GTM, and let Consent Mode enforce it consistently across your tags. Once that foundation is in place, you can adapt the details to your CMP, your legal requirements and your measurement stack.


publication auteur Sven Bosschem
AUTHOR
Sven Bosschem

| LinkedinThis email address is being protected from spambots. You need JavaScript enabled to view it.

 

 

Tags: