Here`s how WordPress GDPR cookie plugins should work

WordPress GDPR cookie plugin

As the most widely-used CMS in the world, WordPress powers a huge proportion of websites across the globe. If you use WordPress and need your website to be compliant with the European Union’s (EU) latest GDPR regulations, you will need to use some form of WordPress GDPR cookie plugin or an alternative commercial service. In this post, we will focus on WordPress GDPR cookie consent plugins, not commercial services that are designed to offer GDPR compliant solutions. Incidentally, it is worth noting that many such commercial services fail to work as intended unless you opt for a costly Enterprise package.

It’s no secret that the Internet has become increasingly annoying. It seems every website you visit prompts you to accept a cookie policy. This is true even if you access a website from outside an EU jurisdiction area, such as the US, Brazil, Singapore, Australia, or even a country in Europe but not in the EU.

Recently, we have been working on our own GDPR compliance and believe it or not, we struggled to find a plugin that worked the way we wanted. There were two crucial requirements we needed in a WordPress GDPR cookie consent plugin. These are as follows:

  1. Only display the cookie consent warning to visitors from the EU. We did not want to show a warning and risk annoying visitors from other areas of the world.
  2. We wanted to maintain full control over the plugin, including when or how to load resources once accepted or declined.

Although we tested a number of different WordPress GDPR cookie plugins, none of them had a cacheable IP to country lookup feature with a simple or full JavaScript control.

What is GDPR and can it really work as intended?

The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection and privacy for all individuals within the European Union (EU) and the European Economic Area (EEA). It also addresses the export of personal data outside the EU and EEA areas. The GDPR aims primarily to give control to citizens and residents over their personal data and to simplify the regulatory environment for international business by unifying the regulation within the EU…

GDPR does not only concern cookies, it regulates how organizations handle data in general. A major part of this is gaining consent and making how you process data as transparent as possible. For a website or internet service to be truly GDPR compliant, a high-end developer/s, lawyer or huge changes would be required to cover all the bases. In a world where anyone with minimal technical knowledge can set up a website using ‘drag & drop’ builders and one-click tasks, it is likely that true GDPR compliance will never be truly seen or correctly enforced.

We agree that visitors must have more information prior to disclosing their data, they must have control over its use, and they must have the ability to opt-out of data processing at any point in time but how website owners will make their websites GDPR compliant is a totally different question.

And finally, we should not annoy visitors outside from EU and almost all of the internet users don’t have clue what is HTTP cookie.

double GDPR cookie contest
1366×768 screen resolution with double GDPR cookie consent!

How we made our own ‘WordPress GDPR cookie plugin’

Rather than seeking out an existing WordPress GDPR cookie plugin and modifying this to our requirements, we decided to start from scratch. We already had knowledge of how to create a cacheable IP to country lookup service, so we simply needed an open source cookie consent code. We eventually found gdpr-cookie-notice and make a number of JavaScript changes. Our new version can be found on GitHub. In a nutshell, we needed three things from our cookie plugin. Here’s how we made them:

1. Create a cacheable IP to country lookup request.

Create a new PHP file in the root folder, /gdpr-location.php with following content:

<?PHP

$eu_iso = array("BE", "BG", "CZ","DK","DE","EE", "IE", "EL","ES","FR","HR", "IT", "CY","LV","LT","LU", "HU", "MT","NL","AT" ,"FR","HR", "IT", "PL","PT","RO","SI", "SK", "FI","SE","UK");

if (in_array($_SERVER["GEOIP_COUNTRY_CODE"], $eu_iso)) {
    $data = array(
        "gdpr" => true,
        "country_name" => $_SERVER["GEOIP_COUNTRY_NAME"],
        "country_code" => $_SERVER["GEOIP_COUNTRY_CODE"],
        "continent_code" => $_SERVER["GEOIP_CONTINENT_CODE"]
    );
    
} else {
    $data = array(
        "gdpr" => false
    );
}

header("Access-Control-Allow-Origin:*", true);
header('Content-Type: application/json', true);
header("Cache-Control:no-cache, must-revalidate, max-age=0", true);
header("robots:noindex", true);
header_remove("pragma");
echo json_encode($data);

The code above uses the built-in Litespeed GeoIP functionality and returns different JSON data depending on the user’s country. We then needed to make this request cacheable, otherwise, the end result will be inferior performance or as we like to say, the biggest WordPress performance mistake.

Here is an overview of how the caching should work:

  • If the request is starting with /gdpr-location.php, cache the request regardless of the HTTP method, query string or anything else AND;
  • If the visitor is not from the EU, cache the request as a single cache key for the rest of the world OR;
  • If the visitor is from the EU, cache the request based on the country two-letter ISO code.

So, we can have 31 different cached responses for each EU country and only one for the rest of the world. That’s 34 in total – perfect! Now it’s time to add caching rules in the .htaccess file, as shown below:

GeoIPEnable On
RewriteCond %{REQUEST_URI} ^/gdpr-location.php
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} !^(BE|BG|CZ|DK|DE|EE|IE|EL|ES|FR|HR|IT|CY|LV|LT|LU|HU|MT|NL|AT|FR|HR|IT|PL|PT|RO|SI|SK|FI|SE|UK)$
RewriteRule ^(.*)$ - [E=Cache-Control:max-age=86400, E=cache-key-mod:-qs:*, L]

RewriteCond %{REQUEST_URI} ^/gdpr-location.php
RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^(BE|BG|CZ|DK|DE|EE|IE|EL|ES|FR|HR|IT|CY|LV|LT|LU|HU|MT|NL|AT|FR|HR|IT|PL|PT|RO|SI|SK|FI|SE|UK)$
RewriteRule ^(.*)$ - [E=Cache-Control:vary=%{ENV:GEOIP_COUNTRY_CODE}, E=Cache-Control:max-age=86400,E=cache-key-mod:-qs:*, L]

Note: the above code and rewrite rules only work on a Litespeed web server with caching enabled and GeoIP support but the same can be made using Apache or Nginx web servers with GeoIP module and caching mechanism just as other WordPress caching plugins works.

2. Add our GDPR cookie plugin JavaScript and CSS files into WordPress.

Next, you need to find a way to include two JavaScript files and one stylesheet file into your WordPress setup. Since we are using a WordPress child theme, we achieved this by adding simple code in the functions.php file, although you could use a plugin for this purpose.

function closte_gdpr_scripts() {
wp_enqueue_script('closte_gdpr_plugin','/wp-content/closte/gdpr/gdpr-plugin.js','','',true);
wp_enqueue_script('closte_gdpr','/wp-content/closte/gdpr/gdpr.js','','',true);
wp_enqueue_style('closte_gdpr_style','/wp-content/closte/gdpr/gdpr-style.css',false, '1.0', 'all');
}
add_action( 'wp_print_scripts', 'closte_gdpr_scripts' );

The gdpr.js file is the most important and you need to modify a few parameters:

  • Domain: If you run the same cookie notice on all subdomains, define the main domain starting with a dot.
  • Statement: the URL to the website’s Privacy Policy.
  • Performance, Analytics & Marketing: Cookie names are separated into 3 categories.

Please note: only add the cookies under your domain. You cannot remove a cookie from an external domain (e.g. Facebook). However, there are methods to control this (please see the implementation section).

//gdpr.js content
jQuery(window).load(function() {

    jQuery.get("/gdpr-location.php", function(data) {

        if (data.gdpr) {
            //Visitor from European Union

            //show the gdpr notification
            gdprCookieNotice({
                locale: 'en', //This is the default value
                timeout: 500, //Time until the cookie bar appears
                expiration: 365, //This is the default value, in days
                domain: '.closte.com', //If you run the same cookie notice on all subdomains, define the main domain starting with a .
                implicit: true, //Accept cookies on scroll
                statement: 'https://closte.com/legal/privacy-policy', //Link to your cookie statement page
                performance: [], //Cookies in the performance category.
                analytics: ['_ga', '_gid', '_gat'], //Cookies in the analytics category.
                marketing: [] //Cookies in the marketing category.
            });

        } else {
            //visitor outside EU, load everything
            var value = {
                performance: true,
                analytics: true,
                marketing: true
            };
            var event = new CustomEvent("gdprCookiesEnabled", {
                detail: value
            });
            document.dispatchEvent(event);
        }
    });

});

In addition, also be aware that you may need to modify some CSS styles to ensure consistency with your website design.

3. Technical implementation of our GDPR cookie plugin.

At this point, we have nearly everything set up, except the most important step. Many WordPress users think that by simply installing a WordPress GDPR cookie plugin, they automatically become compliant. This is completely incorrect!

Here are the major aspects that you need to consider:

  • Do not load any resource (except the essential one) before the user accepts or declines to load cookies. If the visitor is outside of the EU, do not display the cookie consent alert and load all resources.
  • If the visitor is within the EU, once accepted, load all resources OR;
  • Once declined, either load no resources or only the categories accepted.

You will need to wrap any external services JavaScript codes within a simple code. Below is how we made our Google Analytics and Facebook Pixel JavaScript:

<script>
document.addEventListener('gdprCookiesEnabled', function(e) {

    if (e.detail.marketing) {
        //paste Facebook Pixel code or another marketing scripts
    }

    if (e.detail.analytics) {
        // paste Google Analytics code or similar services
    }
});
</script>

You may have a question: But where to do this? The answer is, there where you have made a copy/paste of Google Analytics, Facebook Ads or other scripts. In our case, we utilized the Flatsome theme FOOTER SCRIPTS option.

Finally, you can test the implementation using the Google Chrome Developer Tools -> Inspect and Delete Cookies with all 4 scenarios (first visit, accept all, accept only one category, decline all).

Conclusion

In this article, we have explored just one example of how a WordPress GDPR cookie plugin can be made and it is important to consider visitors outside of the EU who may find cookie consent alerts irritating. This is why in our example, we include the feature to display the cookie consent only to visitors from the EU.

While this is a functional example, there is room to expand the plugin even further. For example, one improvement could be to show the cookie consent modal in the German language for only German visitors. Despite this, the plugin is a solid and functional solution. Of course, you will require some basic knowledge of JavaScript, CSS, and PHP, but we hope our examples are fairly clear and easy to understand.

In summary, you have 3 possible options for how to use a WordPress GDPR cookie plugin:

  1. Keep using your current cookie plugin and annoy the world.
  2. Try to make what we made.
  3. Use a commercial service for this purpose. But take note! These services tend to cost at least $10 per month, and many do not even have the IP lookup functionality unless you buy an “Enterprise” plan.

And finally, we are considering making huge modifications to our cookie consent code as well as making a generic design with one single goal: Make a GDPR consent tab in our WordPress plugin. If anyone wants to collaborate with us, especially in terms of the HTML/CSS modifications, please get in touch.