Tarteaucitron : Comment configurer GTM sans cookie ?

WRInaute accro
Bonjour

Voici mon script PHP clientId.php

PHP:
<?php
    echo (int)hexdec(substr(hash('sha256', urldecode($_GET['userAgent']) . $_SERVER['REMOTE_ADDR']), -10)) % 10 ** 10 . '.' . time();
?>

Ce script est destiné à produire le client_id de GA.

Voici le script de GTM pour tarteaucitron :

JavaScript:
tarteaucitron.user.googletagmanagerId = 'GTM-WKXYXXX';
        (tarteaucitron.job = tarteaucitron.job || [{
      'userID' : 'unknown',
      'storage': 'none',
      'store_gac' : false,
      'client_id': getClientId()
    }]).push('googletagmanager');
  </script>

Je n'ai pas mis le code de la fonction Javascript getClientId(), qui lance clientId .php et reçoit l'id_client.

Voici un exemple d'id_client : 7982804053.1594744121

Ma question est : Avec tarteaucitron et GTM, comment faire en sorte que GTM ne dépose aucun cookie ?

Merci beaucoup.

P.S. Ma configuration de GTM est avec anonymize_ip = true.
 
WRInaute accro
Pardon

Voici la fonction Javascript getClientId() :

$web_url provient de PHP .


JavaScript:
    <script type="text/javascript">
    function getClientId() {
       var d = new Date();
       var url = new URL('" . $web_url . "' + '/tarteaucitron/clientId.php?userAgent=' + encodeURIComponent(window.navigator.userAgent) + '\&timestamp=' + d.getTime());
           console.log('URL = ' + url);

            fetch(url, {
                    method: "GET",
                    headers: {
                            "Content-Type": "text/plain"
                    }
            }).then(function(response) {
                    response.text().then(function(text) {
                            return text;
                    }, function(err) {
                            console.log('Erreur storing User Cookies preferences' + err);
                           return null;
                    })
            }, function(err) {
                    console.log('Erreur Fetching text ' + err);
                    return null;
            })
    }
     </script>
 
WRInaute accro
Rebonjour

J'ai adapté les fonctions UUID($anonid) et ClientUUID($anonid) de Javascript en PHP.

Client_UUID() est beaucoup mieux que ma précédente version de clientId().

D'autre part, $_GET['userAgent'] et $_GET['nbre_accept'] sont l'UserAgent du visiteur et le nombre d'acceptations ( ou de refus ), du visiteur.

nbre_accept set à modifier le clientId, et tous les 3 mois( ou tous les 13 mois ), le clientId est changé.

Ce script doit être lancée en fetch, pour disposer de l'adresse ip.

En effet, mon site a un cache html, l'ip n'est pas disponible.

Merci beaucoup de vos réponses.

Amicalement.


PHP:
<?php
define("COOKIE_TIMEOUT_3_MOIS", 788400);
define("COOKIE_TIMEOUT_13_MOIS", 34164000);
function UUID($anon_id)
{
        // Binary Value
        $nstr = '';
        // Convert Namespace UUID to bits
        for($i = 0; $i < strlen($anon_id); $i+=2) {
                $nbre = (int)(dechex(hexdec(substr($anon_id, $i, 1))) . dechex(hexdec(substr($anon_id, $i + 1, 1))));
                $nstr .= chr($nbre);
        }
        // Calculate hash value
        $hash = sha1($nstr . $anon_id);
        // 32 bits for "time_low"
        $data_1 = substr($hash, 0, 8);
        // 16 bits for "time_mid"
        $data_2 = substr($hash, 8, 4);
        // 16 bits for "time_hi_and_version",
        // four most significant bits holds version number 3
        $tmp_data3 = (hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x4000;
        $data3 = substr(dechex($tmp_data3), 0, 4);
        // 16 bits, 8 bits for "clk_seq_hi_res",
        // 8 bits for "clk_seq_low",
        // two most significant bits holds zero and one for variant DCE1.1
        $tmp_data4 = (hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000;
        $data4 = substr(dechex($tmp_data4), 0, 4);
        // 48 bits for "node"
        $data5 = substr($hash, 20, 12);
        $result = $data_1 . '-' . $data_2 . '-' . $data3 . '-' . $data4 . '-' . $data5;
        return($result);
}
function Client_UUID($anon_id)
{
        $hash = sha1($anon_id);
        $anon_id = sha1($hash);
        $hashed = crc32($anon_id) + crc32($anon_id);
        $regex = "{^(0+)}";
        $regex2 ="{^[0]+(.+)}";
        if(preg_match($regex, $hashed))
        {
            if(preg_match($regex2, $hashed, $array_match))
            {
                $regex3 = "{" . $array_match[0] . "$}";
                // Debut avec des zéro;
                $prefix = preg_replace($regex3, '', $hashed);
                $tmp_len = strlen($prefix);
                // Remplacement avec des chiffres différents de zéro.
                $tmp_prefix = '';
                for($i = 0; $i < $tmp_len; $i++)
                {
                        $nbre = 1 + ($i * 2) % 10;
                        $tmp_prefix .= (string)$nbre;
                }
                $tmp_prefix .= preg_replace($regex, '', $hashed);
                $hashed = $tmp_prefix;
            }
        }
        return $hashed . '.' . time();
}
function clientId() {
        // Create an anonymous ID - we double hash with salt, GA won't who's who
        $server = $_SERVER['HTTP_HOST'] . $_SERVER['SERVER_ADDR'];
        $salt = sha1($server);
        $add_date = (string)floor(1.0 * time() / COOKIE_TIMEOUT_3_MOIS) + (int)urldecode($_GET['nbreAccept']);
        $hash_const = sha1($add_date . $_SERVER['REMOTE_ADDR'] . $salt);
        $hash_const2 = sha1($add_date . urldecode($_GET['userAgent']) . $_SERVER['REMOTE_ADDR']);
        // Client ID
        $CID = UUID($hash_const);
        // User ID
        $UID = Client_UUID($hash_const2);
        return $UID;
}
echo clientId();
?>
 
WRInaute accro
Bonjour

J'essaye de remplir dataLayer avec les variables qui vont bien, pour qu'il n'y ait pas de cookie, et initialiser client_id ( ou clientId je ne sais pas ), avec la fonction ci-dessus Client_UUID($anonid).

Voici ce que j'ai :

Code:
<script>

getClientId().then(function(response) {
    console.log('clientId = ' + response);
    window.dataLayer = window.dataLayer || [];
    window.dataLayer.push({
        'clientId': response,
        'storage': 'none',
        'storeGac': false,
        event: 'gtm.dom'
    });
    tarteaucitron.user.googletagmanagerId = 'GTM-WK6D676';
    (tarteaucitron.job = tarteaucitron.job || [{
    }]).push('googletagmanager');
    (tarteaucitron.job = tarteaucitron.job || []).push('star_cookie');
})

</script>

getClientId() rend une Promise et le résultat de Client_UUID($anonid).

response est correct, mais les données ( collect ) transmises ne correspondent pas.

C'est possible de tester le résultat avec la console Javascript.

Le cid transmis est différent et _gid aussi.

Voici l'url : https://www.pronostics-courses.fr

Ma window.dataLayer est-elle correctement remplie ?

Merci beaucoup de votre aide.

Amicalement.
 
WRInaute accro
Bonjour

Avec le mode "inspect" de Chrome, je regarde les data transmises à GTM.

Normalement, il devrait y avoir mon gtm.cid

Voici le dataLayer en amont de GTM ( avec tarteaucitron ) :

Cà ne marche pas, quel que soit le nom gtm.cid.

J'ai essayé : userId, userID, clientId, client_id.

Que faire ?

getClientId est dans le Javascript ( sur mon site ), et lance clientId.php qui rend lui-même un id client codé.

Vous pouvez le visualiser en mode inspect.


JavaScript:
getClientId().then(function(response){
        console.log('clientId = '+response);
        window.dataLayer=window.dataLayer||[];
        window.dataLayer.push({
                'storage':'none',
                'gtm.cid':response,
                'event':'gtm.dom'
        });
        tarteaucitron.user.googletagmanagerId='GTM-WK6D676';
        (tarteaucitron.job=tarteaucitron.job||[{}]).push('googletagmanager');
        (tarteaucitron.job=tarteaucitron.job||[]).push('star_cookie');
})

Pardon.

Est-ce que ma déclaration de window.dataLayer ( dans une fonction ) est correcte ?

Merci beaucoup.

Amicalement.
 
WRInaute accro
Bonjour

J'ai troqué mes lancements de script PHP contre une fonction de type UUID_V4, et adapté à un localstorage.

J'alimente le dataLayer avec la fonction window.apply() dans le script tarteaucitron.services.js

Je donne le code après.


Voici :

Code:
<script>

function sha1 (str) {
function hex (value) {
var s = (value >>> 0).toString(16)
while (s.length < 8) s = '0' + s
return s
}
function limit (n) {
return n & 0xffffffff
}
function rotateLeft (n, s) {
return (n << s) | (n >>> (32 - s))
}
var H0 = 0x67452301
var H1 = 0xefcdab89
var H2 = 0x98badcfe
var H3 = 0x10325476
var H4 = 0xc3d2e1f0
var i, j
var blockstart
var W = new Array(80)
var A, B, C, D, E
var temp
str = unescape(encodeURIComponent(str))
str = str.split(/.*?/).map(function (s) {
return s.charCodeAt(0)
})
var length = str.length
var words = []
for (i = 0; i < length - 3; i += 4) {
j = str[i] << 24 | str[i + 1] << 16 | str[i + 2] << 8 | str[i + 3]
words.push(j)
}
switch (length % 4) {
case 0:
i = 0x80000000
break
case 1:
i = str[length - 1] << 24 | 0x800000
break
case 2:
i = str[length - 2] << 24 | str[length - 1] << 16 | 0x8000
break
case 3:
i = str[length - 3] << 24 | str[length - 2] << 16 | str[length - 1] << 8 | 0x80
break
}
words.push(i)
while ((words.length % 16) != 14) {
words.push(0)
}
words.push(length >>> 29)
words.push(limit(length << 3))
for (blockstart = 0; blockstart < words.length; blockstart += 16) {
for (i = 0; i < 16; i++) {
W[i] = words[blockstart + i]
}
for (i = 16; i < 80; i++) {
W[i] = rotateLeft(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1)
}
A = H0
B = H1
C = H2
D = H3
E = H4
for (i = 0; i <= 19; i++) {
temp = limit(rotateLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5a827999)
E = D
D = C
C = rotateLeft(B, 30)
B = A
A = temp
}
for (i = 20; i <= 39; i++) {
temp = limit(rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ed9eba1)
E = D
D = C
C = rotateLeft(B, 30)
B = A
A = temp
}
for (i = 40; i <= 59; i++) {
temp = limit(rotateLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8f1bbcdc)
E = D
D = C
C = rotateLeft(B, 30)
B = A
A = temp
}
for (i = 60; i <= 79; i++) {
temp = limit(rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xca62c1d6)
E = D
D = C
C = rotateLeft(B, 30)
B = A
A = temp
}
H0 = limit(H0 + A)
H1 = limit(H1 + B)
H2 = limit(H2 + C)
H3 = limit(H3 + D)
H4 = limit(H4 + E)
}
return hex(H0) + hex(H1) + hex(H2) + hex(H3) + hex(H4)
}
function hexdec (hexString) {
// discuss at: http://locutus.io/php/hexdec/
// original by: Philippe Baumann
// example 1: hexdec('that')
// returns 1: 10
// example 2: hexdec('a0')
// returns 2: 160
hexString = (hexString + '').replace(/[^a-f0-9]/gi, '')
return parseInt(hexString, 16)
}
function chr (code) {
return(String.fromCharCode(code));
}
function aleatoire(size) {
var liste = ["a","b","c","d","e","f", "0","1","2","3","4","5","6","7","8","9"];
var result = '';
for (i = 0; i < size; i++) {
result += liste[Math.floor(Math.random() * liste.length)];
}
return result;
}
function ClientUUID()
{
var anon_id = aleatoire(60);
// Binary Value
nstr = '';
// Convert Namespace UUID to bits
for(i = 0; i < anon_id.length; i+=2) {
var nbre = (hexdec(anon_id.substr(i, 1))).toString(16) + (hexdec(anon_id.substr(i + 1, 1))).toString(16);
nstr += chr(Number(nbre));
}
// Calculate hash value
hash = sha1(nstr + anon_id);
// 32 bits for "time_low"
data_1 = hash.substr(0, 8);
// 16 bits for "time_mid"
data_2 = hash.substr(8, 4);
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 3
tmp_data3 = (hexdec(hash.substr(12, 4)) & 0x0fff) | 0x4000;
data3 = tmp_data3.toString(16).substr(0, 4);
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
tmp_data4 = (hexdec(hash.substr(16, 4)) & 0x3fff) | 0x8000;
data4 = tmp_data4.toString(16).substr(0, 4);
// 48 bits for "node"
data5 = hash.substr(20, 12);
result = data_1 + '-' + data_2 + '-' + data3 + '-' + data4 + '-' + data5;
return result;
}
function apply_gtm() {
window.apply('js', new Date())
// defines window.localstorage key
const GA_LOCAL_STORAGE_KEY = 'ga:clientId'
const GA_MEASUREMENT_ID = 'UA-XXXXXXXXX-Y';
// checks if localstorage is available
if (window.localStorage) {
// checks if user was already connected and loads client_id from localstorage
if (localStorage.getItem(GA_LOCAL_STORAGE_KEY)) {
// creates new tracker with same client_id as the last time the user visited
window.apply('js', new Date())
window.apply('config', GA_MEASUREMENT_ID, {
'send_page_view': true,
'storage': 'none',
'gac_storage': false,
'client_id': localStorage.getItem(GA_LOCAL_STORAGE_KEY)
})
} else {
// creates client_id and saves it in localStorage -> currently random UUIDv4
window.localStorage.setItem(GA_LOCAL_STORAGE_KEY, ClientUUID())
// creates new tracker with the new client_id
window.apply('js', new Date())
window.apply('config', GA_MEASUREMENT_ID, {
'send_page_view': true,
'storage': 'none',
'gac_storage': false,
'client_id': localStorage.getItem(GA_LOCAL_STORAGE_KEY)
})
}
console.log('client_id = ' + localStorage.getItem(GA_LOCAL_STORAGE_KEY))
}
}
window.dataLayer = window.dataLayer || [];
tarteaucitron.user.googletagmanagerId = 'GTM-WKXDYYY';
(tarteaucitron.job = tarteaucitron.job || [{
}]).push('googletagmanager');
(tarteaucitron.job = tarteaucitron.job || []).push('star_cookie');
</script>


Voilà le code dans tarteaucitron.services.js :

Cà ne marche pas, les _gid et cid envoyés à GTM ( collect de mode inspect ), n'ont pas changé.


JavaScript:
// google tag manager
tarteaucitron.services.googletagmanager = {
       "key": "googletagmanager",
       "type": "api",
       "name": "Google Tag Manager",
       "uri": "https://adssettings.google.com/",
       "needConsent": true,
       "cookies": ['_ga', '_gat', '__utma', '__utmb', '__utmc', '__utmt', '__utmz', '__gads', '_drt_', 'FLC', 'exchange_uid', 'id', 'fc', 'rrs', 'rds', 'rv', 'uid', 'UIDR', 'UID', 'clid', 'ipinfo', 'acs', 'ID_COOKIE'],
       "js": function () {
               "use strict";
               // When user allow cookie
               if (tarteaucitron.user.googletagmanagerId === undefined) {
                       return;
               }
               gestion_cookies('ACCEPT', 'accept_cookies');

               window.dataLayer = window.dataLayer || [];

               window.apply = function apply(){dataLayer.push(arguments);
                   console.log(arguments);
               }

               apply_gtm();

//                window.dataLayer.push({
//                    'gtm.start': new Date().getTime(),
//                    event: 'gtm.js'
//                });

               tarteaucitron.addScript('https://www.googletagmanager.com/gtm.js?id=' + tarteaucitron.user.googletagmanagerId);
       },
       "fallback": function () {
               "use strict";
               // when use deny cookie
               gestion_cookies('DENY', 'accept_cookies');
       }
};
 
Dernière édition:
WRInaute accro
Bon

Voilà ( d'après le collect ) ce que j'envoie à GTM :

Code:
Array(6)
0: {storage: "none"}
1: {storeGac: false}
2: {userId: "995137dc-03f1-4b8a-8b98-939d9e912265"}
3: {gtm.start: 1595242296248, event: "gtm.js", gtm.uniqueEventId: 0}
4: {event: "gtm.dom", gtm.uniqueEventId: 2}
5: {event: "gtm.load", gtm.uniqueEventId: 3}
push: ƒ ()length: 
6__proto__: Array(0)

Est-ce que les noms des variables sont corrects ?

Merci beaucoup.
 
Nouveau WRInaute
Merci à toi pour tes partages d'information. Je trouve dommage qu'il y a peu de participants à ce fil, mais sans doute parce qu'il est un peu spécifique.

Mais j'ai découvert qu'entre temps tu as passé de tarteaucitron Sirdata CMP, avec une solution qui marche bien je crois.
 
WRInaute accro
Bonjour Olivier

Il me semble que la CNIL n' a pas encore indiqué que la norme IAB TCF2.0 était obligatoire.

Peut-être que je me trompe.

Pour sirdata, j'ai obtenu de sirdata un code pour GTM, et puis pour ma notation à étoiles, j'ai fait une implémentation avec la seule finality : lire et écrire un cookie/fingerprint sur le navigateur.

Merci beaucoup beaucoup à Wri pour son site. ;)

Très respectueusement.
 
Discussions similaires
Haut