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.
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.
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.
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.
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.
You can enable the consent overview in your container’s settings.
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!
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:
- Access the latest consent state, whether from the dataLayer or from the OptanonConsent cookie.
- 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.
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.
- CT – OneTrust – Analytics Consent
- CT – OneTrust – Functional Consent
- CT – OneTrust – Personalization Consent
- CT – OneTrust – Advertising Consent
(CT here stands for Custom Template)
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
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.
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
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
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.
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:
- Each consent selection is set to denied upon page load
- 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.
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.
Using the dataLayer events, you can define additional triggers to be added to the tags that require it.
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.