Comment utiliser Google Analytics en conformité au RGPD

La communication de la CNIL relative à Google Analytics a suscité un tollé général en raison de sa prise de position. Après 24h d’analyse intense et de discussions avec de nombreux experts en matière de protection des données personnelles, après avoir contacté Google pour avoir les détails juridiques et techniques sur les solutions possibles, je suis heureux de vous proposer une solution opérationnelle (et gratuite) qui vous permettra d’utiliser Google Analytics en conformité avec le RGPD.

Précisions que le sujet est hautement complexe, donc pas à l’abri de nouvelles surprises ; on rappellera donc en premier le problème de fond, et les différents des points évoqués à la fois par la CNIL et également par Google (I), avant de livrer une solution opérationnelle pour utiliser Analytics (II).

I - Le problème juridique posé par Google Analytics

Google analytics pose plusieurs problèmes d’un point de vue du RGPD, la CNIL en ayant soulevé un majeur qui est relatif aux transferts de données personnelles hors de l’Union européenne (A) ; cependant la réalité est que l’on peut parfaitement éviter ces transferts au travers des outils mis en place par Google (B).

A - Par défaut des données personnelles sont transférées aux Etats-Unis

Le premier point à déterminer est de savoir si l’utilisation de Google analytics va générer un traitement de données personnelles au sens du RGPD. Pourquoi ? Parce que c’est cela qui va déterminer l’application du RGPD. Et à défaut, les gestionnaires de site web n’auront aucune obligation à ce sujet. L’enjeu de qualification juridique est donc très important.

À ce titre, il est donc essentiel de déterminer précisément quelles sont les données qui sont collectées et traitées avec Analytics et si celles-ci relèvent de la notion de donnée personnelle au sens de l’article 2 du RGPD.

Commençons notre investigation par les Conditions Générales d’Utilisation de Google Analytics.

1) Google interdit les données personnelles dans GA

Le premier élément que l’on doit analyser est le contrat de Google analytics (les Terms of Service - TOS ou CGV en français). Celui-ci indique en effet très clairement qu’il est interdit d’ajouter quelque données personnelles que ce soit dans Google analytics :

  1. Privacy. You will not and will not assist or permit any third party to, pass information to Google that Google could use or recognise as personally identifiable information.

Au moins les choses sont claires ! L’objectif de cette clause est évidemment de tenter d’écarter l’application du RGPD. En effet, à défaut de données personnelles traitées, le RGPD ne trouve pas à s’appliquer et les webmasters utilisant Analytics n’auraient aucune obligation à ce titre (pour rappel le champ d’application du RGPD est défini dans l’article 2 et les notions de données à caractère personnelles sont définies dans l’article 4, donc les choses sont assez claires de ce côté, voir notre article initial sur Google analytics publié en 2018 sur ces points).

La mise en garde de Google vaut en particulier pour deux éléments qui sont importants :

  1. des urls contenant des données personnelles - qui vont être ajoutées dans Analytics - par exemple www.site.fr/jean-dupont - dès lors qu’elles seront consultées ;
  2. ou la transmission volontaire d’userID ou de données permettant d’identifier des personnes par le webmaster lui-même à Analytics (exemple : l’enregistrement d’un évènement dans Analytics, comme d’un achat, en ajoutant l’email d’une personne ou son userId)

Si l’on évacue ces deux cas spécifiques, on pourrait se dire que l’usage d’Analytics ne va pas générer de traitement de données personnelles.

Mais en réalité, c’est essentiellement l’adresse IP des visiteurs qui va poser problème.

2) Toutefois l’IP d’un visiteur sera traitée par Google

Si le webmaster ne transmet aucune donnée personnelle à Google, il n’en reste pas moins que la requête web permettant d’enregistre un évènement dans Anlytics - comme la visite d’une page web - va elle-même engendrer un traitement de données personnelles en cela qu’elle va imposer le traitement de l’adresse IP du visiteur.

C’est là ou les choses se compliquent substantiellement, car et cet acte de transmission avec l’adresse IP du visiteur qui va générer l’essentiel du problème soulevé par la CNIL.

Avant de détailler le problème (et sa solution), il nous faut toutefois attaquer une seconde question : qui est responsable du traitement, et comment se positionne Google par rapport au traitement de cette donnée côté RGPD ?

Pourquoi cette notion est essentielle ? Simplement parce que si Google est responsable de traitement - et ne fait que fournir des données agrégées aux webmasters, alors ces derniers n’auront aucune obligation côté RGPD. En effet, ceux-ci ne disposeront d’aucune donnée personnelle, Google ne leur fournissant que des statistiques ne permettant jamais l’identification d’une personne. C’est le point que j’avais soulevé dans l’article initial concernant la communication de la CNIL.

J’ai donc pris la précaution de contacter Google à ce sujet afin d’avoir leur vision sur la chose (les contrats de Google sont assez très difficiles à lire en raison du volume très important de documents), et leur réponse a été extrêmement rapide et tout à fait bienvenue !

La voici en détail :

L’architecture RT/ST est donc déterminée précisément dans les “Data protection Termes : Service information” que voici :

On voit que la question a donc été mûrement réfléchie par les équipes de Google qui précisent ici que l’entreprise agit en tant que sous-traitant pour les services fournis au travers de Google Analytics. Le contrat précise également le type de données personnelles traitées au travers du service, ce qui va nous être très utile dans notre analyse :

Types of personal data In relation to the Google Ads Data Processing Terms, Customer Personal Data may include the following types of personal data (as applicable, depending on the Processor Services provided under the Agreement). Google Analytics Online identifiers, including cookie identifiers, internet protocol addresses and device identifiers; client identifiers

Nous avons donc 3 types de données personnelles traitées au travers de ce service :

  • les cookies - en cela qu’ils permettent d’identifier une personne physique (on écarte la question du consentement qui est requis par la directive 2002/58 - e-privacy)
  • l’adresse IP de l’utilisateur
  • l’identifiant client (le userId qui est généré par Analytics et qui permettra de suivre un utilisateur au travers de son parcourt web)

Donc Analytics génère bien un traitement de données personnelles qui va engendrer l’application du RGPD. Le problème tient alors que ces données personnelles seront ensuite transférées aux États-Unis.

3) Cette IP traitée sera transférée aux États-Unis

Le problème principal soulevé par la CNIL est qu’elle relève que l’adresse IP du visiteur - dans l’affaire spécifique qu’elle mentionnait - sera transférée aux États-Unis ; or cela est très strictement régi par le RGPD.

La communication de la CNIL ne mentionait le mécanisme du Privacy Shield, en laissant entendre in fine qu’il n’existe aucune solution pour utiliser Google Analytics en conformité avec le RGPD - ce qui est en réalité totalement faux.

En effet, si le Privacy Shield a été réellement mis à mal par l’arrêt Scrhems II, il reste plusieurs mécanismes tout à fait effectifs qui permettent de transférer des données personnelles hors de l’UE, dont un qui est “les clauses contractuelles types de protection”. Et cet élément est tout à fait essentiel.

Revenons toutefois sur le problème posé par l’arrêt Schrems II : dans cette décision la CJUE jugeait que le mécanisme de Privacy Shield devait être invalidé, car il ne permettait pas d’assurer un niveau de protection suffisant aux données personnelles transférées aux États-Unis. La raison étant que les services de renseignement US pouvaient avoir accès aux données personnelles sans garanties réelles pour les personnes concernées quant à l’utilisation de ces données.

Toutefois, cette annulation ne concerne pas les clauses contractuelles types ! Pourquoi ? Parce que le responsable du traitement qui a recourt à ces clauses peut parfaitement adopter des mesures supplémentaires spécifiques destinées à assurer la protection des données personnelles transférées. Et donc supprimer le risque pour les personnes concernées au regard du transfert.

En cela, le responsable du traitement conserve la maîtrise - ainsi que la responsabilité - d’assurer un niveau de protection effectif aux données personnelles. L’essentiel du point de vue du RGPD est que les données personnelles disposent d’un niveau effectif de protection qui soit identique au niveau existant à l’intérieur de l’UE. Au responsable de traitement de se débrouiller lui-même pour trouver une solution.

Reprenons en détail la décision de la CJUE :

132 Dès lors que, comme il ressort du point 125 du présent arrêt, il est inhérent au caractère contractuel des clauses types de protection des données que celles-ci ne sauraient lier les autorités publiques des pays tiers, mais que l’article 44, l’article 46, paragraphe 1, et l’article 46, paragraphe 2, sous c), du RGPD, interprétés à la lumière des articles 7, 8 et 47 de la Charte, exigent que le niveau de protection des personnes physiques garanti par ce règlement ne soit pas compromis, il peut s’avérer nécessaire de compléter les garanties que contiennent ces clauses types de protection des données. À cet égard, le considérant 109 dudit règlement énonce que « [l]a possibilité qu’ont les responsables du traitement [...] de recourir à des clauses types de protection des données adoptées par la Commission [...] ne devrait pas les empêcher [...] d’y ajouter d’autres clauses ou des garanties supplémentaires » et précise, en particulier, que ceux-ci « devraient être encouragés à fournir des garanties supplémentaires [...] qui viendraient compléter les clauses types de protection [des données] » 133 Il apparaît ainsi que les clauses types de protection des données adoptées par la Commission au titre de l’article 46, paragraphe 2, sous c), du même règlement visent uniquement à fournir aux responsables du traitement ou à leurs sous-traitants établis dans l’Union des garanties contractuelles s’appliquant de manière uniforme dans tous les pays tiers et, dès lors, indépendamment du niveau de protection garanti dans chacun d’entre eux. Dans la mesure où ces clauses types de protection des données ne peuvent, eu égard à leur nature, fournir des garanties allant au-delà d’une obligation contractuelle de veiller à ce que le niveau de protection requis par le droit de l’Union soit respecté, elles peuvent nécessiter, en fonction de la situation prévalant dans tel ou tel pays tiers, l’adoption de mesures supplémentaires par le responsable du traitement afin d’assurer le respect de ce niveau de protection.

Les choses sont donc très claires de ce côté : un transfert est possible et licite, à condition qu’il soit bien encadré.

B - Toutefois on peut éviter ce transfert et en assurer la légalité

Légalement on peut donc transférer des données personnelles aux États-Unis à la condition d’avoir des garanties supplémentaires (1). Or, Google a précisément prévu ces garanties afin de rendre ce transfert possible (2).

1) Légalement on peut transférer des données aux États-Unis à condition d’avoir des garanties supplémentaires

L’arrêt de la CJUE est important pour deux raisons (pour une bonne présentation du problème voir ici):

  • il rappelle clairement qu’il est possible de réaliser un transfert de données personnelles aux États-Unis à la condition de disposer de garanties supplémentaires effectives
  • il impose in fine à chaque responsable de traitement de mettre à plat la situation transfert par transfert et de s’interroger sur le niveau de protection adéquat

La question qui va se poser maintenant est donc de déterminer quelles sont les mesures supplémentaires que l’on peut mettre en place pour garantir un niveau effectif final de protection en utilisant Google Analytics.

Fort heureusement l’EBPB a très précisément détaillé les mesures additionnelles susceptibles d’être mise en place, ce qui nous donne des indications intéressantes et qui va pouvoir nous servir de base de travail.

L’annexe 2 nous donne en particulier un exemple très intéressant :

A data exporter first pseudonymises data it holds, and then transfers it to a third country for analysis, e.g., for purposes of research. If

  1. a data exporter transfers personal data processed in such a manner that the personal data can no longer be attributed to a specific data subject, nor be used to single out the data subject in a larger group without the use of additional information,
  2. that additional information is held exclusively by the data exporter and kept separately in a Member State or in a third country, by an entity trusted by the exporter in the EEA or under a jurisdiction offering an essentially equivalent level of protection to that guaranteed within the EEA,
  3. disclosure or unauthorised use of that additional information is prevented by appropriate technical and organisational safeguards, it is ensured that the data exporter retains sole control of the algorithm or repository that enables re-identification using the additional information, and
  4. the controller has established by means of a thorough analysis of the data in question - taking into account any information that the public authorities of the recipient country may be expected to possess and use - that the pseudonymised personal data cannot be attributed to an identified or identifiable natural person even if cross-referenced with such information, then the EDPB considers that the pseudonymisation performed provides an effective supplementary measure

Reste à voir comment de telles garanties pourraient être appliquées.

2) Or Google propose des garanties supplémentaires effectives et licites

Google qui avait réagi une première fois à la décision de l’autorité autrichienne a détaillé une liste très importante de mesures supplémentaires mises en œuvre pour assurer la conformité du transfert hors UE.

Or dans ce guide on trouve une mesure essentielle qui va nous permettre de garantir la conformité et la sécurité du traitement :

IP Anonymisation: Google Analytics customers can turn on IP Anonymisation (or IP masking) to instruct Google to anonymise all IP-addresses immediately after they are collected. If IP Anonymisation is turned on, at no time is the full IP-address written to disk as all anonymisation happens in memory nearly instantaneously after the request has been received. When our systems receive an IP-address from a user in the EU, they are designed to render IP Anonymisation in EU servers. More details about IP Anonymisation are here.

En d’autres termes, en mettant en œuvre le mécanisme d’anonymisation, il n’y a plus de données personnelles traitées une fois cette anonymisation opérée, et donc plus aucun transfert hors UE.

Si l’on met donc en place une solution technique qui supprime les cookies, qui élimine l’userId, nous n’avons plus que l’adresse IP comme donnée personnelle traitée. Celle-ci pouvant être anonymisée, nous avons donc toutes les bases d’une solution opérationnelle.

Tous les points juridiques étant maintenant posés, nous sommes en mesure de construire la solution.

II - Comment paramétrer Google Analytics pour être en conformité au RGPD

Il y a donc une série d’actions à mettre en œuvre pour s’assurer de la conformité RGPD d’Analytics :

  • supprimer l’ensemble des cookies
  • Générer un userId anonyme
  • activer Anonymize IP
  • activer les clauses contractuelles types - essentiellement par précaution
  • et s’assurer de respecter le contrat en ne transférant aucune DCP dans Analytics

A - Supprimer tous les cookies

La première action a mettre en œuvre est de supprimer l’ensemble des cookies qui sont placés côté client qui existe dans Google Analytics dans sa configuration par défaut.

En effet, dans la décision autrichienne rendue récemment à propos d’Analytics, les cookies sont considérés par l’autorité comme permettant l’identification d’une personne physique.

D’un point de vue du RGPD cela peut se discuter, car il est douteux qu’on puisse identifier une personne au moyen de cookies la majorité dy temps, mais c’est une prise de position que l’on doit prendre en compte.

Fort heureusement Analytics permet de mettre en place une solution sans cookies au travers des paramètres suivants :

client_storage: ‘none’, client_id: buildUserId()

Le second paramètre va être un userID que nous allons devoir nous-même fournir à Analytics ; cet userId est considéré comme une donnée personnelle par Google en temps normal (cf. les data processings terms de Google que nous avions déjà analysé ci-dessus), nous allons donc la supprimer.

Afin d’éviter plus de complexité liée au RGPD, nous allons donc générer un userId anonyme.

B - Générer un userId anonyme

Nous allons devoir relever un challenge intéressant : générer un ID unique pour chaque utilisateur qui fréquente le site, faire en sorte que cet ID puisse être lié à des requêtes d’un même navigateur (pour plus ou moins identifier les pages visitées par une personne), sans toutefois être en mesure d’identifier la personne en question.

À l’origine, c’était le rôle joué par les cookies qui permettaient de déterminer si une personne effectuait plusieurs visites ou si elle demandait à avoir plusieurs pages sur un site web donné. Toutefois, comme nous l’avons vu, recourir aux cookies pose de nombreux problèmes en termes de conformité RGPD (en plus de celui de devoir demander le consentement de la personne concernée - conformément à la directive 2002/58 - e-privacy).

Ce que nous allons faire c’est donc créer un identifiant temporaire pour une personne ; celui-ci n’aura pas l’effectivité des cookies sur le long terme, mais cet identifiant nous permettra de reconnaitre plusieurs pages visitées par un même navigateur et cela sans être en mesure d’identifier la personne exacte, ce qui est essentiel côté RGPD.

La solution fonctionne de la manière suivante :

  • on identifie le navigateur de la personne
  • on identifie les langues configurées sur le navigateur
  • on génère une tranche horaire arrondie à 3h
  • on effectue un hachage de ces données (md5) pour générer l’userId anonyme

De la sorte en disposant de l’userId on ne pourra pas remonter à la personne elle-même. Nous avons donc une solution d’anonymisation qui est suffisamment solide pour ne pas opérer un traitement de données personnelles et qui est dans le même esprit que la solution technique de l’EDPB (cf. ci-dessus) - en fait plus solide encore, car elle est anonymisée et non simplement pseudonimisée (avec notre userId, il ne sera jamais possible de remonter à la source).

Cet userId anonyme sera donc ensuite communiqué à Analytics pour la création de statistiques. La solution est basique pour des statistiques et pourrait très bien être améliorée, mais c’est une manière simple d’avoir des données d’utilisation de son site web sans trop d’encombrement règlementaire. Et la solution a l’avantage d’être mise en œuvre exclusivement côté client (voir le code ci-dessous).

Une solution plus élaborée consisterait à générer un userId sur un serveur interne, et conserver une trace des sessions au moyen de l’IP de l’utilisateur, mais cela impose des développements plus importants (déploiement d’une API, génération d’un userId, management des sessions, vérification de la conformité RGPD de la solution…).

C - Activez Anonymize IP

Une fois que l’on a un userId anonyme, et que l’on a évacué les cookies, nous nous retrouvons avec une seule donnée personnelle au sens du RGPD : l’adresse IP de l’utilisateur qui sera transmise à Google.

Fort heureusement, Google permet d’anonymiser cette donnée. Et comme il est indiqué clairement dans leur documentation, l’anonymisation sera effectuée en Europe : https://services.google.com/fh/files/misc/safeguards_for_international_data_transfers.pdf

IP Anonymisation: Google Analytics customers can turn on IP Anonymisation (or IP masking) to instruct Google to anonymise all IP-addresses immediately after they are collected. If IP Anonymisation is turned on, at no time is the full IP-address written to disk as all anonymisation happens in memory nearly instantaneously after the request has been received. When our systems receive an IP-address from a user in the EU, they are designed to render IP Anonymisation in EU servers.

En mettant en place cette option, aucune donnée personnelle ne sera alors transférée hors de l’UE puisque le seul moment pendant lequel les données personnelles seront traitées est le temps de leur anonymisation en Europe.

Voici le paramétrage qui vous permettra d’utiliser Google Analytics :

‘anonymize_ip’: true.

En anonymisant l’IP, nous coupons donc totalement au transfert de données hors de l’UE et pouvons exploiter Google analytics en conformité au RGPD.

Voici la configuration de Google analytics (le code complet ci-dessous):

<script async src="https://www.googletagmanager.com/gtag/js?id=XXXXXXX-XX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXX-XX',  
    { 
        'anonymize_ip': true,
        'allow_ad_personalization_signals': false,
        'allow_google_signals': false,
        'ad_storage': 'denied',
        client_storage: 'none',
        client_id: buildUserId()
    }
);
</script>

Trois options sont essentielles :

  • anonymize_ip’: true -> cette option permet d’anonymiser l’adresse IP et donc d’éviter des transferts hors UE, elle était manquante dans la décision de l’autorité autrichienne
  • client_storage: ‘none’ -> cela permet d’éviter les cookies, donc à la fois l’application du RGPD pour les cookies, et éviter l’application de la directive e-privacy qui impose le consentement des persones pour le stockage de données sur leurs navigateurs (cookies, localStorage…)
  • client_id: buildUserId() -> Google analytics nécessite un userId, la fonction buildUserId() va donc renvoyer cet userId qui est un hash des éléments susmentionnés.

Et voici le détail du code avec la fonction buildUserId() et son implémentation pratique dans le <head> de la page web :

<script>
            /*
            *   permet de créer un MD5 - hash 
            *   origine : http://www.myersdaily.org/joseph/javascript/md5.js
            *
            */
            function md5cycle(x, k) {
                var a = x[0], b = x[1], c = x[2], d = x[3];

                a = ff(a, b, c, d, k[0], 7, -680876936);
                d = ff(d, a, b, c, k[1], 12, -389564586);
                c = ff(c, d, a, b, k[2], 17,  606105819);
                b = ff(b, c, d, a, k[3], 22, -1044525330);
                a = ff(a, b, c, d, k[4], 7, -176418897);
                d = ff(d, a, b, c, k[5], 12,  1200080426);
                c = ff(c, d, a, b, k[6], 17, -1473231341);
                b = ff(b, c, d, a, k[7], 22, -45705983);
                a = ff(a, b, c, d, k[8], 7,  1770035416);
                d = ff(d, a, b, c, k[9], 12, -1958414417);
                c = ff(c, d, a, b, k[10], 17, -42063);
                b = ff(b, c, d, a, k[11], 22, -1990404162);
                a = ff(a, b, c, d, k[12], 7,  1804603682);
                d = ff(d, a, b, c, k[13], 12, -40341101);
                c = ff(c, d, a, b, k[14], 17, -1502002290);
                b = ff(b, c, d, a, k[15], 22,  1236535329);

                a = gg(a, b, c, d, k[1], 5, -165796510);
                d = gg(d, a, b, c, k[6], 9, -1069501632);
                c = gg(c, d, a, b, k[11], 14,  643717713);
                b = gg(b, c, d, a, k[0], 20, -373897302);
                a = gg(a, b, c, d, k[5], 5, -701558691);
                d = gg(d, a, b, c, k[10], 9,  38016083);
                c = gg(c, d, a, b, k[15], 14, -660478335);
                b = gg(b, c, d, a, k[4], 20, -405537848);
                a = gg(a, b, c, d, k[9], 5,  568446438);
                d = gg(d, a, b, c, k[14], 9, -1019803690);
                c = gg(c, d, a, b, k[3], 14, -187363961);
                b = gg(b, c, d, a, k[8], 20,  1163531501);
                a = gg(a, b, c, d, k[13], 5, -1444681467);
                d = gg(d, a, b, c, k[2], 9, -51403784);
                c = gg(c, d, a, b, k[7], 14,  1735328473);
                b = gg(b, c, d, a, k[12], 20, -1926607734);

                a = hh(a, b, c, d, k[5], 4, -378558);
                d = hh(d, a, b, c, k[8], 11, -2022574463);
                c = hh(c, d, a, b, k[11], 16,  1839030562);
                b = hh(b, c, d, a, k[14], 23, -35309556);
                a = hh(a, b, c, d, k[1], 4, -1530992060);
                d = hh(d, a, b, c, k[4], 11,  1272893353);
                c = hh(c, d, a, b, k[7], 16, -155497632);
                b = hh(b, c, d, a, k[10], 23, -1094730640);
                a = hh(a, b, c, d, k[13], 4,  681279174);
                d = hh(d, a, b, c, k[0], 11, -358537222);
                c = hh(c, d, a, b, k[3], 16, -722521979);
                b = hh(b, c, d, a, k[6], 23,  76029189);
                a = hh(a, b, c, d, k[9], 4, -640364487);
                d = hh(d, a, b, c, k[12], 11, -421815835);
                c = hh(c, d, a, b, k[15], 16,  530742520);
                b = hh(b, c, d, a, k[2], 23, -995338651);

                a = ii(a, b, c, d, k[0], 6, -198630844);
                d = ii(d, a, b, c, k[7], 10,  1126891415);
                c = ii(c, d, a, b, k[14], 15, -1416354905);
                b = ii(b, c, d, a, k[5], 21, -57434055);
                a = ii(a, b, c, d, k[12], 6,  1700485571);
                d = ii(d, a, b, c, k[3], 10, -1894986606);
                c = ii(c, d, a, b, k[10], 15, -1051523);
                b = ii(b, c, d, a, k[1], 21, -2054922799);
                a = ii(a, b, c, d, k[8], 6,  1873313359);
                d = ii(d, a, b, c, k[15], 10, -30611744);
                c = ii(c, d, a, b, k[6], 15, -1560198380);
                b = ii(b, c, d, a, k[13], 21,  1309151649);
                a = ii(a, b, c, d, k[4], 6, -145523070);
                d = ii(d, a, b, c, k[11], 10, -1120210379);
                c = ii(c, d, a, b, k[2], 15,  718787259);
                b = ii(b, c, d, a, k[9], 21, -343485551);

                x[0] = add32(a, x[0]);
                x[1] = add32(b, x[1]);
                x[2] = add32(c, x[2]);
                x[3] = add32(d, x[3]);

            }

            function cmn(q, a, b, x, s, t) {
                a = add32(add32(a, q), add32(x, t));
                return add32((a << s) | (a >>> (32 - s)), b);
            }

            function ff(a, b, c, d, x, s, t) {
                return cmn((b & c) | ((~b) & d), a, b, x, s, t);
            }

            function gg(a, b, c, d, x, s, t) {
                return cmn((b & d) | (c & (~d)), a, b, x, s, t);
            }

            function hh(a, b, c, d, x, s, t) {
                return cmn(b ^ c ^ d, a, b, x, s, t);
            }

            function ii(a, b, c, d, x, s, t) {
                return cmn(c ^ (b | (~d)), a, b, x, s, t);
            }

            function md51(s) {
                txt = '';
                var n = s.length,
                state = [1732584193, -271733879, -1732584194, 271733878], i;
                for (i=64; i<=s.length; i+=64) {
                md5cycle(state, md5blk(s.substring(i-64, i)));
                }
                s = s.substring(i-64);
                var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
                for (i=0; i<s.length; i++)
                tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
                tail[i>>2] |= 0x80 << ((i%4) << 3);
                if (i > 55) {
                md5cycle(state, tail);
                for (i=0; i<16; i++) tail[i] = 0;
                }
                tail[14] = n*8;
                md5cycle(state, tail);
                return state;
            }

            /* there needs to be support for Unicode here,
            * unless we pretend that we can redefine the MD-5
            * algorithm for multi-byte characters (perhaps
            * by adding every four 16-bit characters and
            * shortening the sum to 32 bits). Otherwise
            * I suggest performing MD-5 as if every character
            * was two bytes--e.g., 0040 0025 = @%--but then
            * how will an ordinary MD-5 sum be matched?
            * There is no way to standardize text to something
            * like UTF-8 before transformation; speed cost is
            * utterly prohibitive. The JavaScript standard
            * itself needs to look at this: it should start
            * providing access to strings as preformed UTF-8
            * 8-bit unsigned value arrays.
            */
            function md5blk(s) { /* I figured global was faster.   */
                var md5blks = [], i; /* Andy King said do it this way. */
                for (i=0; i<64; i+=4) {
                md5blks[i>>2] = s.charCodeAt(i)
                + (s.charCodeAt(i+1) << 8)
                + (s.charCodeAt(i+2) << 16)
                + (s.charCodeAt(i+3) << 24);
                }
                return md5blks;
            }

            var hex_chr = '0123456789abcdef'.split('');

            function rhex(n) {
                var s='', j=0;
                for(; j<4; j++)
                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
                + hex_chr[(n >> (j * 8)) & 0x0F];
                return s;
            }

            function hex(x) {
                for (var i=0; i<x.length; i++)
                x[i] = rhex(x[i]);
                return x.join('');
            }

            function md5(s) {
                return hex(md51(s));
            }

            /* this function is much faster,
            so if possible we use it. Some IEs
            are the only ones I know of that
            need the idiotic second function,
            generated by an if clause.  */

            function add32(a, b) {
                return (a + b) & 0xFFFFFFFF;
            }

            if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
                function add32(x, y) {
                var lsw = (x & 0xFFFF) + (y & 0xFFFF),
                msw = (x >> 16) + (y >> 16) + (lsw >> 16);
                return (msw << 16) | (lsw & 0xFFFF);
                }
            }
        
            /*
            *   Cette fonction va permettre de créer une chaine de caractère (date/h)
            *   différente toutes les 3 heures
            *
            */
            function roundHours(precision, d){
                precision= precision || 1;
                d= d? new Date(d):new Date();
                if(d.getSeconds()>30) d.setMinutes(d.getMinutes()+1);
                if(d.getMinutes>30) hours+= 1;
                var hours= d.getHours(), diff= hours%precision;
                if(diff>precision/2) hours+= (precision-diff);
                else hours-= diff;
                d.setHours(hours, 0, 0, 0);
                return d.toLocaleString();
            }

            /*
            *   Enfin on crée un userId sur la base 
            *   des données du navigateur + roundHour
            */
            function buildUserId(){
                return md5(roundHours(3, new Date()) + window.navigator.userAgent + window.navigator.languages.toString() );
            }
    </script>


    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-XX"></script>
    <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    <!-- REPLACE YOUR ID HERE -->
    gtag('config', 'UA-XXXXXXX-XX',  
        { 
            'anonymize_ip': true,
            'allow_ad_personalization_signals': false,
            'allow_google_signals': false,
            'ad_storage': 'denied',
            client_storage: 'none',
            client_id: buildUserId()
        }
    );
    </script>

Deux autres précautions seront utiles.

D - Acceptez les clauses contractuelles types

Bien que nous ne procédons à aucun transfert de données personnelles, il est toujours utile d’accepter les clauses contractuelles types de protection des données dans Google Analytics directement, simplement à titre de précaution :

E - Ne transférez aucune donnée personnelle dans GA

Et enfin il faut s’assurer de ne transférer aucune donnée personnelle dans Google analytics pour que ce paramétrage soit valable. Attention à ce titre, car la notion de données personnelles couvre les données directement personnelles de même que les données indirectement personnelles, donc un identifiant utilisateur, ou un numéro de commande par exemple, seraient des données personnelles au sens du RGPD, donc à éviter.

Thiébaut Devergranne
Thiébaut Devergranne
Thiébaut Devergranne est docteur en droit et expert en droit des nouvelles technologies depuis plus de 20 ans, dont 6 passés au sein des services du Premier Ministre. En savoir plus

Ils nous ont fait confiance

logo Deloitte
logo starbucks
logo orange bank
logo vinci
logo nokia
logo sanofi
logo sncf
VOS CGV (gratuites)