Consentement avec google analytics

  • Auteur de la discussion Auteur de la discussion yoyo910
  • Date de début Date de début
WRInaute accro
Pour répondre a ta question il n'y a aucune affirmation/confirmation officielle à ce propos. J'aurais même plutôt tendance à dire que cela ne suffira pas pour être conforme sans le consentement du visiteur. Olivier (Webrankinfo) avait partagé un lien sur un des posts qui traite d'Analytics et du RGPD, qui faisait mention de la problématique concernant Analytics.

Voir aussi : alternative à Google Analytics pour le RGPD
 
WRInaute discret
Pour répondre a ta question il n'y a aucune affirmation/confirmation officielle à ce propos. J'aurais même plutôt tendance à dire que cela ne suffira pas pour être conforme sans le consentement du visiteur. Olivier (Webrankinfo) avait partagé un lien sur un des posts qui traite d'Analytics et du RGPD, qui faisait mention de la problématique concernant Analytics.

merci
que penses-tu de cet article ?est ce que cette technique permet de ne pas demander de consentement ? https://www.donneespersonnelles.fr/...analytics-en-conformite-au-rgpd#comment-83319
 
WRInaute accro
J'en dis que pour le moment y aller avec des bidouilles ne tout genre n’est pas forcément une bonne idée.
Mais c’est effectivement l'article en question qui explique pourquoi c’est complexe d'être conforme avec Analytics.
 
WRInaute accro
Bonjour yoyo910

En fait, il est indiqué dans la documentation Google Measurement Protocol, que les deux paramètres "dh" et "dp" simultanément, ou bien "dl", doivent figurer dans les paramètres.

dh => Hostname
dp => Request URI,

dl => Toute l'url.

Voilà.

Pour l'adresse ip, fournir "aip" ( je ne me souviens plus du paramètre ), donc anonymiser l'adresse ip est -il nécessaire ?

Et puis surtout : Comment faire celà avec gtag.js au lieu de analytics.js ?

Merci beaucoup à yoyo910.

Respectueusement.
 
WRInaute accro
Bonjour

Voici le programme d'envoi des data à Google, en utilisant la technologie Google Measurement Protocol.

Pour get_ip_address() j'ai pris $_SERVER['REMOTE_ADDR'], merci de corriger.

C'est un test, il affiche le résultat.

Merci aussi de corriger la fontion http_post($url, $data).

Respectueusement.


PHP:
<?php

function validate_ip($ip)
{
    if((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false)&&(filter_var($ip,    FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false))
    {
        return false;
    }
    return(true);
}

function correct_ip6($remote_addr)
{
    $array_ip6    = array();
    $array_ip6_fin    = array();
    if(!empty($remote_addr))
    {
        $array_ip6 = preg_split("{:}", $remote_addr);
        $tmp_count = 8;
        for($i = 0; $i < count($array_ip6); $i++)
        {
            if($array_ip6[$i] !== "")
            {
                $tmp_count--;
            }
        }
        $j = -1;
        $k_count = 0;
        for($i = count($array_ip6) - 1; $i >= 0; $i--)
        {
            if($array_ip6[$i] !== "")
            {
                unset($tmp);
                $tmp = substr("000". $array_ip6[$i], -4);
                $j++;
                $array_ip6_fin[$j] = $tmp;
            }
            else
            {
                unset($tmp);
                $tmp = "0000";
                while($k_count < $tmp_count)
                {
                    $j++;
                    $array_ip6_fin[$j] = $tmp;
                    $k_count++;
                }
            }
        }
        $addr_remote = "";
        for($i = count($array_ip6_fin) - 1; $i >= 0; $i--)
        {
            unset($tmp);
            $tmp = $array_ip6_fin[$i];
            if($i == (count($array_ip6_fin) - 1))
            {
                $addr_remote = $tmp;
            }
            else
            {
                $addr_remote .= ":" . $tmp;
            }
        }
        $addr_remote = strtolower($addr_remote);
        return((empty($addr_remote)) ? false : $addr_remote);
    }
    else
    {
        return(false);
    }
}

function get_ip_address()
{
    $ip = false;
    if(getenv("HTTP_CLIENT_IP"))
    {
        $ip = getenv("HTTP_CLIENT_IP");
    }
    elseif( getenv("HTTP_X_FORWARDED_FOR"))
    {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
        if( strstr($ip, ','))
        {
            $tmp = explode(',', $ip);
            $ip = preg_replace("{^[ \t]+}", "", $tmp[0]);
            $ip = preg_replace("{[ \t]+$}", "", $ip);
        }
    }
    else
    {
        $ip = getenv("REMOTE_ADDR");
    }
    $ip = $_SERVER["REMOTE_ADDR"];
    /*
    * Adresse ipv6,
    * On convertit
    * à la valeur
    * normalisée.
    */
    if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false)
    {
        $ip = correct_ip6($ip);
    }
    if(!validate_ip($ip))
    {
        return(false);
    }
    return($ip);
}

function http_post($url, $data)
{
    $request = http_build_query($data);
    $user_agent = $_SERVER['HTTP_USER_AGENT'];
    //    Utilisation de la librairie Curl
    //    pour envoi de paramètres POST.
    $ch = @curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_USER_AGENT, $user_agent);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    $content = @curl_exec($ch);
    if(@curl_errno($ch))
    {
        echo @curl_error($ch) . "<br>\n";
        @curl_close($ch);
        exit;
    }
    else
    {
        @curl_close($ch);
    }
    $response = array();
    $response = preg_split("/\n/", $content);
    return($response);
}

/**
 * Plugin Name: GDPR Analytics
 * Plugin URI: https://www.legiscope.com
 * Description: Google Analyics compatible with GDPR (completely anonymizing data)
 * Version: 1.0
 * Author: Legiscope
 * Author URI: https://www.lesgiscope.com
 *
 * Note : this a proof of concept of 100% compliant Google Analytics integration
 *       no personal data is sent back to GA, therefore GDPE will no apply ( art. 2 and art. 4)
 *       Check our legal study : https://www;donneespersonnelles.fr
 *
 *       Google API implementation : https://ga-dev-tools.appspot.com/hit-builder
 *                      https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
 *                      https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
 */
/**
 * This function will send a request to GA servers with anonymous users's ID and details about the visit
 */
function gdpr_analytics() {
    $ip_address = get_ip_address();
    $ga_url = "https://www.google-analytics.com/collect";
    //    $ga_url = "https://www.google-analytics.com/debug/collect";
    $data = array();
    # Enter your GA CODE HERE
    $data['tid'] = "UA-XXXXXXX-Y";
    # Create an anonymous ID - we double hash with salt, GA won't who's who
    $salt = hash("sha256", $_SERVER['SERVER_ADDR'] . $_SERVER['SERVER_NAME'] . $_SERVER['DOCUMENT_ROOT']);
    $hash = hash("sha256", $ip_address  . $_SERVER['HTTP_USER_AGENT']);
    $anon_id = hash("sha256", $salt . $hash);
    # Anonymous UserId
    $data['cid'] = $anon_id;
    # Application
    $data['ds'] = "analytics-gdpr";
    # Hit type
    $data["v"] = 1;
    # Hit type
    $data["t"] = "pageview";
    # IP address remote
    $data['uip'] = $ip_address;
    # Referer
    $data['dr'] = $_SERVER['HTTP_REFERER'];
    # User language
    $langue = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
    $pos1 = strpos($langue, ";");
    $pos2 = strpos($langue, ",");
    $data['ul'] = substr($langue, 0, min($pos1, $pos2));
    # Hostname
    $data['dh'] = $_SERVER['HTTP_HOST'];
    # Domain path
    $data['dp'] = $_SERVER['REQUEST_URI'];
    # Send the request
    $response = http_post($ga_url, $data);
    return($response);
}

$array_response = array();
$array_response = gdpr_analytics();
print_r($array_response);

?>
 
WRInaute accro
Bon, bon

Voici une nouvelle fonction get_ip_address().

Est-ce vraiment non secure de se fier à des en-têtes d'ip derrière des proxies ?

Merci beaucoup.

PHP:
<?php

function validate_ip($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)
    {
        return false;
    }
  
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) === false)
    {
        return false;
    }

    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false)
    {
        return false;
    }

    return(true);
}

function correct_ip6($remote_addr)
{
    $array_ip6    = array();
    $array_ip6_fin    = array();
    if(!empty($remote_addr))
    {
        $array_ip6 = preg_split("{:}", $remote_addr);
        $tmp_count = 8;
        for($i = 0; $i < count($array_ip6); $i++)
        {
            if($array_ip6[$i] !== "")
            {
                $tmp_count--;
            }
        }
        $j = -1;
        $k_count = 0;
        for($i = count($array_ip6) - 1; $i >= 0; $i--)
        {
            if($array_ip6[$i] !== "")
            {
                unset($tmp);
                $tmp = substr("000". $array_ip6[$i], -4);
                $j++;
                $array_ip6_fin[$j] = $tmp;
            }
            else
            {
                unset($tmp);
                $tmp = "0000";
                while($k_count < $tmp_count)
                {
                    $j++;
                    $array_ip6_fin[$j] = $tmp;
                    $k_count++;
                }
            }
        }
        $addr_remote = "";
        for($i = count($array_ip6_fin) - 1; $i >= 0; $i--)
        {
            unset($tmp);
            $tmp = $array_ip6_fin[$i];
            if($i == (count($array_ip6_fin) - 1))
            {
                $addr_remote = $tmp;
            }
            else
            {
                $addr_remote .= ":" . $tmp;
            }
        }
        $addr_remote = strtolower($addr_remote);
        return((empty($addr_remote)) ? false : $addr_remote);
    }
    else
    {
        return(false);
    }
}

function sanitize($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false)
    {
        return(correct_ip6($ip));
    }
    elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false)
    {
        return(long2ip(ip2long($ip)));
    }
    return false;
}

function get_ip_address()
{
    $array_type_ip = array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR');

    foreach($array_type_ip as $key)
    {
        if(!isset($_SERVER[$key]))
        {
            continue;
        }

        unset($ip);
        $ip = $_SERVER[$key];

        if(!empty($ip))
        {
            $ip = trim($ip);
            if(strpos($ip, ",") !== false)
            {
                $array_ip = explode($ip);
                foreach($array_ip as $ip)
                {
                    unset($tmp_ip);
                    $tmp_ip = sanitize($ip);
                    if(validate_ip($tmp_ip))
                    {
                        return($tmp_ip);
                    }
                }
            }
            else
            {
                $tmp_ip = trim(sanitize($ip));
                if(validate_ip($tmp_ip))
                {
                    return($tmp_ip);
                }
            }
        }
    }
    return(false);
}
?>
 
WRInaute accro
Ah bougre

Il faut aussi urlencoder les paramètres genre urls, ndd et autres joyeusetés.

Mon site est maintenant sous Google Measurement Protocol pour GA mais pas pour Google+.

Comment faire ?

Respectueusement.
 
WRInaute accro
Rebonjour

Voilà il n'y a plus qu'un petit détail : Les sessions.

Le paramètre "sc" a deux valeurs : "start" et "end".

Comment fait-on pour mémoriser le moment du commencement de la session ?

Après, on pourrait à la rigueur faire en fonction du timing, mais comment savoir lors d'une requête quand a eu lieu la requête http antérieure ou $data["sc"] = "start" ?

Si on ne spécifie pas du tout ce paramètre, quelle est la durée de session prise en compte par Google ?

Merci beaucoup de vos réponses.

Amicalement.
 
WRInaute accro
Rebonjour

Une question importante qui intéressera tous les Wrinautes :

Le paramètre referrer ( $data['dr'] ), est-il l'url entière ( $_SERVER['HTTP_REFERER'] ), ou le nom de domaine seulement ?

Hier, j'ai 1 seule visite par Google...

Merci.
 
WRInaute accro
Hé bé

Avec le paramètre "cid" ( Client-ID ), çà marche bien si le 'cid' est un UUID correct ( type RFC4122 Version 4 ).

Cependant, il y a un gros problème avec le Google Measurement Protocol : Les referer provenant de Google sont masqués : Le nombre de visites par recherche est nul.

Par contre, le nombre de visiteurs a drôlement augmenté.

C'est vrai qu'il est maintenant impossible pour le visiteur de refuser d'être mesuré, dites-moi si je ne dois pas laisser le choix, même si strictement aucune données du visiteur sont transmises.

Code:
function UUID()
{
        # $_SERVER['REMOTE_ADDR']
        $ip_address = ip_address();

        # Create an anonymous ID - we double hash with salt, GA won't who's who
        $salt = sha1($_SERVER['SERVER_ADDR'] . $_SERVER['SERVER_NAME'] . $_SERVER['DOCUMENT_ROOT']);
        $hash = sha1($ip_address  . $_SERVER['HTTP_USER_AGENT']);
        $anon_id = sha1($salt . $hash);

        // Binary Value
        $nstr = '';

        // Convert Namespace UUID to bits
        for($i = 0; $i < strlen($anon_id); $i+=2) {
            $nstr .= chr(hexdec(substr($anon_id, $i, 1).substr($anon_id,$i + 1, 1)));
        }

        // Calculate hash value
        $hash = sha1($nstr . $anon_id);

        return sprintf('%08s-%04s-%04x-%04x-%12s',
            // 32 bits for "time_low"
            substr($hash, 0, 8),
            // 16 bits for "time_mid"
            substr($hash, 8, 4),
            // 16 bits for "time_hi_and_version",
            // four most significant bits holds version number 3
            (hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x4000,
            // 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
            (hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
            // 48 bits for "node"
            substr($hash, 20, 12)
        );
}

function is_valid($uuid) {
        return preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?'.
            '[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i', $uuid) === 1;
}

// Usage
// Pseudo-random UUID
$v4uuid = UUID();

if(is_valid($v4uuid))
{
    echo "\t\t\t" . $v4uuid . " is a perfect UUID version 4.\n\n";
}
else
{
    echo "\t\t\t" . $v4uuid . " is an invalid UUID version 4.\n\n";
}
 
Discussions similaires
Haut