Construire
installer posthog sans bandeau de consentement cookies
Script de reproduction · posthog-cookieless-storage-check.mjs · mis à jour le 2026-08-06
Si le plan consiste à ajouter PostHog, puis à coller un bandeau de consentement par-dessus, on peut souvent se passer du bandeau, mais la raison est plus précise que « PostHog respecte la vie privée ». Un tracker exige le consentement quand il lit ou écrit sur le dispositif du visiteur. Configurez posthog-js pour qu'il n'écrive rien, et ce déclencheur ne s'active jamais. C'est exactement la configuration que nous utilisons sur ce site, et l'artefact de cette page le prouve en conditions réelles : zéro cookie, zéro localStorage, zéro sessionStorage après un pageview. Le piège : « cookieless » désigne deux fonctionnalités distinctes dans PostHog, et la plus évidente fausse silencieusement vos comptages. C'est tout l'objet de cette page.
Prérequis
Un projet PostHog (ce site utilise EU Cloud) et posthog-js chargé dans un bundle client. Rien ici ne nécessite de SDK serveur.
Une décision à prendre avant d'écrire la moindre ligne, car elle est structurante : vous renoncez aux profils individuels, au session replay et à toute notion de visiteur récurrent. Pas de cohortes, pas de courbe de rétention, pas de funnel multi-visite. Si vous avez besoin de l'un de ces éléments, cette approche ne vous convient pas et le bandeau est obligatoire. Dites-le clairement maintenant, car chaque option ci-dessous existe pour tenir cette ligne, et en rouvrir une rouvre la question du consentement. C'est le même arbitrage que nous avons documenté pour notre propre funnel : nous mesurons les transitions au sein d'une session unique et acceptons que les chiffres absolus de visiteurs uniques soient un plafond, pas un comptage.
Vous aurez également besoin d'un moyen de transmettre la clé de projet au client au moment du build, pas seulement à l'exécution. L'étape 4 explique pourquoi ce n'est pas la même chose.
Étapes
1. Initialisez avec les cinq options qui n'écrivent rien. C'est l'init exacte que ce site utilise :
import posthog from 'posthog-js'
posthog.init(key, {
api_host: 'https://eu.i.posthog.com',
persistence: 'memory', // not cookie, not localStorage
person_profiles: 'never', // no individual identifier is ever sent
capture_pageview: false, // captured manually, see step 2
capture_pageleave: false,
disable_session_recording: true,
})
persistence: 'memory' maintient l'identifiant de session en mémoire JavaScript uniquement. person_profiles: 'never' empêche la création de tout profil identifié. disable_session_recording: true compte plus qu'il n'y paraît : le replay capture l'écran, ce qui sur un formulaire ou un chat signifie capturer ce que le visiteur tape, et ça seul vous ramènerait dans le champ du consentement.
2. Capturez les pageviews manuellement au changement de route. Avec capture_pageview: false, vous les déclenchez vous-même. Dans le Next.js App Router, lisez usePathname, pas useSearchParams :
'use client'
import { useEffect } from 'react'
import { usePathname } from 'next/navigation'
export function PageviewTracker() {
const pathname = usePathname()
useEffect(() => {
posthog.capture('$pageview', { $current_url: window.location.href })
}, [pathname])
return null
}
useSearchParams dans un composant client force la route entière hors du prerender statique vers le rendu dynamique : un coût payé sur chaque page pour un signal rarement utile. usePathname seul ne suspend pas et laisse le prerender intact.
3. Transmettez la clé au moment du build, pas seulement à l'exécution. Si vos pages marketing sont prérendues, la clé est gravée dans le HTML pendant next build. Une clé injectée seulement au démarrage du container rend l'analytics mort sur toutes les pages statiques, sans aucune erreur visible. Passez-la comme argument de build Docker et lisez-la dans le composant serveur qui rend le provider, puis transmettez-la en prop. Une lecture process.env côté client ne fonctionnera pas : sans le préfixe NEXT_PUBLIC_, la valeur n'est jamais inlinée, et ajouter ce préfixe publie la clé dans le bundle, ce qui pour une clé de projet est acceptable, mais doit être un choix délibéré, pas un accident.
4. Désactivez aussi le session replay dans les paramètres du projet. posthog-js peut démarrer un enregistrement quand la fonctionnalité est activée côté serveur, donc le flag dans le code n'est que la moitié du verrou. Désactivez-le également dans le projet PostHog. Deux verrous, car chacun peut être défait sans toucher à l'autre.
Le piège que la doc passe sous silence
« Cookieless » désigne deux fonctionnalités, et choisir la mauvaise fausse silencieusement vos chiffres. L'approche ci-dessus (persistence: 'memory') n'écrit rien, mais la persistence en mémoire dure exactement un pageview. Chaque chargement complet de page, et chaque visiteur qui atterrit directement sur une URL, démarre une nouvelle session que PostHog comptabilise comme une nouvelle personne. Les soft navigations internes restent dans une même session, donc les tendances tiennent, mais votre nombre absolu de visiteurs uniques est gonflé et doit être lu comme un plafond. La plupart des tutoriels qui montrent persistence: 'memory' ne le mentionnent jamais, et c'est pourtant la chose la plus importante à savoir avant de faire confiance à un tableau de bord construit dessus.
L'autre fonctionnalité cookieless de PostHog résout réellement le problème de comptage : le cookieless server hash mode, activé avec cookieless_mode: 'always', que vous devez d'abord activer dans Project Settings → Web analytics. Il identifie les visiteurs uniques via un hash serveur quotidiennement salé de l'IP et du user agent : rien n'est stocké sur le dispositif, mais le comptage est bien plus fiable qu'avec la persistence en mémoire. La contrepartie est réelle : vous ne pouvez pas appeler identify(), le sel quotidien fait qu'un visiteur récurrent apparaît comme nouveau le lendemain, les collisions d'IP et de user agent fusionnent deux personnes en une, et GeoIP, détection de bots, session replay et sondages ne sont pas disponibles. C'est le bon outil quand le comptage importe plus que l'identité, ce qui est une décision différente de celle de cette page.
Le comportement par défaut de la bibliothèque n'est pas cookieless. Omettez les options et posthog-js tourne avec persistence: 'localStorage+cookie'. L'artefact mesure exactement ça : la configuration par défaut dépose un cookie ph_..._posthog ainsi que des clés localStorage et sessionStorage, tandis que notre configuration laisse les trois vides. Oubliez les deux options ci-dessus et vous redéposez un cookie sans vous en rendre compte, bandeau inclus. Un ancien rapport (posthog-js issue #614) affirmait que les configurations « cookieless » déposaient encore un cookie, ce qui explique précisément pourquoi l'artefact mesure plutôt que fait confiance. Sur posthog-js 1.405.3, ça ne se reproduit plus.
« Pas de bandeau » couvre PostHog, pas votre page. Des polices tierces, une carte ou une vidéo intégrée, un widget de support, des tags marketing : chacun conserve sa propre question de consentement. Retirer PostHog de la liste ne vide pas la liste.
N'écrire rien n'est pas l'exemption « mesure d'audience » de la CNIL, et la différence joue en votre faveur. L'exemption CNIL est une tolérance étroite pour les trackers que vous déposez bien : mesure d'audience ou A/B testing uniquement, sans recoupement avec d'autres données, périmètre limité à un seul éditeur, dernier octet de l'IP tronqué, durée de vie de 13 mois, et utilisateurs informés avec possibilité d'opposition. La CNIL elle-même note que la plupart des grandes offres d'audience ne répondent pas aux critères. Ne rien stocker sur le dispositif échappe à ce test, car le déclencheur lecture/écriture ne s'active jamais. C'est une position plus solide, mais ce n'est pas un pass automatique : la conformité n'est pas un booléen, donc maintenez la mention mesure d'audience dans votre politique de confidentialité et minimisez les données. Nous sommes ingénieurs, pas vos avocats, et ceci est un cadrage, pas un conseil juridique.
Vérifier
Exécutez l'artefact. npm i posthog-js@1.405.3 playwright, npx playwright install chromium, puis node posthog-cookieless-storage-check.mjs. Il charge le build navigateur réel, l'initialise une fois avec la configuration de ce site et une fois avec les valeurs par défaut, déclenche un pageview dans chaque cas et lit tous les stores client. Vous devriez voir le même résultat que nous : la configuration cookieless n'écrit rien, la configuration par défaut écrit un cookie ph_* et des clés de stockage. Il sort avec un code non nul si le côté cookieless laisse jamais fuiter une clé, ce qui en fait également un test de régression lors de chaque mise à jour de posthog-js.
Vérifiez votre propre application dans les devtools. Ouvrez Application → Storage. Après plusieurs soft navigations et un rechargement complet, Cookies, Local Storage et Session Storage doivent tous rester vides d'entrées ph_*. Basculez ensuite persistence sur 'localStorage+cookie' le temps d'un test et observez le cookie apparaître : vous avez ainsi la preuve que votre vérification peut échouer, pas seulement réussir.
Confirmez que la clé a bien atteint le client. Le chemin sans clé est un no-op silencieux par conception, donc un build vert ne prouve rien ici. La seule preuve réelle est un $pageview qui atterrit dans les événements live de PostHog après déploiement. C'est le même raisonnement qui justifie l'instrumentation dès le départ : vous ne pouvez pas corriger une erreur Anthropic 529 overloaded_error que vous n'avez jamais enregistrée, ni une boucle de récursion incontrôlée qui ne se manifeste que comme coût, et vous ne pouvez pas lire un funnel que vous avez eu peur de mesurer. C'est l'analytics que nous déployons sur nos propres systèmes agentiques, choisi pour que la mesure ne coûte rien au visiteur.
Sources
Les noms des options de persistence et leur comportement exact proviennent de la documentation JavaScript persistence de PostHog ; les deux modes cookieless, le paramètre de projet requis et la restriction sur identify() proviennent du tutoriel cookieless tracking et de la documentation conformité RGPD. La revendication historique de fuite de cookie est posthog-js issue #614. Les conditions de l'exemption consentement sont la Fiche n°16 de la CNIL. Le comportement de stockage rapporté ici a été mesuré sur posthog-js 1.405.3 avec Playwright et Chromium le 2026-08-06 en exécutant l'artefact, qui imprime le comportement de votre version installée et c'est la raison pour laquelle il est livré.
Cas rapportés
Juste votre email, rien d’autre à remplir. Alex vous répond.