Integrate OneTrust with Google Tag Manager

I had my first touch with OneTrust in 2018. Since then, I’ve worked with the tool many times as it remains one of the market’s most popular consent management platforms (CMP).

OneTrust is supposed to be easy. They offer an autoblock solution that should automatically block the scripts that don’t have the necessary consent. However, the reality is often not that easy.

This post goes through how you can integrate OneTrust with the consent configuration feature in Tag Manager.

Jump to the technical setup.

OneTrust Autoblock

While autoblock usually works, it falls short in plenty of cases.

One such case of failure is when the tracking is done simply by loading a pixel instead of injecting a script. Autoblock focuses only on blocking scripts.

Another case when autoblock falls short is when a tracking script is bundled inside another script file. In this case, autoblock could block the whole script file and break some of the site’s functionality.

Then there’s the case when it’s not enough just to block or allow a script. Some of the script’s features might not require consent, while others should only be enabled after consent.

What’s the value of having an autoblock solution that you can’t trust? Not much. 

The best solution is to ensure that all tracking scripts are managed in one place in Tag Manager. Once the management of the tracking scripts is centralized, there’s no need for a clumsy and unreliable solution such as autoblock.

Difficulties in Integrating Onetrust with Google Tag Manager

OneTrust is not exactly the best when it comes to aligning the tags in GTM with the consent selections of the visitor.

The usual difficulties in having GTM in sync with the consent preferences are related to the timing of when this information becomes available

OneTrust offers many dataLayer events to make the consent selections available for GTM.

datalayer pushes generated by OneTrust

However, these dataLayer pushes contain a lot of overlap. Probably the reason for that is backward compatibility. Over the years, OneTrust realized that the dataLayer events they initially created were insufficient. Instead of updating the existing ones, they’ve just added new ones.

Currently, the main dataLayer push to look at is called “OneTrustGroupsUpdated.” OneTrust pushes that event whenever the script is loaded, or the visitor updates their consent preferences.

The rest of the dataLayer pushes are legacy.

So, OneTrust has made the information on consent changes available. What’s the difficulty?

OneTrust is not the lightest resource you can load on your website. The initial otSDKStub.js script loads many additional resources before OneTrust is ready to operate.

resources loaded by OneTrust

GTM uses an asynchronous script that’s supposed to load as early as possible when the page is loaded so that the analytics events don’t get a long delay. Usually, when OneTrust has finished loading, and the consent information is available in the dataLayer, the GTM script has already been executed and has attempted to fire the first tags in the container.

Because of that, if we want to rely entirely on the OneTrust dataLayer pushes, we need to delay everything in GTM until they happen. That would, of course, not be very nice.

Here are a few solutions I’ve used over the years for handling the timing-related issues with OneTrust consent selections:

  • Implementing consent banner button click tracking to capture consent status updates
  • Implementing clumsy custom JS solutions to detect when the OneTrustGroupsUpdated dataLayer event actually includes an update in the consent selections instead of just the initial state read from the OptanonConsent cookie.
  • Using trigger groups to capture the “consent granted” event when the tracking scripts can be enabled for a new visitor.

Clearly, these have been less than ideal.

GTM consent configuration

GTM’s consent configuration is a great feature that allows managing the consent state inside GTM and aligning the tags with that. It shouldn’t be mixed with consent mode, a feature the Google tags have for reading the consent configuration data and adjusting their behavior accordingly.

Once you’ve integrated your CMP with the GTM consent configuration, you can align any tag with the consent selections by including additional consent checks. The additional consent checks block the tag if the necessary consent has not been granted.

gtm tag additional consent checks

Tags can also have internal consent checks. Their behavior is defined by whoever created the tag template. With Google tags, the internal consent check will allow the tag to execute, but with limited features, for example, by blocking storage access.

If you’d like to block the tags instead, you can always include an additional consent check in the tag.

The consent overview feature in GTM includes a nice view for checking which tags are linked to which consent levels.

gtm consent overview
The Consent Overview will list the tags that have not been configured for consent.

You can enable the consent overview in your container’s settings.

Enable consent overview

Installing the OneTrust script

How to install the OneTrust script is not really in the scope of this article. However, I will share a few thoughts on what to consider when installing the script.

Firstly, I would prefer not to install OneTrust through GTM

In my opinion, GTM should mainly be used for managing tracking codes and not for injecting new content, such as a consent banner, into the DOM.

However, in some cases, using GTM could be the only option you have. In that case, you can implement the scripts using a custom HTML tag. Just remember to check the “Support document.write” setting in the custom HTML tag!

onetrust tag installation using custom html tag

Integrating the consent preferences between OneTrust and GTM will work just as well, even if you install the OneTrust script through GTM. Also, the integration does not rely on the OneTrust script loading as fast as possible. So, there’s no need to configure setup tags or anything else additional to get the script to load before the consent preferences are communicated to GTM for the first time.

Technical setup – How to integrate OneTrust with GTM

To get started, we need to set up two things:

  1. Access the latest consent state, whether from the dataLayer or from the OptanonConsent cookie.
  2. Feed the consent status into GTM’s consent configuration model.

Once these are in place, each tag in GTM can be aligned with the visitor’s consent selection by utilizing the additional consent checks—no need for blocking triggers.

Accessing the consent state

As mentioned, the latest OneTrust consent status can be fetched by utilizing the dataLayer messages and the OptanonConsent cookie. To make it easier, I’ve created a custom variable template that does it. You can install the template through the GTM template gallery.

OneTrust consent groups variable template

OneTrust Consent Groups template

You can use the template to either return the status of the selected consent group, for example, analytics, or to return the status of all consent groups in one JSON object. 

Start by creating the following four variables, one for each OneTrust consent groups. The variables are needed later for feeding the data into GTM’s consent model.

  1. CT – OneTrust – Analytics Consent
  2. CT – OneTrust – Functional Consent
  3. CT – OneTrust – Personalization Consent
  4. CT – OneTrust – Advertising Consent

(CT here stands for Custom Template)

OneTrust analytics consent variable example

When defining the variables, you’ll need to know the OneTrust codes for each consent group. In this example, “C0002” is the code that links to the analytics (or performance) cookies consent. In another setup, the code could be just “2”. I think different OneTrust versions could have different mappings. Sometimes the mapping could also be customized.

You can select either “true / false” or “denied / granted” for the return format. GTM’s consent APIs use the terms “denied” and “granted”. However, the GTM Consent Configuration tag template in the next step will understand “true” and “false” as well.

Feed the consent selections into GTM’s consent model

GTM’s template APIs have two commands for declaring consent: setDefaultConsentState and updateConsentState

The default consent is used for declaring the consent selections as soon as possible and before any queued dataLayer events. When done using the Consent Initialization trigger, all tags that are fired during later dataLayer events can access the information.

The consent update command is used whenever the consent selections have already been declared, but there is an update in the preferences.

Start by installing the GTM Consent Configuration tag template from the template gallery.

GTM Consent Configuration template

After adding the template, create two tags: one for declaring the initial consent during page load and one for updating consent selections during the “OneTrustGroupsUpdated” event.

Tag 1: Declare initial consent selections

set initial gtm consent tag

Include the consent update listener. It will generate a dataLayer event whenever the consent preferences of a user change.

The tag should be set to fire as early as possible using the Consent Initialization – All Pages default trigger.

Tag 2: Update consent selections

update gtm consent tag

Use the OneTrustGroupsUpdated dataLayer event as the trigger for the update tag. This way, any changes to the visitor’s consent preferences will be communicated to GTM’s consent model.

In addition to the actual consent preference changes, OneTrust sends the OneTrustGroupsUpdated event on each page load. This means that most of the events are irrelevant. However, there’s no harm in running the update tag with these events as well.

onetrust groups updated trigger

The variables used in the tags will default to consent denied if there’s no data in the dataLayer messages or the cookie.

With these two tags, the flow for a new visitor looks like this:

  1. Each consent selection is set to denied upon page load
  2. Once the actual preferences are set, the consent levels are updated accordingly

Integrate the tags with the consent preferences

Now that the base setup is in place, the next step is integrating all tags with the consent preferences. If you want to block the tag from firing without the required consent, you should include an additional consent check in the tag’s advanced settings.

include an additional consent check

Remember to utilize the Consent Overview feature to check for any tags with missing consent checks.

On the other hand, if you want to utilize features such as Google’s consent mode, which collects data without storage access, you should not include an additional consent check. The tags will read the consent preferences in GTM’s consent model and adjust their behavior accordingly.

Consent granted triggers

When you want to block the tags from firing without consent, you’ll likely encounter some cases where important data from new visitors could be missed. For example, with Google Analytics, capturing the first page view is essential, as it holds information about the traffic source. The issue is that the visitor won’t have enough time to grant consent before GTM tries to fire the page view tag.

The solution is to set up a consent granted trigger.

The initial GTM consent tag includes a consent update listener, which will trigger a dataLayer event whenever a consent type that wasn’t previously allowed is granted. You can use these dataLayer events as additional triggers for tags like the GA page view, which should capture the first visited page.

consent granted datalayer events
Example: consent granted dataLayer events that are sent when the visitor accepts all cookies

Using the dataLayer events, you can define additional triggers to be added to the tags that require it.

analytics storage granted trigger
page view tag triggers example
Example triggers in a page view tag

Final thoughts

The consent configuration in GTM is an excellent way to handle the consent integration of individual tags. Before it, we used to rely on blocking triggers, which was a very error-prone way of handling the consents. 

While some CMPs do a great job of providing integrations with GTM consent configuration, some don’t. You can use the GTM Consent Configuration tag template referenced in this post to align any consent solution with GTM’s consent configuration. The only thing that is needed is that the data is made available somehow, be it through dataLayer or a cookie, for example.

6 thoughts on “Integrate OneTrust with Google Tag Manager”

  1. Avatar photo
    Aksel Sabah

    Hi! Thank you so much for the article, it’s quite helpful. My only concern would be the initial loading of GTM with the consent template and its following applied logic.

    Does this integration with consent-mode is also efficient in performance? Escpecially compared to blocking triggers that I currently use.

    1. Avatar photo
      Taneli Salonen


      I don’t see any performance issues in this method compared to using blocking triggers.

      The consent APIs in GTM are designed to be used like this, so that you set the consent preferences as early as possible using the consent initialization trigger. Basically, what happens during the consent initialization event, is that the dataLayer and the OneTrust cookie are being read by the variables. Then, using that information, the data is communicated to GTM using GTM’s own internal consent APIs. I think these are both very light operations, and I don’t really see how they could degrade site performance compared to blocking triggers. The blocking triggers also require the same data to be accessed and applying the blocking logic to each tag.

      Consent mode is then separate thing. It’s built into the Google tags and utilizes this consent selection data that is now integrated to GTM’s consent configuration.

  2. Hello Taneli,

    I wanted to express my gratitude for the article you shared; it has proven to be incredibly helpful. I’ve been searching for a guide like this for a while. I’m new to implementing consent management, and I have a question. Can we place the Google Tag on the ‘All Pages’ trigger, or should we stick with ‘Dom Ready’ only? Additionally, we need to use the ‘analytics_storage_granted’ trigger for the Google Tag and all the Events Tags. I’ve already implemented this in one of my containers, and I’ve attached the exported JSON file to the drive( Could you please take a look and confirm if I’ve set everything up correctly? Your assistance would be greatly appreciated. Thank you!

    1. Avatar photo
      Taneli Salonen


      With this solution, you only need to make sure that “set initial consent” tag is fired before the Google Tag. If you fire the initial consent tag using the consent initialization trigger, you can very well use the “All Pages” trigger for the Google Tag. In this solution, the Google Tag does not need to wait for the OneTrust script to have finished loading.

      I’ve been using the “analytics_storage_granted” only with the Google Tag (and the page view tag in case you have it as a separate tag).

      With the other tags, I’ve just accepted that the events will be missed if they happen before the user grants consent. Capturing those other events, in case they were missed because of consent not yet granted, could be a bit more difficult. For some important events, you could try to utilize the GTM trigger groups, if needed:

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top