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.

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.

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.

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:

  1. Initialize dataLayer and gtag Function: Prepares GTM’s data layer for tracking events and variables.
  2. Retrieve User Consent: Checks localStorage for any previously stored consent preferences.
  3. 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) -->

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:

  1. Accept All Cookies: Grants consent for all cookie categories.
  2. Customize: Opens a modal for users to select specific cookie preferences.
  3. Reject All Cookies: Denies consent for all optional cookie categories.

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:

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:

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).

Choose the consent types required for the tag to fire (e.g., analytics_storage for Google Analytics).

Example for Google Analytics Tag:

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:

Step 8: Test Your Implementation

After setting up, thoroughly test to ensure compliance:

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.