La limite de « 360 jours de stockage des ID utilisateur » annoncée par GA4 à la mi-2024, couplée à l'obligation du Consent Mode v2 en mars 2024, a confronté les équipes marketing à un dilemme : accepter que le taux de consentement des banneau cookies chute sous les 40 % et perdre l'infrastructure de segmentation construite depuis l'ère UA, ou découvrir comment bâtir une nouvelle stack de mesure fonctionnant sans cookie. Fusionner des outils d'analytique privacy-first comme Plausible avec une architecture d'agrégation côté serveur est devenu la solution technique de ce scénario.
La Barrière Cookies Franchit 60 %
Depuis 2017, ITP (Intelligent Tracking Prevention) d'Apple bloque les cookies tiers dans Safari. Chrome a défini Privacy Sandbox comme comportement par défaut au Q4 2024. Firefox maintient la protection contre le suivi activée. Selon le rapport 2025 de Mozilla, l'utilisateur européen moyen clique sur « Refuser » ou ferme le banneau cookies dans 62 % des cas. Le nombre de sessions marquées consent_status=denied dans les propriétés GA4 B2C s'est stabilisé entre 55 et 65 % à partir du Q4 2024.
Cela signifie que les pixels client-side classiques (gtag.js, fbq) perdent plus de la moitié du trafic. La fonction « modeled conversion » de GA4 tente de combler ce vide par des estimations de régression plutôt que par des événements réels. Les tests d'incrémentalité montrent que les conversions modélisées dévient de 18 à 22 % en moyenne par rapport aux vraies données (documentation beta Google Marketing Platform 2025).
Le suivi sans cookie repose alors sur deux architectures : la première collecte entièrement côté serveur (GTM serveur, Segment, RudderStack) ; la seconde génère une identité éphémère côté client (sessionStorage/localStorage) transmise au serveur. Plausible Analytics emprunte cette deuxième voie, mais l'identité n'est jamais persistée — chaque session reçoit un nouveau hash. À première vue, il semblerait impossible de tracer un parcours utilisateur ; en réalité, l'agrégation côté serveur rend possibles les analyses de cohortes et les mesures de rétention.
Architecture Plausible : Event Stream via Beacon POST
Plausible Analytics est une plateforme d'analytique open-source (licence MIT, plausible.io). Le script ne pèse que 1,4 KB (GA4 : 43 KB, Segment : 28 KB) ; il n'écrit aucun cookie ; la conformité RGPD/KVKK/CCPA est garantie par défaut. Fonctionnement :
Script client :
// Implémentation minimale plausible.js
(function(){
const endpoint = 'https://analytics.example.com/api/event';
const sessionHash = btoa(navigator.userAgent + performance.timing.navigationStart).substring(0,16);
function sendEvent(name, props = {}) {
navigator.sendBeacon(endpoint, JSON.stringify({
n: name, // nom de l'événement
u: location.href, // URL de la page
d: document.domain,
r: document.referrer,
w: window.innerWidth,
h: sessionHash, // identifiant de session éphémère
p: props // propriétés personnalisées
}));
}
sendEvent('pageview');
// Suivi des clics
document.addEventListener('click', (e) => {
if (e.target.matches('[data-track]')) {
sendEvent('click', { element: e.target.dataset.track });
}
});
})();
L'API navigator.sendBeacon émet un POST HTTP sans cookie. Le sessionHash est généré côté client et non persévéré (il disparaît à la fermeture de l'onglet). Ce hash relie les pages vues au sein d'une même session, mais n'identifie pas le même utilisateur sur plusieurs jours.
Côté serveur (écrit en Elixir/Phoenix) : Les événements reçus sont insérés dans ClickHouse (base de données time-series). ClickHouse est le moteur par défaut dans une installation self-hosted de Plausible ; la version cloud utilise une instance ClickHouse managée. Schéma de la table :
CREATE TABLE events (
timestamp DateTime,
domain String,
pathname String,
referrer String,
session_hash String,
event_name String,
props Map(String, String),
user_agent String,
country String,
device_type Enum8('desktop'=1, 'mobile'=2, 'tablet'=3)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (domain, toDate(timestamp), session_hash);
Les requêtes d'agrégation s'exécutent très rapidement dans le moteur MergeTree de ClickHouse : interroger 100 M d'événements pour obtenir « sessions uniques par jour » retourne en 200-400 ms.
Agrégation Côté Serveur : Session → Cohorte → Rétention
Le tableau de bord Plausible affiche des « sessions uniques » plutôt que des « visiteurs uniques ». Or, en analyse marketing, une session ne suffit pas : les projections de LTV, l'attribution de campagne et l'analyse par cohorte demandent une identité utilisateur. La clé pour le faire sans cookie : résolution d'identité côté serveur + couche d'agrégation.
Scénario : un site e-commerce collecte des événements Plausible et les exporte vers BigQuery. Lorsqu'un utilisateur se connecte, l'ID utilisateur est envoyé comme propriété personnalisée :
// Page de checkout, après connexion
plausible('Login', { props: { user_id: '{{user.id}}' } });
Un job batch quotidien dans BigQuery fusionne les événements Plausible en s'appuyant sur user_id :
-- Modèle dbt : user_sessions_daily.sql
WITH raw_events AS (
SELECT
timestamp,
session_hash,
JSON_EXTRACT_SCALAR(props, '$.user_id') AS user_id,
pathname,
event_name
FROM `analytics.plausible_events`
WHERE DATE(timestamp) = CURRENT_DATE - 1
),
identified_sessions AS (
SELECT
session_hash,
FIRST_VALUE(user_id IGNORE NULLS) OVER (
PARTITION BY session_hash ORDER BY timestamp
) AS resolved_user_id
FROM raw_events
)
SELECT
e.timestamp,
e.session_hash,
COALESCE(i.resolved_user_id, e.session_hash) AS user_key,
e.pathname,
e.event_name
FROM raw_events e
LEFT JOIN identified_sessions i USING (session_hash);
Dans ce modèle, user_key est soit l'ID utilisateur connecté, soit le session_hash pour les sessions anonymes. Les calculs de rétention peuvent désormais s'appuyer sur user_key :
-- Cohorte de rétention 7 jours
SELECT
DATE_TRUNC(first_seen, WEEK) AS cohort_week,
COUNT(DISTINCT user_key) AS cohort_size,
COUNT(DISTINCT CASE WHEN day_7_active THEN user_key END) AS retained_d7,
SAFE_DIVIDE(
COUNT(DISTINCT CASE WHEN day_7_active THEN user_key END),
COUNT(DISTINCT user_key)
) AS retention_rate
FROM user_retention_facts
GROUP BY 1;
Les sessions anonymes (sans connexion) entrent dans cette analyse, mais sont exclues des calculs de LTV long terme — impossible de les suivre au-delà d'une journée. Sur un site où le taux de connexion atteint 30 %, on mesure néanmoins la rétention de 30 % de la cohorte sur une base utilisateur réelle, profondeur équivalente à celle de GA4 sous 35-40 % de consentement, mais sans aucun risque de violation RGPD.
Comparaison GA4 : Conformité vs. Granularité
Avantages de GA4 :
- User ID + Google Signals permettent le suivi multi-appareils (avec consentement)
- Export BigQuery natif, schéma stable
- Rapports d'entonnoir et d'exploration de parcours prêts à l'emploi dans l'interface
- Intégration Google Ads en un clic
Inconvénients de GA4 :
- Consent Mode v2 obligatoire → données modélisées quand
consent_status=denied - Stockage d'ID utilisateur 360 jours (réinitialisation après 14 mois)
- Script de 43 KB (30 fois celui de Plausible)
- L'export ClickStream requiert GA360 (150 K $ par an minimum)
Avantages de Plausible + stack serveur :
- Aucun cookie → banneau RGPD optionnel (simplification radicale)
- Propriété des données : raw data sous ton contrôle (ClickHouse, BigQuery, S3)
- Script ultraléger → impact <5 ms sur le temps de chargement
- Option self-hosted disponible (données restent en Europe)
Inconvénients de Plausible :
- Pas de suivi multi-appareils (sauf pour utilisateurs connectés)
- L'analyse d'entonnoir/parcours demande du SQL personnalisé
- L'intégration Ads/Meta Meta Conversion API requiert un pipeline custom
Comparaison des coûts (100 M événements/mois) :
- GA4 standard : gratuit, mais pas d'export BigQuery (GA360 : 150 K $/an)
- Plausible Cloud : 200 $/mois plan Business (limite 200 K pageviews/mois, self-host au-delà)
- Plausible self-hosted + ClickHouse (AWS c6g.2xlarge + 500 GB SSD) : ~350 $/mois
- Agrégation quotidienne BigQuery : ~80 $/mois
Total Plausible stack : ~430 $/mois. GA360 : 12,5 K $/mois. Différence : 30x moins cher.
Résolution d'Identité Probabiliste
Identifier les utilisateurs non connectés au-delà d'une session emploie la résolution d'identité probabiliste. Le fingerprinting est interdit (RGPD, Directive ePrivacy) mais l'agrégation côté serveur de signaux produit un résultat similaire.
Combinaison : user_agent + subnet IP + timezone + résolution écran génère un hash :
-- BigQuery UDF : probabilistic_user_id
CREATE TEMP FUNCTION probabilistic_user_id(ua STRING, ip STRING, tz STRING, res STRING)
RETURNS STRING
AS (
TO_BASE64(SHA256(CONCAT(
REGEXP_EXTRACT(ua, r'^[^/]+'), -- famille de navigateur
NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(ip), 24), -- subnet /24
tz,
res
)))
);
SELECT
timestamp,
session_hash,
probabilistic_user_id(user_agent, ip_address, timezone, screen_resolution) AS prob_user_id
FROM plausible_events;
Cette méthode n'est pas infaillible (collisions probabilistes entre utilisateurs : ~2-4 %), mais, dans le cadre de Données First-Party & Architecture de Mesure, combiner signaux déterministes (user_id) et probabilistes (hash) crée des cohortes « floues ». Ces cohortes affichent une rétention avec une déviation inférieure aux données modélisées de GA4 : tests A/B internes montrent ~8 % de déviation contre 18-22 % pour GA4 modeled.
Conformité KVKK : Contrats de Traitement et Conservation
Article 5 KVKK : « Les données personnelles doivent être traitées pour des finalités déterminées, explicites et légitimes. » L'adresse IP + user agent combinés constituent un « identifiant indirect ». Plausible récupère l'IP côté serveur mais ne l'écrit jamais dans ClickHouse — seul le champ country (issu d'une recherche GeoIP) est conservé, puis l'IP est supprimée.
En installation self-hosted, ce flux reste sous ton contrôle :
# lib/plausible/ingestion/event.ex (simplifié)
defmodule Plausible.Ingestion.Event do
def process(conn, params) do
ip = get_ip_address(conn)
country = GeoIP.lookup(ip) |> Map.get(:country_code)
event = %{
timestamp: DateTime.utc_now(),
domain: params["d"],
session_hash: params["h"],
country: country,
# L'IP est supprimée ici
}
ClickHouse.insert("events", event)
end
end
Article 7 KVKK : « Les données personnelles peuvent être conservées aussi longtemps que la finalité du traitement l'exige. » Rétention analytique typique : 24-36 mois. TTL basé sur partition dans ClickHouse :
ALTER TABLE events
MODIFY TTL toDate(timestamp) + INTERVAL 36 MONTH;
Les partitions se suppriment automatiquement après 36 mois. Dans GA4, les données au niveau utilisateur se réinitialisent après 14 mois (user_pseudo_id) ; l'export BigQuery peut s'étendre jusqu'à 60 mois, mais cet export requiert GA360 (non disponible sans souscription premium).
Contrat de Traitement KVKK : Avec Plausible Cloud, signer un DPA (Data Processing Agreement) est obligatoire. Plausible héberge en Europe (Hetzner, Allemagne) et fournit un modèle de DPA conforme au RGPD. En self-hosted, tu es le seul « responsable du traitement » ; il n'existe pas de « sous-traitant ».
Intégration Conversion API : Renvoi d'Événements Côté Serveur
Transférer les événements Plausible vers Meta/Google Ads repose sur un pipeline Webhook. Plaus