← Zpět na blog AI & LLM

Ptám se svého webu, jak se mu daří: Google Analytics přes MCP

Týden po spuštění webu mě pochopitelně zajímá, co se na něm děje. Jenže místo do Google Analytics jsem se dnes podíval jinam — napsal jsem agentovi v Claude Code:

co se dělo na webu za poslední týden?

A zpátky přišla tabulka:

Event Počet
page_view 76
blog_view 7
cta_click 6
blog_read_complete 4
contact_click 1

(zkráceno — celý výstup má 12 řádků)

Žádný dashboard, žádné proklikávání. Za odpovědí stojí oficiální MCP server od Googlu, který agentovi zpřístupní Google Analytics — jen pro čtení, takže v datech nemůže nic rozbít. V článku projdu, proč jsem do toho šel, jak si to nastavit na Macu i na Windows — a čtyři věci, co z toho reálně tahám.

(Jak udržuji projekt — včetně tohohle setupu — synchronizovaný mezi dvěma počítači, popisuje Jedno repo, dvě klávesnice. Tady jde o jeden stroj a deset minut.)

Proč to řešit

GA4 svá data schovává důkladně. Kdo v něm někdy hledal jedno konkrétní číslo, ten to zná: standardní reporty ukazují všechno možné, jen ne to, co zrovna potřebujete, a tak stavíte exploration, vzpomínáte, pod kterou záložkou jsou custom definitions, a klikáte.

Hlavní důvod je ale jinde. Agent, se kterým na webu pracuju, zná jeho kontext. Ví, že cta_click je klik na hlavní tlačítko, že blog_read_complete posílám při dočtení článku a že web jede bez cookies. Takže nemusím mluvit jazykem metrik — zeptám se třeba, kolik lidí tenhle týden kliklo na kontakt, a překlad do dimenzí a filtrů nechám na něm.

Jak jsem vybíral

Možností, jak dostat GA data k agentovi, existuje víc. Prošel jsem je a rozhodlo se celkem rychle:

  • Oficiální MCP server od Googlu — jako jediný umí realtime reporty a výpis custom definitions, obojí jsem chtěl. A udržuje ho Google.
  • Komunitní MCP servery — ten nejzajímavější přidává prohledávání schématu dimenzí a metrik, ale realtime ani custom definitions nemá. A je to one-man projekt; u analytiky radši sázím na oficiální věc.
  • CLI nástroje — prakticky neexistují. Našel jsem jediný opuštěný repozitář na GitHubu.
  • Hostované služby — platit měsíčně za to, aby moje čísla tekla přes třetí stranu, se mi u osobního webu prostě nechce.

Druhé rozhodnutí byla autentizace. Google v návodu doporučuje přihlášení přes gcloud — jenže to znamená instalovat SDK o stovkách megabajtů kvůli jedinému loginu. Service account s JSON klíčem udělá to samé bez gcloudu, klíč jde per stroj revokovat a nikdy neexpiruje. U read-only přístupu k analytice osobního webu s tím nemám problém.

Setup v pěti krocích

Jediný předpoklad: nástroj uv — server je Python balík a přes uvx se stahuje i spouští sám, nic dalšího se neinstaluje:

brew install uv                  # Mac
winget install astral-sh.uv     # Windows

Dál potřebujete Google Cloud projekt (zdarma, bez billing účtu) a zhruba deset minut:

  1. GCP projekt + dvě API. V console.cloud.google.com založte projekt a zapněte Google Analytics Admin API a Google Analytics Data API.
  2. Service account + klíč. IAM → Service accounts → Create service account. Žádné GCP role nepotřebuje. Na detailu účtu pak Keys → Add key → JSON.
  3. Viewer v GA. V GA4: Admin → Property access management → přidejte e-mail service accountu s rolí Viewer. Tím vidí zrovna tuhle property a nic víc.
  4. Klíč uložte mimo repo. Na Macu ~/.config/google-analytics-mcp/sa-key.json a chmod 600; na Windows třeba C:\Users\<vy>\.config\google-analytics-mcp\sa-key.json. Do gitu nikdy — klíče nalezené ve veřejných repozitářích Google automaticky invaliduje, a ani v privátním repu nemají co dělat.
  5. Registrace v Claude Code. Na Macu:
claude mcp add analytics-mcp --scope user \
  -e GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/google-analytics-mcp/sa-key.json" \
  -e GOOGLE_PROJECT_ID=<vas-gcp-projekt> \
  -- uvx analytics-mcp

Na Windows stejný příkaz, jen s cestou ke klíči ve tvaru C:\Users\<vy>\... — server ji dostává mimo git-bash, takže tvar /c/Users/... mu nic neřekne.

Pozor na jednu věc: tools naskočí až v nové session. Po registraci Claude Code restartujte — claude mcp list sice hlásí connected hned, ale zavolat je jde až po restartu.

A dodatek pro ty, kdo jedou na víc strojích: JSON klíč se přes repo nesyncuje. Každý stroj má vlastní klíč — dají se pak revokovat nezávisle.

Co z toho tahám

Formát ukázek si půjčím z taháku: prompt, který píšu, co se volá pod kapotou, a co přišlo zpátky. Delegovat neznamená přestat rozumět tomu, co se děje.

Co se dělo za týden

Tabulka z úvodu. Pod kapotou se volá run_report s dimenzí eventName, metrikou eventCount a rozsahem 7daysAgo..today — a agent výstup rovnou okomentuje, protože ví, která čísla jsou konverze.

Web je týden po spuštění a čísla jsou malá. Dvě z nich mě ale zajímají víc než všechna ostatní: 6× klik na hlavní CTA, 1× na kontakt.

Localhost se počítá taky. Přišel jsem na to hned při prvním reálném reportu: dev server posílá eventy na to samé GA ID jako produkce, a za týden vývoje to bylo 68 % všech eventů — čísla v tomhle článku nevyjímaje. Web už od té doby z localhostu neposílá vůbec nic a v dotazech pro jistotu filtruju hostName. První čistá tabulka bude až ta příští.

Které články lidi dočítají

blog_view počítám při otevření článku, blog_read_complete při doscrollování na 90 %. Poměr těch dvou = dočítanost — podle mě užitečnější metrika než holé pageviews.

které články lidi čtou a kolik jich dočte do konce?

Pod kapotou: run_report s dimenzemi customEvent:article_slug a eventName, filtr na ty dva eventy:

article_slug Event Počet
tahak-git-github-claude-code blog_view 6
tahak-git-github-claude-code blog_read_complete 4
ai-agenti-v-enterprise blog_view 1

Tenhle týden vede tahák: 6 otevření, 4 dočtení. Když jsem ale ten samý dotaz pustil poprvé, výstup vypadal jinak, než jsem čekal — většina řádků říkala (not set). Custom dimenze jako article_slug se totiž v reportech plní až od chvíle, kdy je v GA adminu zaregistrujete — a já je registroval den po spuštění webu. Launch traffic tak zůstane neatribuovaný napořád. Kdybych to věděl dřív, registruju dimenze před deployem, ne po něm.

Sedí konfigurace? A funguje deploy?

Use-case, kvůli kterému jsem to celé stavěl. Web posílá 9 custom dimenzí a 2 metriky a každou z nich musíte ručně zaregistrovat v GA adminu — jména parametrů musí sedět na znak přesně.

vypiš custom dimenze a metriky registrované v GA
a porovnej je s tím, co reálně posílá kód

Pod kapotou get_custom_dimensions_and_metrics; porovnání s kódem už je agentova domácí úloha, kód má před sebou. Výsledek: 9 dimenzí, 2 metriky, jména sedí 1:1. Kdyby neseděla, dozvím se to hned — a ne za měsíc z prázdného reportu.

A po každém deployi rychlá kontrola:

otevřel jsem teď web — vidíš můj page_view v realtime?

Pod kapotou run_realtime_report. Standardní reporty mají zpoždění klidně den; realtime je jediná cesta, jak si deploy ověřit hned.

Měsíční scorecard

Jednou za měsíc si nechám udělat přehled:

udělej mi měsíční scorecard: contact_click, cta_click a blog_read_complete
po týdnech, srovnej s minulým měsícem

K tomu jedno vysvětlení. Web jede bez cookies — žádný consent banner, ale taky žádné trvalé ID návštěvníka. Metriky jako Users nebo Sessions u něj nedávají smysl, tak je neměřím. Scorecard stojí na počtech eventů: kolikrát někdo klikl na kontakt, kolikrát dočetl článek. U osobního webu mi to bohatě stačí — nepotřebuju vědět, kolik bylo „uživatelů", potřebuju vědět, jestli se někdo ozval.

Bonus: stejný klíč otevírá i Search Console

Z GA vidím, co lidi na webu dělají. Jak se k němu přes Google vůbec dostali — jaké dotazy, jaká pozice ve výsledcích — to je v Search Console. A ta oficiální MCP server nemá. Nevadí — Search Console API je tak jednoduché, že na něj stačí krátký skript a ten samý service account.

Postup navazuje na setup výše:

  1. Ve stejném GCP projektu zapněte Search Console API (třetí do party k těm dvěma analytickým).
  2. V Search Console přidejte service account jako uživatele. Nastavení → Uživatelé a oprávnění → e-mail účtu z kroku 2, stačí oprávnění Omezené.
  3. Skript. Zhruba 90 řádků Pythonu bez jediné závislosti: podepíše JWT přes openssl (na Windows ho s sebou nosí git-bash), vymění ho za access token a zavolá Search Analytics API. Můj leží v repu jako scripts/gsc_report.py — psal jsem ho původně pro jiný web, tady jsem jen přepnul doménu.

Podpis JWT je dvacet řádků boilerplate — privátním klíčem se podepíše krátký JSON a OAuth endpoint ho vymění za hodinový access token. Zbytek je krátký: celé Search Analytics API je jeden endpoint a tělo dotazu říká jen rozsah dat a dimenze.

def query(token: str, body: dict) -> list:
    req = urllib.request.Request(
        f"https://www.googleapis.com/webmasters/v3/sites/{urllib.parse.quote(SITE, safe='')}/searchAnalytics/query",
        data=json.dumps(body).encode(),
        headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"})
    return json.load(urllib.request.urlopen(req)).get("rows", [])

base = {"startDate": start, "endDate": end, "type": "web"}
totals      = query(token, base)                                            # souhrn
top_queries = query(token, {**base, "dimensions": ["query"], "rowLimit": 10})
top_pages   = query(token, {**base, "dimensions": ["page"], "rowLimit": 5})

Bez dimenzí přijde souhrn, s query top dotazy, s page top stránky. To je celé — žádná knihovna, žádné SDK.

A agent skript volá jako každý jiný nástroj:

jak si web vedl ve vyhledávání první týden?

Pod kapotou python3 scripts/gsc_report.py 2026-07-12 2026-07-18:

"totals": { "clicks": 1, "impressions": 64, "ctr": 0.0156, "position": 8.2 }

64 zobrazení, 1 kliknutí, průměrná pozice 8. Nový web týden po spuštění — indexace se teprve rozjíždí. Mezi dotazy je zatím hlavně tahák („claude code cheat sheet github", pozice 7) a jednou i „mirek ai" na pětce. Malá čísla, ale přesně tahle chci sledovat měsíc po měsíci — proto skript zůstává v repu vedle webu.

Pozor na jedno: data mají zhruba dvoudenní zpoždění. Okno proto končím dva dny před dneškem — novější řádky by přišly prázdné.

Co to neumí

  • Zápis. Server je read-only. Registrace dimenzí, key events, retence dat — admin věci v GA zůstávají na ruční klikání. Beru to jako vlastnost — agent v datech nic nepokazí.
  • Čerstvá data ve standardních reportech. GA je zpracovává s odstupem 24–48 hodin. Na „co se děje teď" je realtime report, na všechno ostatní si den počkáte.
  • Stoprocentní trefa názvů. Párkrát si agent vymyslel název dimenze. API mu vrátí chybu a on se opraví — horší by bylo, kdyby potichu dostal špatná data. Proto jsem si výstupy zpočátku ověřoval proti GA UI, než jsem tomu začal věřit.

Závěr

Za deset minut nastavování analytika, které se ptám česky a která zná můj web. Čísla jsou tam, kde pracuju — v terminálu, hned vedle kódu, který je posílá. GA dashboard jsem od té doby otevřel jednou, a to jen kvůli admin klikání, které server neumí.

Spolupráce

S čím vám můžu pomoci?

Máte projekt, nápad nebo jen otázku? Pište, volejte, posílejte poštovní holuby... Rád to s vámi proberu. Nezávazně. Jdeme na to?

Pojďme na to!