Débogueur PostHog
Inspectez et déboguez les implémentations PostHog sur n'importe quel site Web à l'aide d'outils d'automatisation de navigateur. Cette compétence aide les développeurs et les équipes produit à comprendre exactement comment PostHog est configuré et quelles données sont capturées.
Règles critiques
- Demandez toujours l'URL en premier si elle n'est pas fournie.
- Demandez toujours si la page nécessite une connexion. Si oui, guidez l'utilisateur pour se connecter via Chrome d'abord.
- Utilisez les outils de navigateur pour naviguer et inspecter. Préférez Chrome DevTools MCP (
mcp__chrome-devtools__*) ou Playwright MCP (mcp__playwright__*). - Vérifiez plusieurs signaux. PostHog peut être implémenté de différentes manières - vérifiez les scripts, les demandes réseau et l'objet window.
- Signalez les résultats clairement. Résumez ce que vous trouvez dans un format structuré.
- Ne modifiez jamais rien. Ceci est une inspection en lecture seule.
Flux initial
Quand un utilisateur demande d'inspecter une implémentation PostHog :
- Obtenez l'URL (si non fournie)
- Naviguez vers l'URL avec
?__posthog_debug=trueajouté - Vérifiez si la connexion est requise en prenant un snapshot et en cherchant les indicateurs de connexion
- Si la connexion est requise, demandez à l'utilisateur de s'authentifier dans le navigateur
- Une fois authentifié, procédez à l'inspection
Détection des pages de connexion
Après la navigation, prenez un snapshot et cherchez les indicateurs de connexion :
- Le titre de la page contient « login », « sign in », « authenticate »
- L'URL contient « login », « signin », « auth », « sso »
- La page a des champs nom d'utilisateur/mot de passe
- La page affiche des boutons « Sign in with Google/GitHub/etc. »
Flux des pages authentifiées
Si vous détectez une page de connexion ou que l'utilisateur mentionne que la page nécessite une authentification :
-
Gardez le navigateur ouvert - vous y avez déjà navigué
-
Demandez à l'utilisateur de se connecter :
"Cette page nécessite une authentification. Veuillez vous connecter à l'aide du navigateur Chrome que j'ai ouvert. Faites-moi savoir quand vous êtes connecté et sur la page que vous souhaitez inspecter." -
Une fois l'utilisateur confirmé, prenez un nouveau snapshot pour vérifier l'authentification
-
Ajoutez le paramètre debug s'il n'est pas déjà présent et rechargez si nécessaire
-
Procédez à l'inspection
Outils de navigateur disponibles
Chrome DevTools MCP
mcp__chrome-devtools__navigate_page- Naviguer vers une URLmcp__chrome-devtools__take_snapshot- Obtenir l'arbre d'accessibilité de la pagemcp__chrome-devtools__evaluate_script- Exécuter JavaScript pour inspecter PostHogmcp__chrome-devtools__list_network_requests- Voir le trafic réseaumcp__chrome-devtools__get_network_request- Obtenir les détails de la demandemcp__chrome-devtools__list_console_messages- Vérifier les erreurs
Playwright MCP
mcp__playwright__browser_navigate- Naviguer vers une URLmcp__playwright__browser_snapshot- Obtenir un snapshot de la pagemcp__playwright__browser_evaluate- Exécuter JavaScriptmcp__playwright__browser_network_requests- Voir le trafic réseaumcp__playwright__browser_console_messages- Vérifier la console
Flux d'inspection
Étape 1 : Naviguer vers la page en mode débogage
Ajoutez toujours ?__posthog_debug=true à l'URL pour activer le mode débogage de PostHog. Cela affiche les journaux détaillés dans la console.
- Si l'URL n'a pas de chaîne de requête :
https://example.com?__posthog_debug=true - Si l'URL a déjà une chaîne de requête :
https://example.com?foo=bar&__posthog_debug=true
Flux :
- Naviguez vers l'URL avec le paramètre debug
- Prenez un snapshot pour voir ce qui a été chargé
- Vérifiez les indicateurs de page de connexion :
- L'URL s'est redirigée vers
/login,/signin,/auth,/sso - Le titre de la page contient « log in », « sign in »
- La page a des champs de formulaire de connexion
- L'URL s'est redirigée vers
- Si la connexion est détectée :
- Dites à l'utilisateur : « J'ai ouvert la page mais elle nécessite une connexion. Veuillez vous connecter avec Chrome, puis faites-moi savoir quand vous êtes prêt. »
- Attendez la confirmation de l'utilisateur
- Prenez un nouveau snapshot pour vérifier l'authentification
- Ajoutez le paramètre debug à la nouvelle URL si nécessaire
- Si aucune connexion nécessaire : Procédez à l'inspection
Étape 2 : Vérifier l'objet global PostHog
Exécutez JavaScript pour inspecter l'objet posthog sur window :
(() => {
if (typeof posthog === 'undefined') {
return { installed: false };
}
const ph = posthog;
return {
installed: true,
version: ph.version || ph.LIB_VERSION || 'unknown',
config: {
token: ph.config?.token || ph.get_config?.('token') || 'not accessible',
apiHost: ph.config?.api_host || ph.get_config?.('api_host') || 'not accessible',
autocapture: ph.config?.autocapture ?? ph.get_config?.('autocapture') ?? 'not accessible',
capturePageview: ph.config?.capture_pageview ?? ph.get_config?.('capture_pageview') ?? 'not accessible',
capturePageleave: ph.config?.capture_pageleave ?? ph.get_config?.('capture_pageleave') ?? 'not accessible',
sessionRecording: ph.config?.enable_recording_console_log !== undefined ||
ph.sessionRecording?.started ||
'check network',
persistence: ph.config?.persistence || ph.get_config?.('persistence') || 'not accessible',
debug: ph.config?.debug ?? ph.get_config?.('debug') ?? false
},
distinctId: ph.get_distinct_id?.() || 'not accessible',
sessionId: ph.get_session_id?.() || 'not accessible',
featureFlags: ph.getFeatureFlag ? Object.keys(ph.featureFlags?.flags || {}) : [],
activeFeatureFlags: ph.getFeatureFlag ?
Object.entries(ph.featureFlags?.flags || {})
.filter(([_, v]) => v)
.map(([k]) => k) : []
};
})()
Étape 2b : Vérifier PostHog groupé (config distante)
Si posthog n'est pas sur window, vérifiez les implémentations groupées qui utilisent _POSTHOG_REMOTE_CONFIG :
(() => {
const remoteConfig = window._POSTHOG_REMOTE_CONFIG;
if (!remoteConfig) {
return { found: false };
}
const tokens = Object.keys(remoteConfig);
const configs = tokens.map(token => {
const cfg = remoteConfig[token]?.config || {};
return {
token,
hasFeatureFlags: cfg.hasFeatureFlags || false,
autocapture: !cfg.autocapture_opt_out,
sessionRecording: cfg.sessionRecording || false,
heatmaps: cfg.heatmaps || false,
surveys: cfg.surveys || false,
capturePerformance: cfg.capturePerformance || {},
defaultIdentifiedOnly: cfg.defaultIdentifiedOnly || false
};
});
return {
found: true,
bundled: true,
configs
};
})()
Étape 2c : Vérifier la console pour les messages de débogage PostHog
Avec ?__posthog_debug=true, PostHog affiche les journaux détaillés. Utilisez list_console_messages et cherchez les entrées [PostHog.js] :
Messages clés à chercher :
[PostHog.js] Persistence loaded- Affiche le type de persistance (localStorage, sessionStorage, cookie)[PostHog.js] [Surveys] Surveys loaded successfully- Module Surveys chargé[PostHog.js] [Surveys] flags response received, isSurveysEnabled: X- Si les sondages sont activés[PostHog.js] [SessionRecording]- Statut de l'enregistrement de session[PostHog.js] [WebExperiments]- Expériences web/feature flags[PostHog.js] set_config- Changements de configuration
Distinction importante :
- Module chargé = Le fichier JavaScript chargé avec succès
- Fonctionnalité activée = La fonctionnalité est activée dans les paramètres PostHog
Un module peut être chargé mais désactivé. Par exemple :
[PostHog.js] [Surveys] Surveys loaded successfully <- Module chargé
[PostHog.js] [Surveys] flags response received, isSurveysEnabled: false <- Fonctionnalité désactivée
Étape 3 : Vérifier les scripts PostHog
Cherchez les scripts PostHog dans la page :
(() => {
const scripts = Array.from(document.querySelectorAll('script'));
const posthogScripts = scripts.filter(s =>
(s.src && (s.src.includes('posthog') || s.src.includes('ph.js'))) ||
(s.textContent && (s.textContent.includes('posthog.init') || s.textContent.includes('!function(t,e)')))
);
return {
found: posthogScripts.length > 0,
scripts: posthogScripts.map(s => ({
src: s.src || 'inline',
async: s.async,
defer: s.defer,
type: s.type || 'text/javascript'
}))
};
})()
Étape 4 : Vérifier les demandes réseau
Filtrez les demandes réseau pour trouver le trafic PostHog. PostHog peut utiliser :
Domaines standard :
*.posthog.comus.i.posthog.com/eu.i.posthog.comus-assets.i.posthog.com/eu-assets.i.posthog.com
Domaines proxy personnalisés (modèles courants) :
ph.yourcompany.comanalytics.yourcompany.comt.yourcompany.com- N'importe quel domaine avec
/array/phc_dans le chemin (config PostHog)
Points de terminaison à chercher :
/e/ou/capture/- Événements/s/- Enregistrement de session/decide/ou/flags/- Feature flags/batch/- Événements par lot/array/phc_*/config.js- Config distante (implémentations groupées)/static/surveys.js- Module Surveys/static/recorder.js- Module d'enregistrement de session
Comment identifier un proxy personnalisé :
- Cherchez les demandes avec les chemins spécifiques à PostHog (
/flags/,/array/phc_) - Vérifiez les détails de la demande réseau pour les en-têtes PostHog
- Cherchez les tokens
phc_dans les URLs ou corps de demande
Étape 5 : Vérifier les problèmes courants
Exécutez les diagnostics :
(() => {
const issues = [];
// Vérifiez si posthog existe
if (typeof posthog === 'undefined') {
issues.push('PostHog not found on window object');
return { issues };
}
// Vérifiez les instances multiples
if (window.__POSTHOG_INSTANCES__ && window.__POSTHOG_INSTANCES__.length > 1) {
issues.push('Multiple PostHog instances detected - may cause duplicate events');
}
// Vérifiez l'initialisation
if (!posthog.get_distinct_id || !posthog.get_distinct_id()) {
issues.push('PostHog may not be fully initialized');
}
// Vérifiez le mode de consentement
if (posthog.has_opted_out_capturing && posthog.has_opted_out_capturing()) {
issues.push('User has opted out of tracking');
}
// Vérifiez le mode debug en production
const isDebug = posthog.config?.debug || posthog.get_config?.('debug');
const hostname = window.location.hostname;
if (isDebug && !hostname.includes('localhost') && !hostname.includes('127.0.0.1')) {
issues.push('Debug mode is enabled in production');
}
// Vérifiez l'autocapture
const autocapture = posthog.config?.autocapture ?? posthog.get_config?.('autocapture');
if (autocapture === false) {
issues.push('Autocapture is disabled - only manual events will be tracked');
}
return {
issues: issues.length > 0 ? issues : ['No issues detected'],
checksRun: true
};
})()
Étape 6 : Capturer les événements récents (si debug disponible)
Si le mode debug est activé ou si nous pouvons accéder à la file d'attente :
(() => {
if (typeof posthog === 'undefined') return { events: [] };
// Essayez d'obtenir les événements en file d'attente
const queue = posthog._requestQueue?.queue ||
posthog.requestQueue?.queue ||
[];
// Obtenez les événements récents de la persistance si disponible
const stored = posthog.persistence?.props?.$stored_events || [];
return {
queuedEvents: queue.length,
recentEventTypes: [...new Set([...queue, ...stored].map(e => e?.event || 'unknown').slice(0, 20))]
};
})()
Étape 7 : Détecter d'autres outils d'analyse
Analysez les demandes réseau et les scripts pour identifier tous les outils d'analyse/suivi sur la page. Utilisez les modèles connus pour les outils nommés et détectez les scripts de suivi inconnus en secours.
(() => {
const scripts = Array.from(document.querySelectorAll('script[src]')).map(s => s.src);
const hostname = window.location.hostname.replace('www.', '');
const knownTools = [];
const matchedScripts = new Set();
const patterns = {
'Google Analytics': /google-analytics\.com|gtag\/js/i,
'Google Tag Manager': /googletagmanager\.com\/gtm/i,
'Facebook Pixel': /connect\.facebook\.net.*fbevents/i,
'LinkedIn Insight': /snap\.licdn\.com/i,
'HubSpot': /js\.hs-scripts\.com|js\.hsforms\.com/i,
'Hotjar': /static\.hotjar\.com/i,
'Segment': /cdn\.segment\.com/i,
'Mixpanel': /cdn\.mxpnl\.com|mixpanel\.com/i,
'Amplitude': /cdn\.amplitude\.com/i,
'Heap': /heap-analytics\.com|heapanalytics\.com/i,
'Intercom': /widget\.intercom\.io|intercomcdn\.com/i,
'Drift': /js\.driftt\.com/i,
'Zendesk': /static\.zdassets\.com/i,
'Crisp': /client\.crisp\.chat/i,
'FullStory': /fullstory\.com\/s\/fs\.js/i,
'LogRocket': /cdn\.logrocket\.com/i,
'Sentry': /browser\.sentry-cdn\.com/i,
'Datadog': /datadoghq\.com/i,
'Snowplow': /cdn\.snowplow/i,
'Rudderstack': /cdn\.rudderlabs\.com/i,
'Clearbit': /tag\.clearbitscripts\.com/i,
'Dreamdata': /cdn\.dreamdata\.cloud/i,
'GrowthBook': /cdn\.growthbook\.io/i,
'LaunchDarkly': /sdk\.launchdarkly\.com/i,
'Optimizely': /cdn\.optimizely\.com/i,
'VWO': /dev\.visualwebsiteoptimizer\.com/i,
'Ahrefs': /analytics\.ahrefs\.com/i,
'AdRoll': /s\.adroll\.com/i,
'Factors.ai': /app\.factors\.ai/i,
'Vector': /cdn\.vector\.co/i,
'Leadfeeder': /sc\.lfeeder\.com/i,
'Pendo': /cdn\.pendo\.io/i,
'Chameleon': /fast\.chameleon\.io/i,
'Appcues': /fast\.appcues\.com/i,
'UserPilot': /js\.userpilot\.io/i,
'Mouseflow': /cdn\.mouseflow\.com/i,
'Lucky Orange': /tools\.luckyorange\.com/i,
'Crazy Egg': /script\.crazyegg\.com/i,
'Plausible': /plausible\.io\/js/i,
'Fathom': /cdn\.usefathom\.com/i,
'Simple Analytics': /scripts\.simpleanalyticscdn\.com/i,
'Matomo': /matomo\.js|piwik\.js/i,
'Klaviyo': /static\.klaviyo\.com/i,
'Customer.io': /track\.customer\.io/i,
'Braze': /sdk\.iad-\d+\.braze\.com/i,
'OneSignal': /cdn\.onesignal\.com/i,
'Insider': /insr\.io/i,
'Mutiny': /cdn\.mutinycdn\.com/i,
'Qualified': /js\.qualified\.com/i,
'Chilipiper': /js\.chilipiper\.com/i,
'Typekit': /use\.typekit\.net/i,
'Google Fonts': /fonts\.googleapis\.com/i,
'Cookiebot': /consent\.cookiebot\.com/i,
'OneTrust': /cdn\.cookielaw\.org/i,
'TrustArc': /consent\.trustarc\.com/i,
'Osano': /cmp\.osano\.com/i,
'Usercentrics': /app\.usercentrics\.eu/i,
'OpenLI/Legal Monster': /widgets\.legalmonster\.com|openli\.com/i,
'Nelio A/B Testing': /nelio-ab-testing/i,
'Mesh': /mesh-interactive|withmesh\.com/i,
'Reddit Pixel': /redditstatic\.com|rdt\.li/i,
'Webflow': /wdfl\.co|webflow\.com\/js/i,
'Dub.co': /dubcdn\.com|dub\.co/i
};
// Correspondance avec les outils connus
for (const [name, pattern] of Object.entries(patterns)) {
for (const src of scripts) {
if (pattern.test(src)) {
knownTools.push(name);
matchedScripts.add(src);
break;
}
}
}
// Trouvez les scripts de suivi inconnus
const trackingKeywords = /track|analytics|pixel|tag|beacon|collect|measure|metric|event|telemetry|monitor/i;
const unknownScripts = scripts.filter(src => {
if (matchedScripts.has(src)) return false;
try {
const url = new URL(src);
const scriptHost = url.hostname.replace('www.', '');
// Ignorez les scripts du même domaine
if (scriptHost === hostname || scriptHost.endsWith('.' + hostname)) return false;
// Ignorez les CDN courants qui hébergent du code non-suivi
if (/unpkg\.com|jsdelivr\.net|cdnjs\.cloudflare\.com|ajax\.googleapis\.com/i.test(scriptHost)) return false;
// Inclure si c'est un mot-clé de suivi ou d'un tiers
return trackingKeywords.test(src) || true;
} catch {
return false;
}
});
// Extrayez juste le domaine des scripts inconnus pour une sortie plus claire
const unknownDomains = [...new Set(unknownScripts.map(src => {
try {
return new URL(src).hostname;
} catch {
return src;
}
}))].sort();
return {
knownTools: [...new Set(knownTools)].sort(),
unknownScripts: unknownDomains
};
})()
Format de réponse
Après inspection, fournissez un résumé structuré. Soyez factuel et concis - pas de commentaires ni de recommandations sauf si demandé. Utilisez des emoji pour indiquer le statut d'un coup d'œil.
Emojis de statut :
- ✅ = Oui / Activé / Actif / Installé
- ❌ = Non / Désactivé / Non trouvé
- ⚠️ = Avertissement / Problème détecté
## Résumé de l'implémentation PostHog
### Statut
✅ Installé / ✅ Installé (groupé) / ❌ Non trouvé
### Type d'implémentation
[window.posthog global / Groupé (non exposé globalement) / Proxy personnalisé]
### Configuration
- **Version :** [version]
- **API Host :** [host] ([Cloud US/EU] / [Proxy personnalisé] / [Auto-hébergé])
- **Token du projet :** [token complet]
- **Persistance :** [localStorage/sessionStorage/cookie/memory]
### Fonctionnalités (Module chargé → Fonctionnalité activée)
| Fonctionnalité | Module chargé | Activée |
|---|---|---|
| Autocapture | ✅ / ❌ | ✅ / ❌ |
| Enregistrement de session | ✅ / ❌ | ✅ / ❌ |
| Sondages | ✅ / ❌ | ✅ / ❌ |
| Cartes thermiques | ✅ / ❌ | ✅ / ❌ |
| Feature flags | ✅ / ❌ | ✅ / ❌ |
| Web Vitals | ✅ / ❌ | ✅ / ❌ |
### Identifiants
- **Distinct ID :** [id]
- **Session ID :** [id]
### Feature flags
[Liste des flags actifs ou « Aucun chargé »]
### Activité réseau
- Point de terminaison des événements : ✅ / ❌
- Enregistrement de session : ✅ / ❌
- Point de terminaison Decide/flags : ✅ / ❌
- Point de terminaison Surveys : ✅ / ❌
### Problèmes trouvés
✅ Aucun détecté
— ou —
⚠️ [Description du problème]
### Chargement des scripts
- **Source :** [CDN/Auto-hébergé/NPM bundle/Proxy personnalisé]
- **Chargement :** [Async/Sync/Defer]
### Autres outils d'analyse détectés
[Liste des outils d'analyse, de suivi et marketing reconnus]
### Autres scripts externes
[Domaines de scripts tiers non associés à des outils connus]
Questions courantes et comment y répondre
« Comment PostHog est-il implémenté sur cette page ? »
Exécutez le flux d'inspection complet et fournissez un résumé complet.
« Le suivi PostHog fonctionne-t-il ? »
- Vérifiez si l'objet posthog existe
- Vérifiez que les demandes réseau sont envoyées
- Vérifiez les erreurs dans la console
- Cherchez le statut d'opt-out
« Quels événements sont suivi ? »
- Vérifiez le statut de l'autocapture
- Regardez les demandes réseau vers
/e/ou/capture/ - Essayez d'accéder à la file d'attente d'événements
- Notez si $pageview, $pageleave, etc. sont activés
« L'enregistrement de session est-il activé ? »
- Vérifiez la config pour les paramètres d'enregistrement
- Cherchez les demandes réseau
/s/ - Vérifiez l'état de l'objet sessionRecording
« Quels feature flags sont actifs ? »
- Vérifiez l'objet featureFlags sur posthog
- Cherchez la demande réseau
/decide/ - Listez tous les flags et leurs valeurs
« Y a-t-il des problèmes avec l'implémentation ? »
Exécutez les vérifications de diagnostic et signalez les résultats.
« Ceci utilise-t-il le cloud EU ou US ? »
Vérifiez la configuration api_host :
us.i.posthog.com= Cloud USeu.i.posthog.com= Cloud EUapp.posthog.com= Legacy (par défaut US)- Domaine personnalisé = Auto-hébergé ou proxy
Exemple de conversation
Utilisateur : « Comment PostHog est-il implémenté sur https://example.com ? »
Claude : « Je vais naviguer vers example.com en mode debug activé et inspecter l'implémentation PostHog. »
[Navigue vers https://example.com?__posthog_debug=true] [Exécute les vérifications JavaScript] [Vérifie la console pour les messages de débogage PostHog] [Analyse les demandes réseau]
Claude :
## Résumé de l'implémentation PostHog
### Statut
✅ Installé
### Type d'implémentation
window.posthog global
### Configuration
- **Version :** 1.96.1
- **API Host :** https://us.i.posthog.com (Cloud US)
- **Token du projet :** phc_abc123def456ghi789jkl012mno345
- **Persistance :** localStorage+cookie
### Fonctionnalités (Module chargé → Fonctionnalité activée)
| Fonctionnalité | Module chargé | Activée |
|---|---|---|
| Autocapture | ✅ | ✅ |
| Enregistrement de session | ✅ | ✅ |
| Sondages | ✅ | ❌ |
| Cartes thermiques | ❌ | ❌ |
| Feature flags | ✅ | ✅ |
| Web Vitals | ✅ | ✅ |
### Identifiants
- **Distinct ID :** 018d4f2a-1234-7abc-def0-123456789abc
- **Session ID :** 018d4f2a-5678-7xyz-abc0-987654321xyz
### Feature flags
- `new-checkout-flow` ✅
- `beta-features` ❌
### Activité réseau
- Point de terminaison des événements : ✅
- Enregistrement de session : ✅
- Point de terminaison Decide/flags : ✅
- Point de terminaison Surveys : ✅
### Problèmes trouvés
✅ Aucun détecté
### Chargement des scripts
- **Source :** CDN (us-assets.i.posthog.com)
- **Chargement :** Async
### Autres outils d'analyse détectés
- Google Tag Manager
- Google Analytics
- HubSpot
### Autres scripts externes
- cdn.example-vendor.com
Exemple 2 : Page authentifiée avec proxy personnalisé
Utilisateur : « Vérifiez PostHog sur https://app.example.com/dashboard »
Claude : « Je vais naviguer vers cette page en mode debug activé. »
[Navigue vers https://app.example.com/dashboard?__posthog_debug=true] [Prend un snapshot, voit la page de connexion]
Claude : « J'ai ouvert la page mais elle nécessite une connexion. Veuillez vous connecter à l'aide du navigateur Chrome que j'ai ouvert. Faites-moi savoir quand vous êtes sur le tableau de bord. »
Utilisateur : « Je suis connecté »
Claude : [Prend un nouveau snapshot, vérifie l'authentification, exécute l'inspection]
## Résumé de l'implémentation PostHog
### Statut
✅ Installé (groupé)
### Type d'implémentation
Groupé (non exposé globalement) via proxy personnalisé
### Configuration
- **Version :** 1.257.2
- **API Host :** ph.example.com (Proxy personnalisé)
- **Token du projet :** phc_abc123def456ghi789jkl012mno345
- **Persistance :** sessionStorage
### Fonctionnalités (Module chargé → Fonctionnalité activée)
| Fonctionnalité | Module chargé | Activée |
|---|---|---|
| Autocapture | ✅ | ❌ |
| Enregistrement de session | ❌ | ❌ |
| Sondages | ✅ | ❌ |
| Cartes thermiques | ❌ | ❌ |
| Feature flags | ✅ | ✅ |
| Web Vitals | ✅ | ❌ |
### Identifiants
- **Distinct ID :** (non accessible - groupé)
- **Session ID :** (non accessible - groupé)
### Activité réseau
- Point de terminaison des événements : ✅
- Enregistrement de session : ❌
- Point de terminaison Decide/flags : ✅
- Point de terminaison Surveys : ✅ (module chargé, fonctionnalité désactivée)
### Problèmes trouvés
✅ Aucun détecté
### Chargement des scripts
- **Source :** Proxy personnalisé (ph.example.com)
- **Chargement :** Groupé dans l'app