GDPR : Managing cookies in WordPress or Divi with tarteaucitron.js

7 Jun 2018

EDIT 11-25-2018 : Update for version 1.2 with alternate CDN loading and customization

 

Good morning everyone,

If you’re reading this post, it means you too have wondered, in the context of the GDPR, how you were going to easily manage authorization and prohibition of these damn cookies / trackers on your WordPress or Divi website…

Basically, I’m in favour of this kind of regulation, but it’s a happy mess technically (and legally).

By the way, I invite those who have missed this new european regulation in the last few weeks (or, like me, who didn’t know how to start with) to read this excellent article from the “marmite” on the General Data Protection Regulations (and WordPress). Very complete and very concrete, he pulled me out of the fog I had been wandering in for a while.

RGPD and cookies (or trackers)

In short, you must forbid the placement of cookies on your website or the setting up of tracers by certain services (such as Google Analytics for audience measurement or behaviour study, for example) until the visitor has expressed his consent to their use. The latter must also be able to choose individually each of the services to be prohibited/authorised.

The tarteaucitron script to the rescue

The “tarteaucitron” script is a GDPR-compliant open-source tag manager. It is very light and recommended and used by the CNIL (national french agency for data protection).

It allows not only to automatically position tags or markers associated with different services (audience measurement, social networks…), in the same way as Google Tag Manager, but also and especially to collect the explicit consent (or refusal) of the visitor for the use of these tags and associated cookies. Exactly what we need.

You can consult the tarteaucitron installation guide; I detail here the different steps for an easy and clean implementation in WordPress or Divi.

Files installation

New CDN alternate loading method : Do not download the tarteaucitron source code from GitHub.

We are just going to call the script on the CDN (Content Delivery Network). The pros of this approach:

  • faster,
  • lighter,
  • easy future updates,
  • optimization-friendly!

Declaration and script initialization

The following lines must be inserted before the </head> tag on each page of your website (this is for version 1.2, but you will have to get the new code for future updates).

You will notice that the script declaration is different from the installation guide because the script is not stored locally. An already minified version is called via the jsdelivr website which hosts the files on a CDN in order to serve them quickly around the world.

For future updates of the script, you will just need to correct the script call (first line) and the initialization that follows, whereas with the standard method it is also necessary to download the new version and install it.

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/AmauriC/tarteaucitron.js@V1.2/tarteaucitron.min.js"></script>
<script type="text/javascript">
  tarteaucitron.init({
    "privacyUrl": "https://pavenum.com/mentions-legales/", /* Privacy policy url */
    "hashtag": "#tarteaucitron", /* Open the panel with this hashtag */
    "cookieName": "tartaucitron", /* Cookie name */
    "orientation": "bottom", /* Banner position (top - bottom) */
    "showAlertSmall": true, /* Show the small banner on bottom right */
    "cookieslist": true, /* Show the cookie list */
    "adblocker": false, /* Show a Warning if an adblocker is detected */
    "AcceptAllCta" : true, /* Show the accept all button when highPrivacy on */
    "highPrivacy": false, /* Disable auto consent */
    "handleBrowserDNTRequest": false, /* If Do Not Track == 1, accept all */
    "removeCredit": false, /* Remove credit link */
    "moreInfoLink": true, /* Show more info link */
    //"cookieDomain": ".my-multisite-domaine.fr" /* Shared cookie for subdomain */
  });
</script>

Now, we are going to use the WordPress or Divi features to do this automatically.

Divi Version

With Divi, it is immediate because you can just copy/paste this block in the Integration tab on the Divi’s options page, in the <head> tag textarea:

tarteaucitron in Divi backend

Of course, you will have to activate the header code integration, according to the screenshot above.

General WordPress version

If the back-end of your theme does not allow you to insert code directly, then you must go through a child theme in order to properly inject the code into your HTML pages.

To do this, add the following lines to the functions.php file of your child theme:

function tarteaucitron_load() {
  wp_enqueue_script( 'tarteaucitron', 'https://cdn.jsdelivr.net/gh/AmauriC/tarteaucitron.js@V1.2/tarteaucitron.min.js' );
} 
add_action( 'wp_enqueue_scripts', 'tarteaucitron_load' );

function tarteaucitron_init() {
  ?><script type="text/javascript">
			tarteaucitron.init({
				"privacyUrl": "https://mon-site.com/mentions-legales/", /* Privacy policy url */
				"hashtag": "#tarteaucitron", /* Open the panel with this hashtag */
				"cookieName": "tartaucitron", /* Cookie name */
				"orientation": "bottom", /* Banner position (top - bottom) */
				"showAlertSmall": true, /* Show the small banner on bottom right */
				"cookieslist": true, /* Show the cookie list */
				"adblocker": false, /* Show a Warning if an adblocker is detected */
				"AcceptAllCta" : true, /* Show the accept all button when highPrivacy on */
				"highPrivacy": false, /* Disable auto consent */
				"handleBrowserDNTRequest": false, /* If Do Not Track == 1, accept all */
				"removeCredit": false, /* Remove credit link */
				"moreInfoLink": true, /* Show more info link */
			});
		</script><?php
}		
add_action('wp_head', 'tarteaucitron_init');

Note: There are also free plugins to insert code into WordPress generated HTML files, but I prefer minimal, lightweight and non-dependent solutions.

Adding services

Service activation is done in much the same way. It is essential for the script to work, since without service, there is no cookie or tracker to prohibit.

First, you need to get the necessary code snippets from the tarteaucitron installation guide (step 3). For example, for Google Analytics Universal:

Tarteaucitron et Analytics

This screenshot then tells us that:

  • the Analytics code must be placed at the end of each page of the site before the </body> tag,
  • the associated official marker, which you must have previously set for this service, must be removed.

Code to add:

<script type="text/javascript">
tarteaucitron.user.analyticsUa = 'UA-XXXXXXXX-X';
tarteaucitron.user.analyticsMore = function () { ga('set', 'anonymizeIp', true); };
(tarteaucitron.job = tarteaucitron.job || []).push('analytics');
</script>

Bonus: You will notice that I added an instruction to the analyticsMore() function to make Analytics a little less curious (anonymization of visitors’ IP address). Sadly it’s not enough to avoid GDPR…

Divi Version

Same procedure as before, but this time the code must replace the official marker in the area associated with the <body> tag, for each service used:

Tarteaucitron et Analytics

General WordPress version

Add these lines to your functions.php file:

add_action( 'wp_footer', 'tarteaucitron_services' );
function tarteaucitron_services() {
?><script>
        tarteaucitron.user.analyticsUa = 'UA-XXXXXXXX-X';
        tarteaucitron.user.analyticsMore = function () { ga('set', 'anonymizeIp', true); };
        (tarteaucitron.job = tarteaucitron.job || []).push('analytics');
</script><?php
}

Adding several services

If you use several services, you can paste all the associated bits of code, either in the Divi options, or in the same tarteaucitron_services() function for the child theme version (in the latter case it is not necessary to declare a function for each):

add_action( 'wp_footer', 'tarteaucitron_services' );
function tarteaucitron_services() {
  ?><script>
        tarteaucitron.user.analyticsUa = 'UA-XXXXXXXX-X';
        tarteaucitron.user.analyticsMore = function () { ga('set', 'anonymizeIp', true); };
        (tarteaucitron.job = tarteaucitron.job || []).push('analytics');
        (tarteaucitron.job = tarteaucitron.job || []).push('facebook');
        tarteaucitron.user.facebookpixelId = 'PIXEL-ID';
        tarteaucitron.user.facebookpixelMore = function () { /* add here your optionnal facebook pixel function */ };
        (tarteaucitron.job = tarteaucitron.job || []).push('facebookpixel');
        (tarteaucitron.job = tarteaucitron.job || []).push('gplus');
        ETC....................
  </script><?php
}

Tarteaucitron filtering

It is possible to disable tarteaucitron for connected users or on specific pages, for example, and therefore at the same time totally preventing the deposit of cookies for the declared services.

To do this, you will need to use the child theme method. For example, on this site I disable the script and Analytics for connected users using the conditional tag is_user_logged_in():

function pavenum_tarteaucitron_load() {
	if ( ! is_user_logged_in() )
		wp_enqueue_script( 'tarteaucitron', 'https://cdn.jsdelivr.net/gh/AmauriC/tarteaucitron.js@V1.2/tarteaucitron.min.js' );
} 
add_action( 'wp_enqueue_scripts', 'pavenum_tarteaucitron_load' );

function pavenum_tarteaucitron_init() {
	if ( ! is_user_logged_in() ) {
		?><script type="text/javascript">
			tarteaucitron.init({
				"privacyUrl": "https://pavenum.com/mentions-legales/", /* Privacy policy url */
				"hashtag": "#tarteaucitron", /* Open the panel with this hashtag */
				"cookieName": "tartaucitron", /* Cookie name */
				"orientation": "bottom", /* Banner position (top - bottom) */
				"showAlertSmall": true, /* Show the small banner on bottom right */
				"cookieslist": true, /* Show the cookie list */
				"adblocker": false, /* Show a Warning if an adblocker is detected */
				"AcceptAllCta" : true, /* Show the accept all button when highPrivacy on */
				"highPrivacy": false, /* Disable auto consent */
				"handleBrowserDNTRequest": false, /* If Do Not Track == 1, accept all */
				"removeCredit": false, /* Remove credit link */
				"moreInfoLink": true, /* Show more info link */
			});
		</script><?php
	}
}		
add_action('wp_head', 'pavenum_tarteaucitron_init');

function pavenum_add_tarteaucitron_analytics() {
	if ( ! is_user_logged_in() ) {
		?><script type="text/javascript">
			tarteaucitron.user.analyticsUa = 'UA-XXXXXXXX-X';
			tarteaucitron.user.analyticsMore = function () { ga('set', 'anonymizeIp', true); };
			(tarteaucitron.job = tarteaucitron.job || []).push('analytics');
		</script><?php
	}
}
add_action('wp_footer', 'pavenum_add_tarteaucitron_analytics');

Dialog box

Once consent has been given (or refused), a box is displayed at the bottom of the site, indicating the number of active cookies and allowing you to view the list and manage the consents.

Personally, I think it somewhat distorts the site and I prefer to display it only on the privacy policy page.

The following CSS allows you to hide it anywhere else (replace XXXX with the WordPress ID of your privacy page):

body:not(.page-id-XXXX) #tarteaucitronAlertSmall {
  display: none !important;
}

Design

To finish with the customization, here is my CSS associated with the general design of tarteaucitron:

/*******************************************************/
/* tarteaucitron */
/*******************************************************/

#tarteaucitronAlertBig #tarteaucitronPersonalize,
#tarteaucitronRoot #tarteaucitronPercentage,
#tarteaucitronAlertSmall #tarteaucitronManager #tarteaucitronDot #tarteaucitronDotGreen {
background: #E61071 !important;
}
#tarteaucitronAlertBig {
background-color: rgba(0,0,0,0.8) !important;
}
#tarteaucitronDisclaimerAlert, #tarteaucitronDisclaimerAlert strong, #tarteaucitronAlertBig #tarteaucitronPrivacyUrl {
color: #fff !important;
}
#tarteaucitronAlertSmall {
background-color: rgba(0,0,0,0.5) !important;
}
#tarteaucitronAlertBig #tarteaucitronPersonalize, #tarteaucitronAlertBig #tarteaucitronCloseAlert {
border-radius: 3px !important;
}

This harmonizes the banner and dialog box with the rest of the site. I leave it to you to adapt it, unless you want to add a little pink to your site!

Caching and optimization

The super bonus is that with the alternative script loading method, I no longer have any conflicts with code optimizers or cache systems 🙂

Indeed, with the local copy of the script, the latter made it impossible for the direct calls of the tarteaucitron.js sub-scripts (for example the initialization of translations) because they moved the optimized files to specific folders.

Note: You might object that with this method, scripts are not optimized… That’s right…. Even if I call a minified version of the main script on the CDN, this one calls non-minified versions of the secondary scripts. In addition, scripts are not combined.

But despite everything, I still have 100% on Pagespeed 😉

Besides, with the local installation method, optimization does not work and scripts must be excluded from the optimization tools! So no better!

Spoiler: The author of the plugin plans improvements in the loading and dependencies of the scripts…

Conclusion

Thanks to the work of Amauri Champeaux, who also provides this script for free for the most common services, cookies and trackers control is cake for WordPress and Divi.

(Background of the presentation image downloaded on Freepik.)