⚠️ IMPORTANT NOTE: The geolocation approach described in this article relies on a third‑party IP‑based geolocation service (e.g.
ipapi.co) to determine the visitor’s country before consent is collected.This may have direct GDPR and ePrivacy implications. Before implementing any solution, you should consult with your legal advisors and privacy consultants.
What This Means:
- The visitor’s IP address is processed and transmitted to a third party
- An IP address may be considered personal data under GDPR (Art. 4)
- This processing happens before consent is obtained
- To process personal data, there must be a valid legal basis (e.g. legitimate interest Art. 6(1)(f))
Your Obligations as a Website Owner
If you implement this solution, it is recommended to:
- Explicitly disclose this processing in your Privacy Policy
- Clearly state:
- That a third‑party geolocation service is used
- That the visitor’s IP address is processed for country detection
- The purpose (deciding which consent framework applies)
- Name the service provider and link to their privacy policy
- Assess and document a Legitimate Interest balancing test
Failing to do so may constitute a GDPR violation, regardless of whether Cookiebot or GA4 are compliant.
Due to existing technical constraints, the IAB TCF 2.x banner, when activated, is displayed globally across all countries and regions, even though the framework is specifically associated with Europe's GDPR legislation.
Nevertheless, there is a solution to address this issue, although it is somewhat technical in nature. This article will examine this method in detail.
The full capabilities of Google Tag Manager to conditionally trigger tags will be leveraged in this workaround.
The objective of this setup is to only inject the IAB TCF (Transparency & Consent Framework) code into the Cookiebot CMP banner when the user is located in a country where TCF is required (primarily GDPR / EEA and selected non‑EEA jurisdictions).
High‑Level Architecture
- Detect the visitor’s country using an IP‑based geolocation API
- Push the detected country to the
dataLayer - Decide (based on country) whether:
- TCF attributes should be injected
- Fire Cookiebot CMP only after geolocation is known
Tags Used in This Setup
| Tag Name | Purpose | Firing Priority |
|---|---|---|
COUNTRY_DATALAYER | Pushes resolved country into dataLayer | 3000 |
INJECT_TCF | Conditionally injects TCF attribute | 2000 |
Cookiebot CMP | Loads the Cookiebot banner | 1000 |
Lower numbers = fires later.
1. Country Detection (Custom JavaScript Variable)
We use a Custom JavaScript Variable in GTM to synchronously fetch the visitor’s country using the IPapi: IP Address Lookup and Geolocation API service.
⚠️ Note: This uses a blocking XHR request. While not ideal from a performance standpoint, it guarantees the country is available early and consistently.
- Navigate to the Variables section of GTM
- Click New (located at the right side of the screen, next to the lowest magnifying glass icon)
- Under Choose variable type, chose Custom Javascript
GTM Variable: GEOLOCATION_FETCH
function() {
if (!window.geoLocationData) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://ipapi.co/json/', false);
xhr.send(null);
if (xhr.status === 200) {
window.geoLocationData = JSON.parse(xhr.responseText);
} else {
window.geoLocationData = { country: 'Unknown' };
}
}
return window.geoLocationData;
}This returns an object like:
{ country: "SE", ... }window.geoLocationData to avoid repeated API calls.Save your changes. The result should look like the below
2. Push Country Data to the Data Layer
Next, we push the detected country into the dataLayer and decide whether TCF should load.
GTM Tag: COUNTRY_DATALAYER
- Tag type: Custom HTML
- Trigger: Consent Initialization – All Pages
- Priority: 3000
Here is how to do the above.
- Navigate to the main Tags section of GTM,
- Click New (located at the right site of the screen, next to the Consent Overview icon)
- Under Tag Configuration, chose Custom HTML
- Paste in the below code in the HTML area
- Chose Consent Initialization – All Pages under Triggering
- In the Advanced Settings drop down, type in 3000 under Tag Firing Priority
<script>
(function() {
var geo = {{GEOLOCATION_FETCH}};
var country = geo && geo.country ? geo.country : 'Unknown';
dataLayer.push({
event: 'geoDataReady',
geoCountry: country
});
// Cookiebot always fires
dataLayer.push({ event: 'fireCookiebot' });
})();
</script>What this does
- Pushes
geoDataReadyfor debugging and visibility - Pushes the
fireCookiebotevent to run aftergeoDataReadyhas been successfully executed
Save your changes. The result should look like the below
3. Conditionally inject TCF Code into Cookiebot
The data-framework="TCFv2.2" is injected only when the GEOLOCATION_FETCH variable is matched with a correct country ISO.
To achieve the above, create a Custom HTML tag the same way described as in Paragraph 2:
GTM Tag: INJECT_TCF
- Tag type: Custom HTML
- Trigger: TRIGGER_TCF (see Paragraph 4)
- Priority: 2000
<script>
(function() {
var geo = {{GEOLOCATION_FETCH}};
var country = geo && geo.country ? geo.country : 'Unknown';
var tcfCountries = [
"AT","BE","BG","HR","CY","CZ","DK","EE","FI","FR",
"DE","GR","HU","IS","IE","IT","LV","LI","LT","LU",
"MT","NL","NO","PL","PT","RO","SK","SI","ES","SE",
"CH","GB"
];
if (!tcfCountries.includes(country)) return;
// MutationObserver to inject TCF
var observer = new MutationObserver(function(mutationsList) {
for (var i = 0; i < mutationsList.length; i++) {
var addedNodes = mutationsList[i].addedNodes;
for (var j = 0; j < addedNodes.length; j++) {
var node = addedNodes[j];
if (
node.tagName === 'SCRIPT' &&
node.src &&
node.src.indexOf('consent.cookiebot.com/uc.js') !== -1 &&
!node.hasAttribute('data-framework')
) {
node.setAttribute('data-framework', 'TCFv2.2');
console.log('✅ Injected data-framework="TCFv2.2" into uc.js script');
observer.disconnect();
}
}
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
})();
</script>Key points
Runs before Cookiebot CMP using the
geoDataReadyeventDoes nothing in non-TCF countries
Does not reload or modify Cookiebot after initialization
4. Setting up Custom Event Triggers
In order to fire the INJECT_TCF and the Cookiebot CMP tag itself in the right order, both needs to fire on custom events outlined in the COUNTRY_DATALAYER tag. Below is a basic run down of the sequence.
COUNTRY_DATALAYERfires first via the Consent Initialization - All Pages triggerINJECT_TCFfires ongeoDataReadyand only if the IP geo location (country) matches the countries set up to match the list of TCF required countries.Cookiebot CMP fires on
fireCookiebotas the last. This ensures thatgeoDataReadyis executed completely before Cookiebot is injected hence, thedata-framework="TCFv2.2is then injected in a timely manner.
GTM Trigger #1: TRIGGER_TCF
- Navigate to the Triggers section of GTM,
- Click New (located at the right site of the screen, next to the magnifying glass icon)
- Under Trigger Type, chose Custom Event
- Under Event Name, type in
geoDataReady - Choose All Custom Events under This trigger fires on
Save your changes. The result should look like the below
GTM Trigger #2: fireCookiebot
The second trigger is created to fire the Cookiebot CMP tag. Create the new trigger exactly the same way as the first, the only difference then being that under Event Name, you type in fireCookiebot instead of geoDataReady.
5. Putting everything together
We are almost done. All we need to do now is to update two triggers.
- Navigate to the main Tags section of GTM
- Open the
INJECT_TCFtag, and navigate below to Triggering - Under Firing Triggers, chose
TRIGGET_TCFand save the changes - Revert back to the Tags area and open the Cookiebot CMP tag
- Assign the
fireCookiebottrigger to our tag and save the changes.
⚠️ Note: Please make sure that the Enable IAB Transparency and Consent Framework toggle button is disabled in the Cookiebot CMP tag as this would otherwise defeat the purpose/goal of this article.
That's it. All you need to do is submit and publish your changes in Google Tag Manager and do a GTM Preview.
Final Result
✅ The user's geolocation is fetched
✅ The geolocation is then pushed to the dataLayer
✅ As a result, TCF is injected only where legally required
✅ TCF never loads unnecessarily
This setup has proven reliable in both GTM Preview and live production environments.
⚠️ IMPORTANT NOTE: In this setup, tags such as GA4 will load before Cookiebot CMP as a result of us using custom event triggers. It is therefore highly recommended to fire GA4 with the same trigger as used in the Cookiebot CMP tag (
fireCookiebot) in order to maintain the correct order. If GA4 fires earlier still, make sure its tag firing priority is set to a lower number than Cookiebot CMP.
Comments
0 comments
Article is closed for comments.