Implementing Google Tag Manager with GDPR Compliance
Implementing Google Tag Manager with GDPR Compliance
Ensuring user privacy while collecting valuable analytics data is crucial in today’s regulatory environment. This guide focuses on how to correctly set up and configure variables in Google Tag Manager (GTM) to make your website GDPR compliant.
Understanding GDPR and Consent Management
The General Data Protection Regulation (GDPR) requires organizations to protect the personal data and privacy of EU citizens. When using GTM, it’s essential to handle user data responsibly and obtain explicit consent before tracking. Proper variable configuration ensures that tracking scripts execute only after users have granted the necessary permissions.
Setting Up Consent Variables
Correctly configuring consent variables is the cornerstone of GDPR compliance in GTM. These variables control how and when tracking scripts execute based on user consent.
Step 1: Initialize the Data Layer and Set Default Consent State
In your website’s <head>
section, include the following script:
<script defer>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
const cookieConsent = localStorage.getItem('cookiesConsent');
gtag('consent', 'default', cookieConsent ? JSON.parse(cookieConsent) : {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied',
'personalization_storage': 'denied',
'functionality_storage': 'denied',
'security_storage': 'granted'
});
</script>
Explanation:
- Initialize dataLayer and gtag Function: Prepares GTM’s data layer for tracking events and variables.
- Retrieve User Consent: Checks localStorage for any previously stored consent preferences.
- Set Default Consent: If no consent is found, sets all optional storage types to ‘denied’ except ‘security_storage’, which is set to ‘granted’.
Step 2: Include Google Tag Manager Scripts
Add the GTM script immediately after the script above:
<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || []; w[l].push({
'gtm.start': new Date().getTime(), event: 'gtm.js'
}); var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true; j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-PXXXXXXX');
</script>
<!-- End Google Tag Manager -->
Note: Replace
'GTM-PXXXXXXX'
with your actual GTM container ID.
Also, add the following <noscript>
tag immediately after the opening <body>
tag on every page:
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
Step 3: Implement the Consent Banner
Create a consent banner that allows users to accept, reject, or customize their cookie preferences. Here’s an example of how to set it up:
<!-- Consent Banner -->
<div id="consent-banner" class="fixed bottom-0 left-0 w-full max-w-screen-lg mx-auto text-white text-sm p-3 flex flex-wrap justify-between items-center shadow-lg z-50 hidden" style="position: fixed !important; bottom: 0 !important; z-index: 9999 !important; background-color: rgba(31, 41, 55, 1) !important; max-height: 20%; overflow: hidden;">
<div class="consent-text">
<!-- Your consent message and privacy policy link here -->
</div>
<div class="button-container flex space-x-1">
<button id="acceptAllCookies" class="px-5 py-2 bg-primary-600 text-white rounded-lg hover:bg-indigo-800">Accept All</button>
<button id="customizeConsent" class="px-5 py-2 bg-gray-900 text-white rounded-lg hover:bg-indigo-800">Customize</button>
<button id="rejectCookies" class="px-5 py-2 bg-gray-900 text-white rounded-lg hover:bg-indigo-800">Reject All</button>
</div>
</div>
Explanation:
- Accept All Cookies: Grants consent for all cookie categories.
- Customize: Opens a modal for users to select specific cookie preferences.
- Reject All Cookies: Denies consent for all optional cookie categories.
Step 4: Implement the Consent Modal
The consent modal allows users to customize their cookie preferences:
<!-- Consent Modal -->
<div id="consent-customization" class="modal-hidden fixed inset-0 z-50 flex items-center justify-center bg-gray-800 bg-opacity-75 p-4 sm:p-6">
<div class="bg-white p-6 rounded-lg shadow-lg max-w-md w-full">
<h3 class="text-lg font-bold mb-4">Customize Preferences</h3>
<form id="consent-form">
<!-- Necessary Cookies (Always Enabled) -->
<!-- Preferences Cookies -->
<!-- Statistics Cookies -->
<!-- Marketing Cookies -->
<!-- Add toggle switches and descriptions for each category -->
<!-- Modal Buttons -->
<div class="modal-buttons-container flex justify-end space-x-1">
<button id="saveConsent" class="px-5 py-2 bg-primary-600 text-white rounded-lg hover:bg-indigo-800">Save Preferences</button>
<button id="cancelConsent" class="px-5 py-2 bg-primary-500 text-white rounded-lg hover:bg-indigo-800">Cancel</button>
</div>
</form>
</div>
</div>
Explanation:
- Necessary Cookies: Essential for website functionality; always enabled and cannot be turned off.
- Preferences Cookies: Remember user settings and preferences.
- Statistics Cookies: Collect anonymous data for analytics.
- Marketing Cookies: Used for advertising and personalization.
Step 5: Handle User Consent Preferences with JavaScript
Add the following script to manage user interactions and update consent variables:
<script>
document.addEventListener('DOMContentLoaded', function () {
const consentStatus = localStorage.getItem('cookiesConsent');
// Show the banner if no consent has been given yet
if (!consentStatus) {
document.getElementById('consent-banner').classList.remove('hidden');
}
// Function to set consent and update GTM
function setConsent(adStorage, analyticsStorage, adUserData, adPersonalization, personalizationStorage) {
const consentData = {
'ad_storage': adStorage,
'analytics_storage': analyticsStorage,
'ad_user_data': adUserData,
'ad_personalization': adPersonalization,
'personalization_storage': personalizationStorage,
'functionality_storage': personalizationStorage,
'security_storage': 'granted'
};
localStorage.setItem('cookiesConsent', JSON.stringify(consentData));
gtag('consent', 'update', consentData);
// Hide the banner and modal
document.getElementById('consent-banner').classList.add('hidden');
document.getElementById('consent-customization').classList.add('modal-hidden');
}
// Accept All Cookies
document.getElementById('acceptAllCookies').addEventListener('click', function() {
setConsent('granted', 'granted', 'granted', 'granted', 'granted');
});
// Reject All Cookies
document.getElementById('rejectCookies').addEventListener('click', function() {
setConsent('denied', 'denied', 'denied', 'denied', 'denied');
});
// Customize Cookies
document.getElementById('customizeConsent').addEventListener('click', function() {
document.getElementById('consent-customization').classList.remove('modal-hidden');
});
// Save Custom Preferences
document.getElementById('saveConsent').addEventListener('click', function(event) {
event.preventDefault();
const analyticsConsent = document.getElementById('statisticsCookies').checked ? 'granted' : 'denied';
const marketingConsent = document.getElementById('marketingCookies').checked ? 'granted' : 'denied';
const personalizationConsent = document.getElementById('preferencesCookies').checked ? 'granted' : 'denied';
setConsent(marketingConsent, analyticsConsent, marketingConsent, marketingConsent, personalizationConsent);
});
// Cancel Button
document.getElementById('cancelConsent').addEventListener('click', function(event) {
event.preventDefault();
document.getElementById('consent-customization').classList.add('modal-hidden');
});
});
</script>
Explanation:
- setConsent Function: Updates consent variables based on user choices and stores them in localStorage.
- Event Listeners: Handle user interactions with the consent banner and modal.
- Updating GTM: Uses
gtag('consent', 'update', consentData);
to inform GTM of the current consent status.
Step 6: Configure GTM Tags to Respect Consent
Within GTM, ensure that all tags are set to fire based on the user’s consent preferences:
Access Tag Settings:
In GTM, go to Tags and select a tag (e.g., Google Analytics).
Enable Consent Checks:
- Under Tag Configuration, click on Advanced Settings.
- Enable Consent Settings by toggling Require Consent to “true”.
Specify Consent Types:
Choose the consent types required for the tag to fire (e.g., analytics_storage
for Google Analytics).
Example for Google Analytics Tag:
- Consent Types: Require
analytics_storage
to be ‘granted’. - Outcome: The tag fires only if the user has consented to analytics cookies.
Step 7: Styling the Consent Banner and Modal
Add CSS to style the consent banner and modal for better user experience:
<style>
/* Styling for the consent banner, modal, switches, and buttons */
</style>
Include Styles for:
- Toggle Switches: Visual representation of on/off states for cookie categories.
- Buttons: Consistent styling for accept, reject, save, and cancel buttons.
- Responsive Design: Ensure the banner and modal are mobile-friendly.
Step 8: Test Your Implementation
After setting up, thoroughly test to ensure compliance:
- Initial Visit: Verify that the consent banner appears for new users.
- Consent Choices: Check that the user’s selections are stored and retrieved correctly.
- Tag Firing: Use GTM’s Preview mode or browser developer tools to confirm that tags fire only after the appropriate consent is given.
- Local Storage: Inspect
localStorage
to see if consent preferences are correctly saved.
Conclusion
By focusing on correctly setting consent variables and configuring your GTM tags to respect user preferences, you ensure GDPR compliance while still collecting valuable analytics data. This approach not only meets regulatory requirements but also builds trust with your users by respecting their privacy choices.
If you need assistance with GDPR compliance or GTM setup, feel free to contact us.