Serveurs MCP : rendre Google Analytics vraiment utile pour les développeurs
Comment les serveurs Model Context Protocol transforment Google Analytics d'un tableau de bord marketing en une source de données interrogeable en langage naturel.

Google Analytics a toujours été un outil marketing que les développeurs tolèrent. Vous configurez le tracking, paramétrez les événements, puis passez le relais à quelqu'un qui apprécie réellement de cliquer dans des tableaux de bord. Quand vous avez besoin de données vous-même — taux de rebond pour une page spécifique, entonnoirs de conversion pour une nouvelle fonctionnalité, utilisateurs actifs en temps réel segmentés par pays — vous finissez par naviguer dans cinq menus imbriqués, lutter avec le constructeur de requêtes GA4, et vous demander pourquoi il faut plus d'effort pour poser une question que pour y répondre.
Model Context Protocol change tout cela. En encapsulant l'API de reporting de GA4 dans un serveur MCP, vous pouvez interroger vos données analytics de manière conversationnelle via Claude ou tout assistant IA compatible MCP. Pas de tableaux de bord. Pas de constructeurs de requêtes. Demandez simplement ce que vous voulez savoir.
Ce qu'est MCP et pourquoi c'est important
Model Context Protocol est un standard ouvert créé par Anthropic qui définit comment les assistants IA interagissent avec les sources de données et outils externes. Pensez-y comme un port USB-C pour l'IA — une interface universelle qui permet à tout assistant compatible de se connecter à toute source de données compatible sans code d'intégration personnalisé pour chaque combinaison.
Avant MCP, connecter un assistant IA à vos données analytics signifiait construire un pipeline sur mesure : exporter les données en CSV, les coller dans un chat, espérer que la fenêtre de contexte soit assez grande. Ou construire une intégration API personnalisée, écrire des templates de prompts, gérer l'authentification vous-même. Chaque nouvelle source de données nécessitait une nouvelle intégration.
MCP standardise cela en trois concepts :
- Resources — les données structurées que le serveur expose (vos propriétés GA4, rapports, dimensions, métriques)
- Tools — les actions que l'IA peut invoquer (exécuter un rapport, interroger les données en temps réel, lister les métriques disponibles)
- Prompts — les templates de prompts réutilisables que le serveur fournit (requêtes analytics courantes pré-structurées pour de bons résultats)
Le serveur gère l'authentification, la récupération des données et le formatage des réponses. L'assistant IA gère la compréhension du langage naturel et l'interprétation des résultats. Aucun des deux côtés n'a besoin de connaître les détails d'implémentation de l'autre.
Pourquoi c'est important pour l'analytics en particulier
Les plateformes analytics sont riches en informations mais pauvres en interactions. GA4 dispose de données extraordinairement puissantes — il suit chaque session utilisateur, chaque page vue, chaque événement, chaque conversion à travers l'ensemble de votre produit. Mais accéder à ces données nécessite de penser dans le vocabulaire de GA4 : dimensions, métriques, segments, plages de dates, filtres, comparaisons. Vous devez traduire votre question dans le modèle de requête de GA4 avant de pouvoir obtenir une réponse.
Un serveur MCP inverse cela. Vous posez votre question en langage naturel. L'IA la traduit dans les bons appels API, les exécute et interprète les résultats. La friction entre "j'ai une question" et "j'ai une réponse" passe de minutes à secondes.
Construire un serveur MCP pour GA4
L'implémentation comporte trois couches : le framework du serveur MCP, le client de l'API Google Analytics Data, et la logique de liaison qui mappe l'intention en langage naturel vers les appels API.
Configuration du projet
mkdir ga4-mcp-server
cd ga4-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk @google-analytics/data zod dotenv
npm install -D typescript @types/node
Le package @modelcontextprotocol/sdk fournit le framework serveur. @google-analytics/data est la bibliothèque client officielle de Google pour l'API GA4 Data (l'API de reporting, pas l'API Admin). zod gère la validation des entrées pour les paramètres des outils.
Authentification avec Google
L'authentification de l'API GA4 utilise un compte de service Google Cloud. Créez-en un dans la Google Cloud Console, téléchargez le fichier de clé JSON et accordez-lui l'accès "Lecteur" à votre propriété GA4.
// src/analytics-client.ts
import { BetaAnalyticsDataClient } from "@google-analytics/data";
const analyticsClient = new BetaAnalyticsDataClient({
keyFilename: process.env.GOOGLE_APPLICATION_CREDENTIALS,
});
const propertyId = process.env.GA4_PROPERTY_ID;
export async function runReport(
dimensions: string[],
metrics: string[],
startDate: string,
endDate: string,
dimensionFilter?: Record<string, string>
) {
const request: any = {
property: `properties/${propertyId}`,
dimensions: dimensions.map((d) => ({ name: d })),
metrics: metrics.map((m) => ({ name: m })),
dateRanges: [{ startDate, endDate }],
};
if (dimensionFilter) {
const filterKey = Object.keys(dimensionFilter)[0];
request.dimensionFilter = {
filter: {
fieldName: filterKey,
stringFilter: {
value: dimensionFilter[filterKey],
matchType: "EXACT",
},
},
};
}
const [response] = await analyticsClient.runReport(request);
return formatReportResponse(response);
}
function formatReportResponse(response: any) {
if (!response.rows || response.rows.length === 0) {
return { data: [], summary: "No data found for the specified query." };
}
const headers = [
...(response.dimensionHeaders?.map((h: any) => h.name) ?? []),
...(response.metricHeaders?.map((h: any) => h.name) ?? []),
];
const rows = response.rows.map((row: any) => {
const values = [
...(row.dimensionValues?.map((v: any) => v.value) ?? []),
...(row.metricValues?.map((v: any) => v.value) ?? []),
];
return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
});
return {
data: rows,
rowCount: response.rowCount,
summary: `Returned ${rows.length} rows.`,
};
}
Le serveur MCP
// src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { runReport, getRealtimeData, getAvailableMetrics } from "./analytics-client";
const server = new McpServer({
name: "ga4-analytics",
version: "1.0.0",
});
// Tool: Run a custom report
server.tool(
"run_report",
"Run a Google Analytics 4 report with specified dimensions, metrics, and date range",
{
dimensions: z.array(z.string()).describe("GA4 dimensions like 'pagePath', 'country', 'deviceCategory'"),
metrics: z.array(z.string()).describe("GA4 metrics like 'activeUsers', 'sessions', 'bounceRate'"),
startDate: z.string().describe("Start date in YYYY-MM-DD format or relative like '7daysAgo'"),
endDate: z.string().describe("End date in YYYY-MM-DD format or 'today'"),
filter: z.record(z.string()).optional().describe("Optional dimension filter as key-value pair"),
},
async ({ dimensions, metrics, startDate, endDate, filter }) => {
const result = await runReport(dimensions, metrics, startDate, endDate, filter);
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
);
// Tool: Get real-time active users
server.tool(
"realtime_users",
"Get current real-time active users, optionally segmented by a dimension",
{
dimension: z.string().optional().describe("Optional dimension to segment by, like 'country' or 'pagePath'"),
},
async ({ dimension }) => {
const result = await getRealtimeData(dimension);
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
);
// Tool: List available metrics and dimensions
server.tool(
"list_metrics",
"List all available GA4 metrics and dimensions for the connected property",
{},
async () => {
const result = await getAvailableMetrics();
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
);
// Resource: Property metadata
server.resource(
"property-info",
"ga4://property/info",
async (uri) => ({
contents: [{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify({
propertyId: process.env.GA4_PROPERTY_ID,
description: "Connected GA4 property for analytics queries",
}),
}],
})
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(console.error);
Cela donne à l'assistant IA trois outils : exécuter des rapports arbitraires, vérifier les données en temps réel et découvrir quelles métriques et dimensions sont disponibles. L'outil de découverte est important — il permet à l'IA de trouver les bons noms de champs sans que vous ayez à vous souvenir s'il s'agit de activeUsers ou active_users ou totalUsers.
Endpoint de données en temps réel
// Added to analytics-client.ts
export async function getRealtimeData(dimension?: string) {
const request: any = {
property: `properties/${propertyId}`,
metrics: [{ name: "activeUsers" }],
};
if (dimension) {
request.dimensions = [{ name: dimension }];
}
const [response] = await analyticsClient.runRealtimeReport(request);
return formatReportResponse(response);
}
Les données en temps réel sont l'une des fonctionnalités à plus forte valeur ajoutée. Dans un tableau de bord, vous navigueriez vers la section temps réel, attendriez le chargement et liriez les chiffres. Via MCP, vous tapez "combien de personnes sont sur le site en ce moment ?" et obtenez une réponse en deux secondes.
Des requêtes concrètes que les développeurs veulent vraiment exécuter
Les capacités théoriques sont ennuyeuses. Voici les requêtes que j'exécute réellement au quotidien et à quoi elles ressemblent sous forme de demandes conversationnelles à l'IA :
Analyse du trafic
"Quelles sont les 10 pages les plus visitées par nombre de sessions cette semaine, et comment chacune se compare-t-elle à la semaine dernière ?"
L'IA traduit cela en deux appels runReport — un pour la semaine en cours, un pour la semaine précédente — puis calcule le delta et présente un tableau comparatif. Dans l'interface GA4, cela nécessite de configurer une plage de dates de comparaison, de sélectionner le bon rapport, d'ajouter la dimension page, de trier par sessions et de limiter à 10. Via MCP, c'est une seule phrase.
"Montre-moi le trafic provenant de la recherche organique sur les 30 derniers jours, ventilé par page d'atterrissage."
Cela devient un seul rapport avec sessionDefaultChannelGroup comme filtre de dimension (filtré sur "Organic Search"), landingPagePlusQueryString comme dimension, et sessions plus engagedSessions comme métriques.
Débogage de conversions
"Quel est le taux de rebond sur /pricing comparé à /features sur les deux dernières semaines ?"
Deux appels de rapport filtrés, résultats comparés côte à côte. C'est le genre de question qui prend 30 secondes à poser de manière conversationnelle et 3 minutes à répondre via l'interface GA4.
"Quels pays ont le taux de conversion le plus élevé pour l'événement d'inscription ?"
Un seul rapport avec la dimension country, la métrique eventCount filtrée sur l'événement sign_up, et sessions pour calculer le taux de conversion. L'IA peut même faire la division et présenter directement les pourcentages.
Suivi de performance
"Quel est le temps d'engagement moyen par session sur mobile vs desktop ce mois-ci ?"
Segmenté par deviceCategory, mesurant averageSessionDuration et engagedSessions. Requête simple, mais qui nécessite de naviguer vers le bon rapport et de configurer les segments dans GA4.
"Y a-t-il des pages avec plus de 1000 vues cette semaine mais un taux d'engagement inférieur à 30 % ?"
C'est là que l'analytics conversationnel brille vraiment. L'IA exécute le rapport, filtre les résultats de manière programmatique et ne renvoie que les pages qui correspondent aux deux critères. Dans GA4, il faudrait exporter vers un tableur et filtrer manuellement, ou construire une exploration personnalisée.
Connexion à Claude et aux assistants IA
Configuration de Claude Desktop
Une fois votre serveur MCP construit, le connecter à Claude Desktop est une simple modification de fichier de configuration :
{
"mcpServers": {
"ga4-analytics": {
"command": "node",
"args": ["/path/to/ga4-mcp-server/dist/server.js"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account-key.json",
"GA4_PROPERTY_ID": "123456789"
}
}
}
}
Sur macOS, cela va dans ~/Library/Application Support/Claude/claude_desktop_config.json. Sur Windows, c'est %APPDATA%\Claude\claude_desktop_config.json.
Après avoir redémarré Claude Desktop, les outils GA4 apparaissent dans le menu des outils. Claude peut maintenant les appeler directement dans la conversation.
Intégration avec Claude Code
Pour les développeurs qui travaillent principalement dans le terminal, Claude Code supporte les serveurs MCP nativement. Ajoutez le serveur au fichier .mcp.json de votre projet :
{
"mcpServers": {
"ga4-analytics": {
"command": "node",
"args": ["./mcp-servers/ga4/dist/server.js"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "./credentials/ga4-service-account.json",
"GA4_PROPERTY_ID": "123456789"
}
}
}
}
Vous pouvez maintenant interroger les données analytics sans quitter votre éditeur. En déboguant une régression de performance, vous pouvez demander "quel est le taux de rebond sur /checkout cette semaine vs la semaine dernière ?" sans changer de contexte vers un navigateur.
Utilisation avec d'autres clients compatibles MCP
La beauté de MCP en tant que standard est que tout client compatible fonctionne. Cursor, Windsurf et d'autres éditeurs supportant MCP peuvent se connecter au même serveur. Vous construisez le serveur une fois et il fonctionne partout.
Exemples pratiques d'analytics conversationnel
Laissez-moi vous montrer un workflow réel que j'utilise régulièrement.
Check-in matinal
Je commence la journée en demandant à Claude : "Donne-moi un résumé du trafic d'hier — sessions totales, utilisateurs actifs, top 5 des pages, et toutes les pages avec un taux d'engagement inférieur à 25 %."
L'IA fait trois appels d'outils : un pour les métriques globales, un pour les pages les plus visitées, un pour les pages à faible engagement. Il revient avec quelque chose comme :
Hier : 2 341 sessions de 1 892 utilisateurs uniques. Les pages les plus visitées étaient /home (580 sessions), /pricing (412), /docs/getting-started (389), /blog/mcp-guide (267), /features (198). Deux pages avaient un engagement inférieur à 25 % : /legal/terms (12 %) et /blog/old-post-2024 (22 %).
Cela prendrait 5-10 minutes dans l'interface GA4. Via MCP, cela prend 15 secondes.
Suivi de lancement de fonctionnalité
Quand je lance une nouvelle fonctionnalité, je veux savoir si les gens la trouvent et l'utilisent. "Compare le trafic vers /features/new-dashboard pour les 3 derniers jours vs les 3 jours avant le lancement, ventilé par canal d'acquisition."
L'IA exécute la comparaison, identifie quels canaux stimulent la découverte (généralement le direct et la recherche organique sont en retard par rapport au social et au referral dans les premiers jours après le lancement), et met en évidence les anomalies.
Débogage de plaintes utilisateurs
Quand les utilisateurs signalent que "le site est lent", je peux demander : "Quel est le temps de chargement moyen par page pour les 7 derniers jours, trié du plus lent au plus rapide ?" Si GA4 a des données Web Vitals (via le measurement protocol ou les événements gtag), le serveur MCP peut les faire remonter sans que j'ouvre un navigateur.
Reporting hebdomadaire
"Génère une comparaison semaine par semaine des sessions, nouveaux utilisateurs, taux d'engagement et taux de conversion pour chacune de nos 20 pages les plus visitées."
Cela produit un tableau formaté que je peux déposer directement dans un message Slack ou une mise à jour d'équipe. Pas de gymnastique avec les tableurs, pas de recadrage de captures d'écran.
Construire des fonctionnalités avancées
Couche de cache
L'API GA4 a des limites de débit (typiquement 10 requêtes par minute par propriété pour le tier gratuit). Pour un serveur MCP qui pourrait être interrogé fréquemment, ajoutez une couche de cache :
import { createHash } from "crypto";
const cache = new Map<string, { data: any; expiry: number }>();
function getCacheKey(dimensions: string[], metrics: string[], startDate: string, endDate: string): string {
const input = JSON.stringify({ dimensions, metrics, startDate, endDate });
return createHash("md5").update(input).digest("hex");
}
export async function cachedRunReport(
dimensions: string[],
metrics: string[],
startDate: string,
endDate: string
) {
const key = getCacheKey(dimensions, metrics, startDate, endDate);
const cached = cache.get(key);
if (cached && cached.expiry > Date.now()) {
return cached.data;
}
const result = await runReport(dimensions, metrics, startDate, endDate);
// Cache for 5 minutes (real-time queries get shorter TTL)
const ttl = startDate === "today" ? 60_000 : 300_000;
cache.set(key, { data: result, expiry: Date.now() + ttl });
return result;
}
Les requêtes en temps réel obtiennent un TTL d'une minute. Les requêtes historiques obtiennent 5 minutes. Cela vous maintient bien dans les limites de débit pendant une session conversationnelle où l'IA pourrait faire plusieurs requêtes liées en succession rapide.
Support multi-propriétés
Si vous gérez plusieurs produits ou clients, étendez le serveur pour supporter le basculement entre propriétés GA4 :
server.tool(
"switch_property",
"Switch to a different GA4 property",
{
propertyId: z.string().describe("The GA4 property ID to switch to"),
},
async ({ propertyId }) => {
// Validate access
const properties = await listAccessibleProperties();
if (!properties.includes(propertyId)) {
return {
content: [{ type: "text", text: `No access to property ${propertyId}` }],
};
}
currentPropertyId = propertyId;
return {
content: [{ type: "text", text: `Switched to property ${propertyId}` }],
};
}
);
Vous pouvez maintenant dire "bascule vers la propriété staging et montre-moi le trafic d'hier" sans rien reconfigurer.
Considérations de sécurité
Exécuter un serveur MCP qui accède aux données analytics introduit plusieurs préoccupations de sécurité qui nécessitent un traitement délibéré.
Gestion des identifiants
Le fichier de clé du compte de service est la pièce la plus sensible. Ne le committez jamais dans le contrôle de version. Utilisez des variables d'environnement ou un gestionnaire de secrets. Si vous exécutez le serveur MCP localement (ce qui est le cas courant pour Claude Desktop), stockez le fichier de clé en dehors du répertoire de votre projet avec des permissions de fichier restreintes :
chmod 600 /path/to/service-account-key.json
Pour les environnements d'équipe, envisagez d'utiliser Workload Identity Federation de Google Cloud au lieu d'un fichier de clé. Cela élimine entièrement les identifiants statiques en utilisant des tokens à durée de vie courte liés à l'identité d'exécution.
Principe du moindre privilège
Le compte de service devrait avoir un accès en lecture seule à GA4. Plus précisément, accordez le rôle "Lecteur" au niveau de la propriété GA4 — pas le rôle "Editeur" ou "Administrateur". Le serveur MCP n'a jamais besoin de modifier votre configuration analytics, de créer des audiences ou de changer les paramètres de mesure.
Au niveau du projet Google Cloud, n'accordez que le scope analyticsdata.readonly. Cela empêche le compte de service d'accéder à tout autre service Google Cloud même si la clé est compromise.
Portée d'exposition des données
Soyez délibéré sur les données auxquelles le serveur MCP peut accéder. GA4 peut contenir des données personnelles — identifiants utilisateur, identifiants client, géolocalisation dérivée de l'IP. Votre serveur MCP devrait masquer ou supprimer les champs qui ne sont pas nécessaires pour les requêtes que vous souhaitez supporter.
const BLOCKED_DIMENSIONS = ["userID", "clientId"];
function validateDimensions(dimensions: string[]) {
const blocked = dimensions.filter((d) => BLOCKED_DIMENSIONS.includes(d));
if (blocked.length > 0) {
throw new Error(`Blocked dimensions for privacy: ${blocked.join(", ")}`);
}
}
C'est particulièrement important si d'autres membres de l'équipe peuvent interagir avec le serveur MCP. Vous voulez empêcher les requêtes occasionnelles qui pourraient exposer des données utilisateur individuelles.
Sécurité du transport
MCP fonctionne actuellement sur stdio (entrée/sortie standard) quand il est utilisé avec Claude Desktop, ce qui signifie que la communication se fait dans les limites du processus local. Il n'y a pas d'exposition réseau. Cependant, si vous déployez un serveur MCP sur HTTP (en utilisant le transport SSE), vous avez besoin de TLS, de tokens d'authentification et de limitation de débit — traitez-le comme n'importe quel autre endpoint API.
Journalisation d'audit
Enregistrez chaque requête que le serveur MCP traite. Pas seulement pour la sécurité — pour la responsabilité. Quand quelqu'un demande "qui a interrogé nos données analytics et quand", vous devriez avoir une réponse.
function logQuery(tool: string, params: Record<string, unknown>) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
tool,
params,
propertyId: currentPropertyId,
}));
}
Compromis et limitations
Ce qui fonctionne bien
L'analytics conversationnel élimine la courbe d'apprentissage GA4 pour les développeurs. Vous n'avez pas besoin de connaître les noms de dimensions et métriques de GA4, les types de rapports ou la syntaxe des filtres. L'IA gère la traduction. Pour les questions ponctuelles — le genre que vous posez une fois et ne répétez jamais — c'est considérablement plus rapide que le tableau de bord.
Combiner l'analytics avec le contexte de développement est puissant. Quand vous déboguez dans Claude Code et que vous pouvez simultanément vérifier les données analytics, la boucle de feedback se resserre. Vous voyez le code, les logs d'erreurs et l'impact utilisateur au même endroit.
Ce qui ne fonctionne pas bien
Les explorations complexes qui nécessitent un affinage itératif sont toujours plus rapides dans l'interface Explore de GA4. Si vous construisez une analyse d'entonnoir avec plusieurs étapes, des segments personnalisés et des groupes de comparaison, le constructeur visuel vous donne un feedback immédiat qu'une interface conversationnelle ne peut pas égaler.
Les tableaux de bord en temps réel qui se rafraîchissent automatiquement sont en dehors du modèle actuel de MCP. MCP fonctionne en requête-réponse — vous demandez, il répond. Pour un tableau de bord en direct montrant les utilisateurs en temps réel, un outil dédié comme la vue temps réel de GA4 ou un panel Grafana personnalisé est préférable.
Le volume de données est une contrainte. L'API GA4 Data renvoie jusqu'à 100 000 lignes par requête. Pour les propriétés avec des millions d'événements quotidiens, vous devrez peut-être être spécifique sur les dimensions et les plages de dates pour éviter d'atteindre cette limite. L'API a aussi un comportement d'échantillonnage pour les grands jeux de données — les résultats peuvent être estimés plutôt qu'exacts pour les requêtes à haute cardinalité.
MCP vs intégration API directe
Si vous construisez une fonctionnalité produit qui nécessite des données analytics (comme un tableau de bord admin pour votre SaaS), utilisez l'API GA4 directement. MCP est pour les requêtes avec un humain dans la boucle, pas pour les pipelines de données programmatiques. Le surcoût de la traduction en langage naturel et de l'interprétation IA est inutile quand vous savez exactement quelle requête exécuter.
MCP brille quand la question est non structurée, quand vous ne savez pas exactement ce que vous cherchez, ou quand l'effort de construire une intégration propre n'est pas justifié pour une question ponctuelle. C'est l'équivalent analytics d'ouvrir un REPL au lieu d'écrire un script.
Pour commencer
Si vous voulez essayer par vous-même, le chemin minimal est :
- Créer un projet Google Cloud et activer l'API Google Analytics Data.
- Créer un compte de service avec accès Lecteur à votre propriété GA4.
- Télécharger la clé JSON du compte de service.
- Cloner ou construire le serveur MCP comme décrit ci-dessus.
- Ajouter le serveur à votre configuration Claude Desktop ou Claude Code.
- Commencer à poser des questions.
L'ensemble de la configuration prend environ 30 minutes si vous avez déjà une propriété GA4. Le retour est immédiat — la première fois que vous obtenez une réponse à une question analytics en 5 secondes au lieu de 5 minutes, vous ne voudrez plus revenir au tableau de bord.
Les données analytics sont l'un des actifs les plus sous-utilisés dans la plupart des équipes de développement. Pas parce qu'elles n'ont pas de valeur, mais parce que y accéder a toujours été suffisamment inconfortable pour décourager les requêtes occasionnelles. MCP supprime cette friction. Les données sont les mêmes. Les questions sont les mêmes. C'est le temps de réponse qui change.
Danil Ulmashev
Full Stack Developer
Intéressé par une collaboration ?