Consent Mode 101 for Marketers

In this post I talk about:

Share the Post:

In an era where digital privacy is key, marketers are often caught in a dilemma between respecting user preferences and gathering valuable data to make informed decisions. For this exact reason, the Consent Mode has been created to help marketers respect privacy regulations like GDPR in the European Union, while collecting useful data. While this topic is key, the documentation on the implementation and its impact is scarce.

In this article, we’ll explain how the consent mode needs to be implemented from a technical perspective and how it impacts data gathering.

What is the purpose of Consent Mode?

I won’t explain in-depth why Consent Mode exists, but as a bottom line: it impacts the way your marketing tags behave. Based on the user selection, the amount available in Google Analytics will be different. Consent mode receives your users’ consent choices from your cookie banner or widget and dynamically adapts the behavior of Analytics, Ads, and third-party tags that create or read cookies.

Technical implementation

Default consent

For this section, we’ll assume you use GTM to trigger your marketing tags. In the latest version, available currently, Consent Mode includes four consent types:

Consent TypeDescription
ad_storageEnables storage, such as cookies (web) or device identifiers (apps), related to advertising.
ad_user_dataSets consent for sending user data to Google for online advertising purposes.
ad_personalizationSets consent for personalized advertising.
analytics_storageEnables storage, such as cookies (web) or device identifiers (apps), related to analytics, for example, visit duration.
functionality_storageEnables storage that supports the functionality of the website or app, for example, language settings
personalization_storageEnables storage related to personalization, for example, video recommendations
security_storageEnables storage related to security such as authentication functionality, fraud prevention, and other user protection

By default, and when someone access your website for the first time, you should default these consent types to denied, except for functionality storage. This can be done using one of the following options:


Most websites use what is called a DataLayer. From a technical standpoint, it is simply a JavaScript array that stores information you need (more information here). You can easily check if a website has it by opening the console and typing dataLayer. In some cases, the name of the variable can be different, but in my experience it is rarely the case.

This object is used by GTM, and it is where we need to specify the default consent values. In our case, we need to execute the following JavaScript before our GTM code to ensure that GTM can read these values. This is a task someone from IT can perform easily on most CMS. On WordPress for instance, you’ll just have to edit the header.php file.

// create an empty array if the dataLayerTag is not defined
window.dataLayer = window.dataLayerTag || [];

// create a function called gtag that pushes the arguments to the dataLayer array
function gtag() {

// call the function with the default consent values
gtag('consent', 'default', {
    "ad_storage": "denied",
    "ad_user_data": "denied",
    "ad_personalization": "denied",
    "analytics_storage": "denied",
    "functional_storage": "granted",
    "personalization_storage": "denied",
    "security_storage": "denied",
    "wait_for_update": 500
  • You need to add this code BEFORE the GTM tag; otherwise you may find yourself in a situation where GTM tries to read the consent status before it is even defined.
  • You can adapt your code based on the local legislation. The code snippet above would work for most EU countries, for instance.


You can define the default consent directly in GTM by using this template from Simo Ahava. Just follow the instructions to configure your tag and set up the default consent states.


Some CMP integrates an option to configure the default value for these consent states. Refer to the documentation of your vendor to know how to configure it properly.

Checking that default consent is working

Once any of these solutions are implemented, you need to make sure that it is correctly implemented. It can be done easily through GTM.

  • Open GTM and select your container
  • Open the website and make sure that you remove all your cookies. In Chrome, you can do that easily using the EditThisCookie extension. This shouldn’t have an impact on what you do, but it’s always better to do it when debugging from scratch in GTM.
  • Click on Preview next to the Submit button, on the top-left hand corner of your screen. If thus button is not available, you need to ask your client to add additional rights to your account.
  • In the Tag Assistant window, make sure that you can spot the Consent Default item on the left and that you have the desired output in the Consent tab.

If you don’t, there is an issue with your implementation, and you need to figure out why.

Updated consent

While we need a default state, we also need an updated status based on the user selection. It is challenging to define a flow that would work for everyone, but the most common would be the following:

  • When a user interacts with your cookie banner and based on the selection, a cookie is generated with the details.
  • You can then read this cookie and fire an update script like the one shown below. If you can, trigger one update with everything, but sometimes you may need to trigger more than one call.
gtag('consent', 'update', {
      'ad_storage': 'granted'

Note that this function will work only if the gtag is defined before, which may not be the case based on the option you used to implement the default values. If it’s not defined yet, do it first:

// create a function called gtag that pushes the arguments to the dataLayer array
function gtag() {

gtag('consent', 'update', {
      'ad_storage': 'granted'

This step is crucial because:

  • if you don’t update your consent based on your user selection, from a GTM perspective the user selection doesn’t matter as you’ll always use the default value (denied)
  • If you don’t store the user selection in a cookie, you won’t be able to know what it was for subsequent pages and you’ll be forced to use the default value (denied)

To check that everything is working, use the GTM Preview Mode and look for Consent Update and see how it impacts the content of the Consent tab. In our example, we have different calls and this one is updating the default (denied) value of analytics_storage.

Configure GTM

When we add GA4 to our GTM container, our tag setup will often look like this:

The All Pages trigger, available by default in GTM, will fire a tag when the container snippet (the GTM code you include on your website) is loaded. In our example, the consent update tags are fired after the Container Loaded event. Therefore, we’ll always send our GA4 hits with the default state: denied.

Therefore, you have two options:

  • Ensure that the consent update calls are sent before the GTM code is read. This example is doing exactly that, where the UPDATE block is added in the code with the user selection, which can be achieved easily with a bit of front-end development.
  • If that’s not possible, you have to change the trigger linked to your GA4 tag. In GTM, you have to find an event name that is triggered after your update calls. In that case, we have OptanonLoaded.

You’ll then adjust your GTM configuration to trigger the GA4 tag when the OptanonLoaded event occurs.

Double-check the implementation

Once you’ve followed these steps, double-check your implementation. You can use the Preview Mode to achieve that in a couple of minutes:

  • At the top of the screen, click on the Google tag icon corresponding to your GA4 property
  • Click on the Page View hit that you see
  • Check what the value of the Google Consent State is.

The possible values are the following:

G100No consent has been granted.
G110Google Ads has consent, Google Analytics does not.
G101Google Analytics has consent, Google Ads does not.
G111Both Google Ads and Google Analytics have consent.

Ensure that these values are coherent with the user selection you test. If that’s not the case, review your setup.

Impact of consent mode

Now that you’ve implemented the consent mode, you may wonder what the impact on your data will be. I’ll just explain what it means for GA4.

How does GA4 model data?

Firstly, let’s explain how GA4 handles the data. When you send a GA4 hit, three parameters are always sent:

  • Google Consent State that we’ve already explained
  • Session ID to identify your session
  • Client ID to identify your browser

The session ID and the client ID are used by GA4 to understand building session-scoped and user-scoped metrics.

When you first land on a page and assuming you didn’t give consent before the GA4 tag is fired, the Google Consent State will be G100. If a different value is sent during your session, Google will override it and use the last one because it is session-scoped.

Under this scenario :


The computed state will be G111. It is critical to understand that because it means that you’d still get (for instance) the landing page even if the consent is granted on the second page view.

Interface (UI)

If you’re using the UI, the data will only include information for sessions where the consent has been granted. In plain English: if your consent rate is 50%, you’ll have access to 50% of your data. You can alter this behavior by going to Admin > Data display > Reporting identity and selecting Blended instead of Observed.

I don’t really like this option because the explanation of how it works is not clear and modelling is applied different in exploration and reports. But it’s completely up to you.


I’ve already explained how you can improve your GA4 experience with BigQuery and I still stand by it. There is another advantage of such implementation: cookieless pings. While information regarding non opt-in users will be hidden from the UI (unless you change the reporting identity setup), this is not the case in BigQuery.

You’ll receive all the information, with a (huge) caveat, though: some fields will be empty. From the export schema, you’ll receive all the information but:

  • the user_pseudo_id (also called client_id)
  • session_id
  • traffic_source fields

The user_pseudo_id and the session_id are used to tie events to a marketing channel (organic search, for instance). You’ll be forced to link conversions to an unknown channel because you won’t have the information to do something else, unless you come up with a more advanced logic.

A concrete example

Let’s imagine that you have an E-commerce with 1,000 sales (from your CRM data) and you want to know what is the best marketing channel.

  • Around 15% of them won’t show in GA4 because you always have users / browsers using ad blockers such as uBlock Origin. You’ve lost 150 sales in your reporting.
  • Your consent rate is 75%, you’re left with 637 (850*0,75) sales
  • You always have a part of your transactions assigned to the Direct (that I prefer to call Unknown) channel. Let’s assume 25% here.

So, out of 1,000 sales, you’re stuck with 477 for your analysis, roughly half of them. This is not an ideal situation, but it’s the reality you’ll have to live with. If you’re dealing with a lot of data and given the regression toward the mean theory, this is not a big issue. But if your sampling is smaller, this is a real challenge to take accurate decisions.

The same will apply if you analyze the best landing pages, for instance. You cannot tie a purchase to a landing page if you don’t have the session_id; hence you’ll have to analyze a sample of your data.


Consent mode, from its implementation to the impact on our data, is a complex topic we need to get familiar with because it heavily impacts our decision process. By understanding the technical aspect of it, you’ll understand better the data at your disposal and the biases you can have when you crunch them.

Get familiar with it, especially in countries where GDPR or GDPR-like legislations exist because they’re not likely to go away soon.

Share the Post: