Server MCP: Rendere Google Analytics Davvero Utile per gli Sviluppatori
Come i server Model Context Protocol trasformano Google Analytics da una dashboard di marketing in una fonte di dati user-friendly per gli sviluppatori, interrogabile in modo conversazionale.

Google Analytics è sempre stato uno strumento di marketing che gli sviluppatori tollerano. Si imposta il tracciamento, si configurano gli eventi e poi lo si consegna a qualcuno a cui piace effettivamente cliccare tra le dashboard. Quando hai bisogno di dati tu stesso — tassi di rimbalzo per una pagina specifica, funnel di conversione per una nuova funzionalità, utenti attivi in tempo reale segmentati per paese — finisci per cliccare attraverso cinque menu annidati, lottando con il builder di query di GA4 e chiedendoti perché ci vuole più sforzo per porre una domanda che per rispondere.
Model Context Protocol cambia tutto questo. Avvolgendo l'API di reporting di GA4 in un server MCP, puoi interrogare i tuoi dati analitici in modo conversazionale tramite Claude o qualsiasi assistente AI compatibile con MCP. Niente dashboard. Niente builder di query. Chiedi semplicemente quello che vuoi sapere.
Cos'è MCP e Perché è Importante
Model Context Protocol è uno standard aperto creato da Anthropic che definisce come gli assistenti AI interagiscono con fonti di dati e strumenti esterni. Pensalo come una porta USB-C per l'AI — un'interfaccia universale che permette a qualsiasi assistente compatibile di connettersi a qualsiasi fonte di dati compatibile senza codice di integrazione personalizzato per ogni accoppiamento.
Prima di MCP, connettere un assistente AI ai tuoi dati analitici significava costruire una pipeline su misura: esportare i dati in CSV, incollarli in una chat, sperare che la finestra di contesto fosse abbastanza grande. Oppure costruire un'integrazione API personalizzata, scrivere modelli di prompt, gestire l'autenticazione da soli. Ogni nuova fonte di dati richiedeva una nuova integrazione.
MCP standardizza questo in tre concetti:
- Risorse — dati strutturati esposti dal server (le tue proprietà GA4, report, dimensioni, metriche)
- Strumenti — azioni che l'AI può invocare (eseguire un report, interrogare dati in tempo reale, elencare le metriche disponibili)
- Prompt — modelli di prompt riutilizzabili forniti dal server (query analitiche comuni pre-strutturate per buoni risultati)
Il server gestisce l'autenticazione, il recupero dei dati e la formattazione della risposta. L'assistente AI gestisce la comprensione del linguaggio naturale e l'interpretazione dei risultati. Nessuna delle due parti ha bisogno di conoscere i dettagli di implementazione dell'altra.
Perché Questo è Importante Specificamente per l'Analisi
Le piattaforme di analisi sono dense di informazioni ma povere di interazione. GA4 ha dati straordinariamente potenti — traccia ogni sessione utente, ogni visualizzazione di pagina, ogni evento, ogni conversione attraverso l'intero prodotto. Ma accedere a quei dati richiede di pensare nel vocabolario di GA4: dimensioni, metriche, segmenti, intervalli di date, filtri, confronti. Devi tradurre la tua domanda nel modello di query di GA4 prima di poter ottenere una risposta.
Un server MCP inverte questo. Tu poni la tua domanda in linguaggio semplice. L'AI la traduce nelle chiamate API corrette, le esegue e interpreta i risultati. L'attrito tra "Ho una domanda" e "Ho una risposta" si riduce da minuti a secondi.
Costruire un Server MCP per GA4
L'implementazione coinvolge tre livelli: il framework del server MCP, il client dell'API Google Analytics Data e la logica di collegamento che mappa l'intento in linguaggio naturale alle chiamate API.
Configurazione del Progetto
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
Il pacchetto @modelcontextprotocol/sdk fornisce il framework del server. @google-analytics/data è la libreria client ufficiale di Google per l'API GA4 Data (l'API di reporting, non l'API Admin). zod gestisce la validazione dell'input per i parametri degli strumenti.
Autenticazione con Google
L'autenticazione dell'API GA4 utilizza un account di servizio Google Cloud. Creane uno nella Google Cloud Console, scarica il file della chiave JSON e concedigli l'accesso "Visualizzatore" alla tua proprietà 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.`,
};
}
Il Server 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);
Questo fornisce all'assistente AI tre strumenti: eseguire report arbitrari, controllare i dati in tempo reale e scoprire quali metriche e dimensioni sono disponibili. Lo strumento di scoperta è importante — permette all'AI di capire i nomi dei campi corretti senza che tu debba ricordare se è activeUsers o active_users o totalUsers.
Endpoint Dati in Tempo Reale
// 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);
}
I dati in tempo reale sono una delle funzionalità di maggior valore. In una dashboard, navigheresti alla sezione in tempo reale, aspetteresti che si carichi e leggeresti i numeri. Tramite MCP, digiti "quante persone sono sul sito in questo momento?" e ottieni una risposta in due secondi.
Query Reali che gli Sviluppatori Vogliono Effettivamente Eseguire
Le capacità teoriche sono noiose. Ecco le query reali che mi trovo a eseguire quotidianamente e come appaiono come richieste conversazionali all'AI:
Analisi del Traffico
"Quali sono le 10 pagine principali per numero di sessioni questa settimana e come si confrontano con la settimana scorsa?"
L'AI traduce questo in due chiamate runReport — una per la settimana corrente, una per la settimana precedente — quindi calcola la differenza e presenta una tabella di confronto. Nell'interfaccia di GA4, questo richiede la configurazione di un intervallo di date di confronto, la selezione del report corretto, l'aggiunta della dimensione della pagina, l'ordinamento per sessioni e la limitazione a 10. Tramite MCP, è una frase.
"Mostrami il traffico dalla ricerca organica degli ultimi 30 giorni, suddiviso per pagina di destinazione."
Questo diventa un singolo report con sessionDefaultChannelGroup come filtro di dimensione (filtrato su "Organic Search"), landingPagePlusQueryString come dimensione e sessions più engagedSessions come metriche.
Debugging delle Conversioni
"Qual è il tasso di rimbalzo su /pricing rispetto a /features per le ultime due settimane?"
Due chiamate di report filtrate, risultati confrontati fianco a fianco. Questo è il tipo di domanda che richiede 30 secondi per essere posta in modo conversazionale e 3 minuti per essere risposta tramite l'interfaccia di GA4.
"Quali paesi hanno il tasso di conversione più alto per l'evento di iscrizione?"
Un singolo report con dimensione country, metrica eventCount filtrata sull'evento sign_up e sessions per calcolare il tasso di conversione. L'AI può persino fare la divisione e presentare le percentuali direttamente.
Monitoraggio delle Prestazioni
"Qual è il tempo medio di coinvolgimento per sessione su mobile vs desktop questo mese?"
Segmentato per deviceCategory, misurando averageSessionDuration e engagedSessions. Query semplice, ma che richiede di navigare al report giusto e configurare i segmenti in GA4.
"Ci sono pagine con più di 1000 visualizzazioni questa settimana ma un tasso di coinvolgimento inferiore al 30%?"
È qui che l'analisi conversazionale brilla davvero. L'AI esegue il report, filtra i risultati programmaticamente e restituisce solo le pagine che corrispondono a entrambi i criteri. In GA4, dovresti esportare in un foglio di calcolo e filtrare manualmente, o costruire un'esplorazione personalizzata.
Connessione a Claude e Assistenti AI
Configurazione di Claude Desktop
Una volta costruito il tuo server MCP, connetterlo a Claude Desktop è una modifica del file di configurazione:
{
"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"
}
}
}
}
Su macOS, questo si trova in ~/Library/Application Support/Claude/claude_desktop_config.json. Su Windows, è %APPDATA%\Claude\claude_desktop_config.json.
Dopo aver riavviato Claude Desktop, gli strumenti GA4 appaiono nel menu degli strumenti. Claude può ora chiamarli direttamente in conversazione.
Integrazione del Codice Claude
Per gli sviluppatori che lavorano principalmente nel terminale, Claude Code supporta nativamente i server MCP. Aggiungi il server al file .mcp.json del tuo progetto:
{
"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"
}
}
}
}
Ora puoi interrogare i dati analitici senza lasciare il tuo editor. Durante il debug di una regressione delle prestazioni, puoi chiedere "qual è il tasso di rimbalzo su /checkout questa settimana rispetto alla settimana scorsa?" senza cambiare contesto con un browser.
Utilizzo con Altri Client Compatibili con MCP
La bellezza di MCP come standard è che qualsiasi client compatibile funziona. Cursor, Windsurf e altri editor che supportano MCP possono connettersi allo stesso server. Costruisci il server una volta e funziona ovunque.
Esempi Pratici di Analisi Conversazionale
Permettimi di illustrare un flusso di lavoro reale che uso regolarmente.
Controllo Mattutino
Inizio la giornata chiedendo a Claude: "Dammi un riepilogo del traffico di ieri — sessioni totali, utenti attivi, le 5 pagine principali e qualsiasi pagina con un tasso di coinvolgimento inferiore al 25%."
L'AI effettua tre chiamate agli strumenti: una per le metriche complessive, una per le pagine principali, una per le pagine a basso coinvolgimento. Torna con qualcosa del genere:
Ieri: 2.341 sessioni da 1.892 utenti unici. Le pagine principali erano /home (580 sessioni), /pricing (412), /docs/getting-started (389), /blog/mcp-guide (267), /features (198). Due pagine avevano un coinvolgimento inferiore al 25%: /legal/terms (12%) e /blog/old-post-2024 (22%).
Questo richiederebbe 5-10 minuti nell'interfaccia di GA4. Tramite MCP, ci vogliono 15 secondi.
Monitoraggio del Lancio di Funzionalità
Quando rilascio una nuova funzionalità, voglio sapere se le persone la trovano e la usano. "Confronta il traffico su /features/new-dashboard per gli ultimi 3 giorni rispetto ai 3 giorni prima del lancio, suddiviso per canale di acquisizione."
L'AI esegue il confronto, identifica quali canali stanno guidando la scoperta (di solito la ricerca diretta e organica sono in ritardo rispetto ai social e ai referral nei primi giorni dopo il lancio) e evidenzia eventuali anomalie.
Debugging dei Reclami degli Utenti
Quando gli utenti segnalano che "il sito sembra lento", posso chiedere: "Qual è il tempo medio di caricamento della pagina per pagina negli ultimi 7 giorni, ordinato dal più lento al primo?" Se GA4 ha dati Web Vitals (tramite il protocollo di misurazione o eventi gtag), il server MCP può mostrarli senza che io apra un browser.
Report Settimanale
"Genera un confronto settimana su settimana di sessioni, nuovi utenti, tasso di coinvolgimento e tasso di conversione per ciascuna delle nostre 20 pagine principali."
Questo produce una tabella formattata che posso inserire direttamente in un messaggio Slack o in un aggiornamento del team. Niente acrobazie con i fogli di calcolo, niente ritagli di screenshot.
Costruire Funzionalità Avanzate
Livello di Caching
L'API di GA4 ha limiti di frequenza (tipicamente 10 richieste al minuto per proprietà per il livello gratuito). Per un server MCP che potrebbe essere interrogato frequentemente, aggiungi un livello di caching:
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;
}
Le query in tempo reale ottengono un TTL di 1 minuto. Le query storiche ottengono 5 minuti. Questo ti mantiene ben entro i limiti di frequenza durante una sessione conversazionale in cui l'AI potrebbe effettuare diverse query correlate in rapida successione.
Supporto Multi-Proprietà
Se gestisci più prodotti o clienti, estendi il server per supportare il passaggio tra le proprietà 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}` }],
};
}
);
Ora puoi dire "passa alla proprietà di staging e mostrami il traffico di ieri" senza riconfigurare nulla.
Considerazioni sulla Sicurezza
L'esecuzione di un server MCP che accede ai dati analitici introduce diverse preoccupazioni di sicurezza che richiedono una gestione deliberata.
Gestione delle Credenziali
Il file della chiave dell'account di servizio è il pezzo più sensibile. Non commetterlo mai al controllo di versione. Usa variabili d'ambiente o un gestore di segreti. Se stai eseguendo il server MCP localmente (che è il caso comune per Claude Desktop), memorizza il file della chiave al di fuori della directory del tuo progetto con permessi di file ristretti:
chmod 600 /path/to/service-account-key.json
Per gli ambienti di team, considera l'utilizzo della Workload Identity Federation di Google Cloud invece di un file di chiave. Elimina completamente la credenziale statica utilizzando token di breve durata legati all'identità di runtime.
Principio del Minimo Privilegio
L'account di servizio dovrebbe avere accesso in sola lettura a GA4. In particolare, concedi il ruolo "Visualizzatore" a livello di proprietà GA4 — non il ruolo "Editor" o "Amministratore". Il server MCP non ha mai bisogno di modificare la tua configurazione analitica, creare segmenti di pubblico o modificare le impostazioni di misurazione.
A livello di progetto Google Cloud, concedi solo lo scope analyticsdata.readonly. Questo impedisce all'account di servizio di accedere a qualsiasi altro servizio Google Cloud anche se la chiave viene compromessa.
Ambito di Esposizione dei Dati
Sii deliberato riguardo a quali dati il server MCP può accedere. GA4 può contenere PII — ID utente, ID client, geolocalizzazione derivata dall'IP. Il tuo server MCP dovrebbe rimuovere o mascherare i campi che non sono necessari per le query che vuoi supportare.
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(", ")}`);
}
}
Questo è particolarmente importante se altri membri del team possono interagire con il server MCP. Vuoi prevenire query casuali che potrebbero esporre dati utente individuali.
Sicurezza del Trasporto
MCP attualmente funziona su stdio (input/output standard) quando usato con Claude Desktop, il che significa che la comunicazione avviene entro i limiti del processo locale. Non c'è esposizione di rete. Tuttavia, se distribuisci un server MCP su HTTP (usando il trasporto SSE), hai bisogno di TLS, token di autenticazione e limitazione della frequenza — trattalo come qualsiasi altro endpoint API.
Registrazione degli Audit
Registra ogni query elaborata dal server MCP. Non solo per la sicurezza — per la responsabilità. Quando qualcuno chiede "chi ha interrogato i nostri dati analitici e quando", dovresti avere una risposta.
function logQuery(tool: string, params: Record<string, unknown>) {
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
tool,
params,
propertyId: currentPropertyId,
}));
}
Compromessi e Limitazioni
Cosa Funziona Bene
L'analisi conversazionale elimina la curva di apprendimento di GA4 per gli sviluppatori. Non è necessario conoscere i nomi delle dimensioni e delle metriche di GA4, i tipi di report o la sintassi dei filtri. L'AI gestisce la traduzione. Per le domande ad hoc — quelle che poni una volta e non ripeti mai — questo è drasticamente più veloce della dashboard.
Combinare l'analisi con il contesto di sviluppo è potente. Quando stai debuggando in Claude Code e puoi contemporaneamente controllare i dati analitici, il ciclo di feedback si stringe. Vedi il codice, i log degli errori e l'impatto sull'utente in un unico posto.
Cosa Non Funziona Bene
Esplorazioni complesse che richiedono un raffinamento iterativo sono ancora più veloci nell'interfaccia Esplora di GA4. Se stai costruendo un'analisi del funnel con più fasi, segmenti personalizzati e gruppi di confronto, il builder visuale ti offre un feedback immediato che un'interfaccia conversazionale non può eguagliare.
Le dashboard in tempo reale che si aggiornano automaticamente sono al di fuori del modello attuale di MCP. MCP è richiesta-risposta — tu chiedi, lui risponde. Per una dashboard che si aggiorna in tempo reale mostrando gli utenti attivi, uno strumento appositamente costruito come la vista in tempo reale di GA4 o un pannello Grafana personalizzato è migliore.
Il volume dei dati è un vincolo. L'API GA4 Data restituisce fino a 100.000 righe per richiesta. Per le proprietà con milioni di eventi giornalieri, potrebbe essere necessario essere specifici riguardo a dimensioni e intervalli di date per evitare di raggiungere questo limite. L'API ha anche un comportamento di campionamento per grandi set di dati — i risultati potrebbero essere stimati anziché esatti per query ad alta cardinalità.
MCP vs. Integrazione Diretta dell'API
Se stai costruendo una funzionalità di prodotto che necessita di dati analitici (come una dashboard di amministrazione per il tuo SaaS), usa direttamente l'API GA4. MCP è per l'interrogazione con un essere umano nel ciclo, non per pipeline di dati programmatiche. Il sovraccarico della traduzione del linguaggio naturale e dell'interpretazione dell'AI è inutile quando sai esattamente quale query eseguire.
MCP brilla quando la domanda è non strutturata, quando non sai esattamente cosa stai cercando, o quando lo sforzo di costruire un'integrazione adeguata non è giustificato per una domanda una tantum. È l'equivalente analitico di aprire un REPL invece di scrivere uno script.
Per Iniziare
Se vuoi provare questo tu stesso, il percorso minimo è:
- Crea un progetto Google Cloud e abilita l'API Google Analytics Data.
- Crea un account di servizio con accesso Visualizzatore alla tua proprietà GA4.
- Scarica il JSON della chiave dell'account di servizio.
- Clona o costruisci il server MCP come descritto sopra.
- Aggiungi il server alla tua configurazione di Claude Desktop o Claude Code.
- Inizia a fare domande.
L'intera configurazione richiede circa 30 minuti se hai già una proprietà GA4. Il vantaggio è immediato — la prima volta che ottieni una risposta a una domanda analitica in 5 secondi invece di 5 minuti, non vorrai più tornare alla dashboard.
I dati analitici sono una delle risorse più sottoutilizzate nella maggior parte dei team di sviluppo. Non perché non siano preziosi, ma perché accedervi è sempre stato abbastanza scomodo da scoraggiare le query casuali. MCP rimuove quell'attrito. I dati sono gli stessi. Le domande sono le stesse. Il tempo per rispondere è ciò che cambia.