Set Up A GDPR Cookie Consent Form Using Google Tag Manager

Ian Lurie

NOTE: This is not legal advice. We are not lawyers. It’s also not the only thing you’ll need to do to reach GDPR compliance for your business. Cookie consent is only one portion of GDPR compliance. Please consult legal counsel before implementing this solution.

Another note: This solution works for cookies fired from inside the GTM container. It won’t prevent cookie placement for those placed outside the container.

We’ve already provided some GDPR basics for marketers. This post gets a lot more tactical.

Under the General Data Protection Regulation (GDPR), the ideal cookie consent form will:

  1. Detect your location and see whether you’re in the EU
  2. Based on your location, display the cookie consent (or not)
  3. Request cookie consent
  4. If you consent, place analytics cookies as usual
  5. By default, let you browse the site, but turn off analytics cookies, providing a seamless user experience
  6. Oh, and since you have about 48 hours (GDPR goes into effect May 25th), require as little developer time as possible.

Ask, and ye shall receive: This step-by-step uses Google Tag Manager (GTM) to create a cookie consent banner that pops up at the bottom of your site only for EU visitors. The banner asks visitors to opt-in. If they don’t, they can still browse the site, but GTM will not fire cookies that require consent.

To set this up, you need to understand GTM and GTM configuration. When you’re done, you’ll get something like this:

gdpr-blog-1

See? A lovely cookie consent banner

 

Step 1: Sign up for an ipinfo.io account

First, you need a way to identify visitors from the European Union. IP Info provides an API to do just that.

gdpr-blog-2

IP Info lets you detect EU visitors

It’s free for up to 1,000 requests/day. We get more traffic than that, so we’re paying $100/month for up to 40K requests/day. Not bad.

After signup you get an API token:

gdpr-blog-2B

Your IP Info API token. Write it down!

Copy that and hang on to it for later.

Step 2: Generate a cookie consent banner at Cookie Consent by Insites

At Cookie Consent by Insites, you can generate a Cookie Consent banner that matches the look and feel of your site.

gdpr-blog-4

A banner, courtesy of Cookie Consent by Insites

Link it to your privacy policy and choose the “opt-in” method under “Compliance Type.”

gdpr-blog-4B

Set opt-in compliance

Once you have configured and styled your banner, copy the code in the box on the right-hand side and hang on to it for later.

Step 3: Configure Google Tag Manager

For this step, we’re assuming you know a bit about GTM variables, triggers, and tags work. This is where the rubber meets the road. If you aren’t sure what this all means, stop. Get your analytics nerd to help out.

Set up country lookup

Set up a Custom HTML tag with a JavaScript that will query the IP Info API and return the visitor’s Country Code.

Country Lookup Custom Tag
gdpr-blog-3-2560x1415-2

Country Lookup Custom Tag

Use this code:

<script type="application/javascript">
  function callback(json) {
    dataLayer.push({'event': 'ipEvent', 'ipCountry': json.country});	
  }
</script>
<script type="application/javascript" src="https://ipinfo.io/?token=YOUR-TOKEN-GOES-HERE&callback=callback"></script>

Replace the YOUR-TOKEN-GOES-HERE portion with your IP Info API Token you set aside from Step 1.

Then create a data layer variable to pull the value of that Country Code.

Data layer pulls country code
gdpr-blog-5-2

Data layer pulls country code

Once the Country Code is available in the data layer, use a Lookup Table variable to look for each of the EU Alpha-2 Country Codes and return a “Yes” if they are in the EU and a “No” for all other Country Codes.

Lookup Table variable
gdpr-blog-5b-2

Lookup Table variable

That will inform a trigger called “IP Event – EU” which will show/hide the Cookie Consent banner based on location.

Show the cookie consent banner?
gdpr-blog-5c-2

Show the cookie consent banner?

Add the cookie consent banner

Next, take your script from Step 2 and create a Custom HTML tag to fire that when the “IP Event – EU” trigger meets its criteria.

gdpr-blog-5d-2

Custom HTML tag to fire criteria

If the visitor accepts, the banner sets a first-party cookie. Otherwise, no cookies for them.

Set a first-party cookie upon accept
gdpr-blog-5d2-2

Set a first-party cookie upon accept

We’ll also need a trigger that verifies the corresponding cookie values if the visitor accepts.

Verify cookie is in place
gdpr-blog-5e-2

Verify cookie is in place

Once that trigger executes, we send a data layer event and trigger.

GTM data layer event and trigger
gdpr-blog-5f-2

GTM data layer event and trigger

Data layer event and trigger
gdpr-blog-5g-2

Data layer event and trigger

Here’s example code for that data layer event.

<script>
dataLayer.push({'event': 'cookieConsent'});
</script>

The “cookieConsent” Custom Event then becomes the trigger that you use to fire all tags for EU visitors.

Non-EU Visitors

Make sure this doesn’t impact any tracking you’re doing for non-EU visitors: Delay your tags to fire on Window Loaded (not Pageview), and ensure your “In The EU” variable equals “No.” That way, the Country Code process has a chance to run.

gdpr-blog-6

Make sure tracking works for non-EU visitors

Quality Assurance

Test! Test! Test! Test on staging or in Google Tag Manager’s preview mode:

Testing the GTM implementation
gdpr-blog-6-2

Turning on GTM preview mode

Next, you’ll want to find a proxy service that allows you to view the preview mode URL from a server in the EU. We used Hide Me, a service that has options to proxy from Holland or Germany.

gdpr-blog-7

Hide Me

Be sure you test this on a mobile device and in every possible form factor. We didn’t, and our social share ribbon overlapped with the consent button. Luckily @_sebastiansimon was on the case and let us know. We’re fixing it as I write this.

Done! And A Question

That’s it! You now have a low-code cookie consent form in place.

We did grapple with one question, and we’d love your opinion: Should we display the cookie consent for everyone, regardless of location? That way if someone from the EU is, say, traveling in Canada, the would still see the form? We don’t want to litter our site with forms. We don’t want to get fined a few million Euros, either. GTM exceptions are a solution to respect cookie exceptions when needed.

Questions or comments? Leave them below.

Start call to action

See how Portent can help you own your piece of the web.

End call to action
0

Comments

  1. Great article and very useful information. My question is: If the EU can not load cookies before consent, why does nobody (or almost nobody) do it? On your page I see that the cookies have been loaded before my consent. I am doing it in the places I do but I feel a little “silly”, or is there something that escapes me?
    Thanks in any case for your method, it is an alternative but I would prefer to continue using a lightweight plugin since calls to Google affect performance.

    1. Hi, Santiago. Thanks for reading!
      It’s important to note that all this solution does is block the cookies that are generated via GTM tags. It is not the only step in becoming GDPR compliant. But it is a very important one, as most folks send data off to the third-party platforms via tag management solutions.
      Do you have a lightweight plugin you prefer for this task? The trouble with plugins, in my experience, is there’s always a risk of them getting outdated and/or not playing nice with new versions of WordPress, etc. Still would love to hear about it, if you have one you like.
      Cheers!

      1. Thanks for your reply! so I’m confused is because the most usual thing in websites around the net (even in the EU) is to load the cookies BEFORE the consent. That’s why I asked you why you have not implemented it. Is it or is it not mandatory to wait to load the cookies until you receive the express consent of the user of the website?
        Regarding the plugins, I am very careful with their choice and their maintenance. Cookie Notice by Dfactory is for me the best option, do not affects performance, GDPR compliant and includes a very useful feature to not load the scripts you want until you receive the consent.
        Thanks a lot for your time and insights!

        1. GDPR requires opt-in for all cookies, whereas most cookie notices prior to the EU were opt-out.
          In our situation, some cookies load by virtue of scripts hosted outside of Google Tag Manager. The plugin solution would definitely help there, so thanks for the tip!
          But this article addresses delaying the firing of any/all tags within GTM that would generate cookies until opt-in occurs.

  2. Hi Michael,
    I run an IP Geolocation API – ipdata.co – that explicitly returns an is_eu field, telling you if the user is in the EU.
    This would make your lookup logic much easier.

    1. Thanks for the tip, Jonathan. There are a lot of IP lookup solutions out there that do slightly different things beyond just the country code and I’m sure our readers appreciate having options to choose one that’s right for them.

  3. I believe there might be several issues with this solution, so I thought I would drop my 5 cents. Some of the potential problems I see are:
    1. GDPR applies to EU citizens, not users browsing from EU. IP address will only identify the device and its current location. You might still reach EU citizen while he’s visiting any other region.
    2. This cookie consent would only be proper for anonymous web tracking. If you want to track PIIs or connect later on visitor data to some identifier, you will likely need more granular permission model.
    3. Storing consent on user’s device might not be the best solution. After all it is mostly supposed to help you in legal processing of data. I believe because of that it would be best recorded in your own database. Cookies can be erased instantly, leaving no trace of user consent.
    Wish all fun with compliance 😉 I don’t believe that 100% compliance is possible anyway.

    1. Good points on all fronts. We’re definitely not billing this as a comprehensive solution for 100% compliance, but as a step toward compliance in good faith. I’d encourage folks to iterate on this method to fit the needs of their business.
      One way to get around the scenario you mentioned in point 3 is to also send in the consent cookie value when given into GA as a user-scoped Custom Dimension.

  4. GDPR is for all european visitors worldwide! European visitors who are not in EU can not consent with your solution. IP checking is not the soluce! I don’t know how to do with eu visitors who lives in America or Africa or Asia….

    1. You can show the consent banner to all visitors as an alternative for the cases you mention.
      The IP lookup is a way to mitigate some potential data loss from other non-EU locations.

  5. Hi Michael/Ian,
    Why do you inject the datalayer variable and base your other tags on this trigger?
    Can’t you just you use the “Cookie consent | Allow or dismiss” trigger you created one step before?
    It seems to me that you’re doing a few steps more that are non required.

    1. The Data Layer Variable is a redundancy to differentiate the consent event from other gtm.click events in the Preview Mode.
      You can forgo this step if you like.
      Thanks for reading!

  6. This is really informative & knowledge full article but i have a question. If the EU can not load cookies before consent, why does nobody do it?

    1. Honestly, I think there’s been inconsistent application and enforcement of the law in the EU and larger companies would rather contest it in court than lose precious customer data.

  7. I am struggling like hell as I cannot go beyond the trigger “cookie consent – allow or dismiss”. Somehow the conditions are not working for me. The click field is “Allow cookies” and I also tried click classes contains “cc-allow”.

    click classes= Data Layer Variable string ‘cc-btn cc-allow’
    click text = Auto-Event Variable string ‘Allow cookies’
    cookie consent = 1st Party Cookie undefined undefined

    1. Hi Alfred,

      I’ll email you around troubleshooting this, as it’s hard to know what’s wrong unless we have Edit access to your container.

      Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

Close search overlay