Hi Data Collection community!
I'm trying to implement Google Consent Mode v2 with OneTrust as my consent management platform and I am using Adobe Launch instead of GTM.
Previously I was using the GTAG extension by Acronym, but this extension seems to inject GTAG scripts for Google accounts (Google Analytics, Google Ads, etc.) into the `<head>` of my web application in an order that does not abide with what OneTrust documentation states.
I have even reached out to OneTrust support and they seem to agree that we are not able to use the GTAG extension for that reason (although they did not sound too confident in that confirmation).
Due to that, I have been testing abandoning the GTAG extension and including most of what the extension was doing in the `<head>` of my web application.
Now, Adobe Launch is only responsible for sending GTAG events using Custom Code actions.
However, after testing this refactor, I am noticing that GTAG scripts are being duplicated in the `<head>` of my web application.
The duplicated GTAG scripts are showing up at the very top of the `<head>` which again does not abide by the order of scripts that OneTrust documentation shows as we need the consent default command to be first.
I have a single page React application.
I also attached a PDF file that explains my concerns better and has screenshots to show the issue.
I understand this might be a better question to ask elsewhere such as the Google forums, or GA or GTAG subreddits.
Thought I would ask here regardless just in case somebody has ran into this issue.
Unfortunately, I don't believe I would be able to get a contact with a Google support agent directly.
Solved! Go to Solution.
The way it usually works is, the initial gtag js will load whenever this runs:
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID">
BUT for each time you run the config line:
gtag('config', 'TAG_ID');
If the Tag ID of your config line doesn't match the js you already loaded, it will load yet another gtag js file at the top of your head.
So if I do this:
Then I end up with this:
Where the red line is the one I deliberately added to the page, and the other three all exist because their configID didn't match what was already loaded. This matches my past experience.
But oddly, that doesn't seem to match your experience, since you are manually setting a script for each account, then doing a config line for each account, and somehow ending up with a script for each- I would expect since you are adding the JS for each account, that the configs wouldn't append the new JS files. Interesting. I'm not able to replicate that, but I wonder if it's a timing thing- since the gtag files load asyncronously, there is no guarantee they'll all be in place when your config codes run.
You could probably get away with only manually adding the script once, then letting the configs add the other files as needed (kinda like in my screenshot just now- this is the approach I've taken in Launch for years- I even blogged about it in 2021, which Google retweeted, so... can't be all wrong).
That said, the order you have things in makes sense to me and seems to match what the automatic Onetrust solution is going for: you establish the gtag function and datalayer, set consent, load the script(s), config each account, load onetrust, then load Launch. While the files being inserted to your head might cause some redundancy, it doesn't harm anything, especially if it happens after your page has rendered, and it doesn't indicate anything isn't working as expected. Gtag throws redundant files around all over the place. If you snoop around the web, you'll see probably half of public sites on the internet have some gtag files automatically inserted above the head- for instance, if you go to the website of a certain very popular orange Home Improvement Store, you'll see this:
So what you have seems to be working as expected (though I haven't seen the google beacons to ensure the consent parameters are correctly set.) Though personally, I'd still probably not go the way Onetrust recommends, particularly if it requires loading my scripts/doing my configuration outside of my tag manager. Especially since you are in a default-opt-in situation, where you don't have to really worry about making sure onetrust can manage your default state (which is more important in default-opt-out settings), there isn't much reason to not just manage it all in Launch:
1. Onetrust Loads
2. Launch Loads
3. A rule in Launch, that fires on page load, with conditions to fire only if onetrust says there is consent, which contains custom code to set consent to true, load the gtag js, config the gtag account, then maybe fire any subsequent gtag events as needed (that's the old school/"Basic" approach where if the user doesn't consent, we simply don't track them). Heck, if you go this route, you may be able to go back to using the gtag extension.
If you are really interested in using consent mode v2 "Advanced", where if the user has not given consent, you can still track "cookieless pings", then for step 3 you'd do this instead:
3. A rule in Launch that fires on page load regardless of consent, with custom code that sets consent dynamically based on what onetrust says, then loads the gtag/configures account/fires gtag events. Note, this means even without consent, those gtag files will load, and data will be sent to Google, it just won't set cookies. That's the nature of "advanced consent mode".
At what point are the gtag scripts being added to the head? Because that is the very nature of gtag- 10 minutes after the page has loaded, if I run the gtag snippet in my console, it will add a gtag script to my <head>. (Obnoxiously, i will add a whole other script for each tag/account I send data to.) Normally being in the <head> means it has loaded first, but in this case, it's just where gtag appends its script, even long after your page has loaded. So your Onetrust problem is less one of the tag being in the head, and more one of timing.
It looks like Onetrust has a more automatic solution, where you configure your gtag defaults first, so as Onetrust loads, it can update them as needed. But that's not the only way you could tackle this. If Onetrust didn't have this prepackaged solution for consent mode, it would probably be simpler for you. (And frankly, I find it surprising that Onetrust would recommend putting gtag script before Onetrust loads, when Onetrust's own very reasonable best practice is usually to have Onetrust load before any marTech scripts). Personally, I'd load Onetrust first, just like I do with any marketing tag, and either use a rule condition to entirely turn gtag on or off (same as I do with other marketing tags), OR, have gtag always fire, but use Javascript to dynamically populate the consent setting variables based on the user's preferences (as stored by Onetrust).
Are you in the EU (with folks-are-opted-out-by-default rules) or elsewhere (like in the US, where in general folks can be opted in by default, so long as they have a way to opt out)? Do you need to have the setting be fairly dynamic (are you dealing with multiple regions) or do your users generally all fall in the same privacy regulation jurisdiction? Also, how committed are you to using consent mode v2, where if someone is "denied", Google will still collect data, just without tying it to any cookies? One could make a good argument for why even with consent mode v2 as an option, it may be best to have a simple "with consent we fire the tag, without it we don't".
Thanks for your thorough reply @Jennifer_Kunz
At what point are the gtag scripts being added to the head?
The ones that show up at the very top of my `<head>` (the "duplicated" ones) seem to appear immediately as a page (or route in the context of React) loads.
Assuming that the GTAG scripts that show up at the top of the head ARE in fact being injected SOME time after the page loads, does that mean that my consent default script may in fact still be executed first BEFORE the injected GTAG scripts show up?
This is the main order of scripts I have been trying.
I say "main" because I have tried several different ordering of scripts.
This is a combination of an example from Google's documentation and OneTrust's documentation.
OneTrust's documentation doesn't mention where to place the GTAG config commands (as you can see in the screenshot in my initial post).
Whereas Google's documentation shows the GTAG config commands in a separate script below the GTAG scripts like
Again, that results in this when I run my test React web application.
This also results in the following messages in the Chrome console:
Are you in the EU (with folks-are-opted-out-by-default rules) or elsewhere (like in the US, where in general folks can be opted in by default, so long as they have a way to opt out)?
I am in Canada and have confirmation that we can set the default consent settings to `granted` for all regions.
Do you need to have the setting be fairly dynamic (are you dealing with multiple regions) or do your users generally all fall in the same privacy regulation jurisdiction?
I do not need different settings for different regions (e.g., provinces). We have a OneTrust consent banner where a user is able to update their cookie preferences. This pushes a consent update event to the Google data layer and also updates the OneTrust `OptanonConsent` cookie. Currently, we only send GTAG events if we have the proper consent by checking the `OptanonConsent` cookie. This is done by rule conditions. But we are looking into updating that approach by implementing Google Consent Mode v2.
Appreciate your help.
There is so much conflicting information out there and seemingly unfinished documentation.
The way it usually works is, the initial gtag js will load whenever this runs:
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID">
BUT for each time you run the config line:
gtag('config', 'TAG_ID');
If the Tag ID of your config line doesn't match the js you already loaded, it will load yet another gtag js file at the top of your head.
So if I do this:
Then I end up with this:
Where the red line is the one I deliberately added to the page, and the other three all exist because their configID didn't match what was already loaded. This matches my past experience.
But oddly, that doesn't seem to match your experience, since you are manually setting a script for each account, then doing a config line for each account, and somehow ending up with a script for each- I would expect since you are adding the JS for each account, that the configs wouldn't append the new JS files. Interesting. I'm not able to replicate that, but I wonder if it's a timing thing- since the gtag files load asyncronously, there is no guarantee they'll all be in place when your config codes run.
You could probably get away with only manually adding the script once, then letting the configs add the other files as needed (kinda like in my screenshot just now- this is the approach I've taken in Launch for years- I even blogged about it in 2021, which Google retweeted, so... can't be all wrong).
That said, the order you have things in makes sense to me and seems to match what the automatic Onetrust solution is going for: you establish the gtag function and datalayer, set consent, load the script(s), config each account, load onetrust, then load Launch. While the files being inserted to your head might cause some redundancy, it doesn't harm anything, especially if it happens after your page has rendered, and it doesn't indicate anything isn't working as expected. Gtag throws redundant files around all over the place. If you snoop around the web, you'll see probably half of public sites on the internet have some gtag files automatically inserted above the head- for instance, if you go to the website of a certain very popular orange Home Improvement Store, you'll see this:
So what you have seems to be working as expected (though I haven't seen the google beacons to ensure the consent parameters are correctly set.) Though personally, I'd still probably not go the way Onetrust recommends, particularly if it requires loading my scripts/doing my configuration outside of my tag manager. Especially since you are in a default-opt-in situation, where you don't have to really worry about making sure onetrust can manage your default state (which is more important in default-opt-out settings), there isn't much reason to not just manage it all in Launch:
1. Onetrust Loads
2. Launch Loads
3. A rule in Launch, that fires on page load, with conditions to fire only if onetrust says there is consent, which contains custom code to set consent to true, load the gtag js, config the gtag account, then maybe fire any subsequent gtag events as needed (that's the old school/"Basic" approach where if the user doesn't consent, we simply don't track them). Heck, if you go this route, you may be able to go back to using the gtag extension.
If you are really interested in using consent mode v2 "Advanced", where if the user has not given consent, you can still track "cookieless pings", then for step 3 you'd do this instead:
3. A rule in Launch that fires on page load regardless of consent, with custom code that sets consent dynamically based on what onetrust says, then loads the gtag/configures account/fires gtag events. Note, this means even without consent, those gtag files will load, and data will be sent to Google, it just won't set cookies. That's the nature of "advanced consent mode".
Thanks for your very thorough reply. It's greatly appreciated.
Give me some time to digest everything and I'll follow up with another message hopefully today, if not, tomorrow.
I noticed that in your blog post you mentioned how we may be able to provide a single one of the GTAG scripts without even including an ID for a Google account, and let the GTAG config command handle that.
When I try that approach, I do not get duplicate scripts.
I suppose one concern is that sometimes (multiple refreshes) the GTAG scripts for each account show up at the top of the <head> and sometimes at the bottom. Sounds like it may be due to a race condition? Not sure if it is a concern.
When the scripts appear at the bottom, OneTrust seems to correctly apply its classes to the GTAG script elements.
When the scripts appear at the top, the OneTrust classes do not seem to get applied.
I don't expect you to know what is happening here, and this is something we can double check on our end.
The `gcs` parameter of `G111` for my test `view_item` event does seem to reflect all consent defaults being set to granted.
In my next post (as I am limited to 4 attachments) will show what things look like when we use the GTAG extension from Acronym.
And here is the result of going back to the Acronym GTAG extension. So the web app only includes Adobe Launch followed by the OneTrust scripts in the `<head>`.
In the pre-account initialization custom code feature of the extension, we have the code snippet that sets the consent defaults all to granted.
Which looks like this in the Google data layer.
All of the OneTrust classes get applied to the GTAG script elements.
And the consent default commands show up before the GTAG config commands in the data layer.
I suppose the Google Floodlight script (DC-1) shows up at the bottom while the rest of the scripts appear at the top.
But I'm starting to think that the location in which the GTAG scripts appear isn't really a problem.
I've been too fixated on trying to get scripts to appear in an order that abides with this documentation:
https://my.onetrust.com/s/article/UUID-d81787f6-685c-2262-36c3-5f1f3369e2a7?language=en_US
Example 2, without CMP template and gtag script:
<script>
// Define dataLayer and the gtag function.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Default ad_storage to 'denied' as a placeholder
// Determine actual values based on business requirements
gtag('consent', 'default', {
'ad_storage': 'denied'
});
</script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID">
</script>
<!-- OneTrust Cookies Consent Notice start -->
<script src="https://cdn.cookielaw.org/scripttemplates/otSDKStub.js" type="text/javascript" charset="UTF-8" data-domain-script="XXXXXX" ></script>
<script type="text/javascript">
function OptanonWrapper() { }
</script>
<!-- OneTrust Cookies Consent Notice end -->
But again, I don't think I need to worry about following that too closely?
At the end of the day, I think we just need to ensure that we are seeing the correct `gcs` parameter for events, and that the OneTrust classes get applied to the GTAG scripts (which they do seem to consistently get applied when using the extension).
I agree, I don't think the order things appears in matters nearly as much as the end results. Sounds like you're well on your way to figuring it out.
Views
Likes
Replies