Docs.
Quickstart
Three steps. Five minutes if your hosting is fast.
Add the connector
In Claude, add a custom MCP connector with URL mcp-analytics.com/mcp. Claude opens a browser tab to authorize.
Confirm via email
Enter your email on that tab. We send a verify link, click it, consent, you're connected. One time per client.
Ask anything
"Add mcp-analytics to my site." Your agent installs the tracking snippet, deploys, and you're live.
What is MCP?
MCP (Model Context Protocol) is the open spec Anthropic introduced for letting AI assistants talk to external services. Think USB for LLMs: one cable, every tool. Claude, Cursor, ChatGPT, and Windsurf all speak it.
mcp-analytics is an MCP server. We expose your web analytics as tools that your AI assistant can call. Instead of opening a dashboard, you ask a question in chat and the assistant fetches the answer over JSON-RPC. No UI between you and your data. No tab to keep open. No "Configure" menu to hunt through.
Installation
The signup itself is the hardest part, and it's still pretty easy. Once the connector is authorized in your client, you stop doing things and your agent takes over.
Tell Claude (or whoever): "Add mcp-analytics to this project." That single sentence is the whole install. Claude will:
- Call
add_sitewith your domain to get asite_id - Call
get_tracking_snippetto get the exact<script>tag - Find the right place in your codebase (layout file, base template, root component)
- Drop the snippet in, commit it, push it
Total work for you: typing one sentence and clicking "approve" on the diff. After deploy, the first pageview lands in our database within seconds.
For every new project after that: same one-liner. "Add mcp-analytics." No new account, no new URL, no new dashboard. Claude already has your connector, knows the snippet, knows your repo conventions. Three minutes for Claude. Zero minutes for you. Custom events take another "track signups, purchases, and video plays as events" sentence.
Privacy modes
Pick a privacy posture per site. Cannot be changed after creation, historical data integrity matters.
| strict (recommended) | balanced | all | |
|---|---|---|---|
| Cookies | none | none | 1st-party persistent |
| visitor_id | always 0 | daily-rotating hash (IP + UA + site salt) |
persistent UUID |
| Session salt | rotates every day | fixed per site | fixed per site |
| Same-day visitor dedup | no | yes | yes |
| Cross-day visitor tracking | no | no | yes |
| LTV / cohort analysis | no | no | yes |
| Referrer path stored | no | yes | yes |
| DNT respected | yes | yes | no (opt-in) |
| Cookie banner needed | no | no | yes (your call) |
Strict is the right call for almost every public-facing site: aggregate answers, no banner, sleep at night. You lose "how many unique people came today" as a number, but session counts plus the rich client signals (timezone, viewport, engagement) usually answer the same question better.
Balanced trades a tiny bit of identifiability (a daily-rotating hash of IP + UA, gone at midnight) for proper same-day visitor counts and full referrer paths. Still no cookies, still no banner, still wipes itself daily. Pick this if you genuinely need "X unique visitors today" as a metric.
All is for when you've already decided your business needs cross-session attribution, LTV cohorts, repeat-visit analysis. Persistent cookies, consent banner becomes your responsibility. Typical for SaaS dashboards behind a login.
Asking questions
Once installed, you ask Claude (or your client of choice) anything you'd normally hunt through a dashboard for. Plain English. No tool names. No SQL. No Configure menus.
How did yesterday go?
On your-site.com yesterday: 412 pageviews from 287 sessions,
bounce rate 64%, top page /pricing (89 views), top source
news.ycombinator.com. Up 23% versus the day before. 4 signup events.
Plus 8% AI-mediated reads (Claude-User, ChatGPT-User fetching pages on user
questions) and 12% bot crawls (mostly GPTBot training, AhrefsBot scanning).
What should I do about the bounce rate?
Looking at engagement_overview: median time on /pricing is 8s, median scroll depth 22%. People are bouncing before seeing the price grid. The grid sits below a 600px hero. Want me to move the grid above the fold and ship it?
Do it.
That last bit is the actual unlock. Claude doesn't just read your analytics. Once it knows what's wrong, it can edit your code, run your tests, commit, push. Analytics-to-ship loop on autopilot. You stay in chat. You approve or reject. The diff lands. The next pageview tells you if it worked.
You don't have to use it that way. Asking questions and getting answers is fine on its own. But if you're already living in Claude, your analytics are now part of the same loop as everything else you ship.
Example prompts
Three prompts to paste into Claude (or Cursor, or ChatGPT) after your connector is wired up. Numbers in the responses are examples.
How did myblog.com do yesterday?
On myblog.com yesterday: 4,287 pageviews from
2,914 sessions. Bounce 41%, average engagement 53 seconds.
Up 18% versus the day before. Top page /pricing
(612 views), top source news.ycombinator.com
(1,103 visits). 27 signup events, 9 of them on the Pro plan.
Bot share 14%, mostly GPTBot indexing your blog.
Calls get_overview with period: "yesterday".
One tool call returns headline metrics, vs-previous-period delta,
top page, top source, bot share, and the top three custom events.
Show me the last 28 days for myblog.com, and tell me what to fix.
Last 28 days: 118,400 pageviews, 76,200 sessions, +12% vs the prior 28 days. Signups up 31% to 842, but signup-to-Pro conversion dropped from 11% to 7%.
Three things stand out:
1. Mobile bounce is 64%, desktop 31%. Mobile traffic grew 38% but
engagement halved. The hero stacks below a 600px header image on phones.
2. Newsletter (utm_source=newsletter) brings 18% of pageviews
but 41% of signups. Your best channel by 2.5x.
3. /pricing has 18,400 views and 2.1% scroll past the
comparison table on mobile. People can't see the Pro column.
Suggestions, in order of likely impact:
a. Move the pricing comparison table above the mobile hero image.
Want me to ship that diff?
b. Triple down on newsletter cadence. One extra issue this week
likely worth ~120 additional signups.
c. Hacker News referrals bounce at 78%, much higher than other
sources. The HN crowd hits the page expecting something different
from your current hero copy. Consider an HN-tailored variant.
Calls get_overview, get_timeseries,
top_sources, breakdown, and
engagement_overview in sequence. The agent picks tools
based on what the question implies. Once it has the data it can also
propose code changes and ship them on approval, no separate dashboard
needed.
Which AI agents fetched myblog.com this week?
Last 7 days on myblog.com, by traffic class:
- GPTBot (ai_training): 8,420 hits, mostly under /blog/*
- ClaudeBot (ai_training): 6,180 hits, same pattern
- PerplexityBot (ai_search): 1,240 hits, focused on
/pricing and your top 5 blog posts
- ChatGPT-User (ai_user_action): 1,847 fetches. These are
real humans chatting with ChatGPT and the assistant pulled your page.
- Claude-User (ai_user_action): 924 fetches, same idea
Two things worth knowing:
First, ai_user_action is up 4x month-over-month. People
are asking AI about your content. The top fetched URLs are
/pricing and /blog/email-management.
Make sure those render meaningful content without JavaScript,
because most AI fetchers don't execute it.
Second, training crawlers (GPTBot, ClaudeBot) are pulling your blog
heavily. If you don't want your posts in training data, add a
robots.txt rule. If you do, you're already in line for
wider AI reach.
Calls top_user_agents and traffic_class_breakdown.
The 8-class taxonomy (user, ai_user_action, ai_search, ai_training,
search_index, social_unfurl, scanner, bot_other) lets the agent
distinguish "AI training crawler hitting your blog" from "real human
using ChatGPT to ask about your product". Most tools collapse both
into one "bot" bucket.
The tools
What your agent can call once your MCP URL is wired in.
list_sites- Every site on your account, with monthly hit counter.
add_site- Register a new domain. Pick the privacy mode (cannot be changed later).
remove_site- Soft-delete a site. Historical events expire on the table TTL.
get_tracking_snippet- The HTML
<script>tag for a given site. get_account- Email, plan, total usage this month.
regenerate_api_token- Rotate the legacy API token. Day-to-day, prefer revoking specific connectors via Settings; this is the nuclear option.
get_overview- TL;DR for a period. Pageviews, sessions, bounce, top page, top source, bot share, top events. This is the one your agent should call first when you ask "how did yesterday go?"
get_timeseries- Pageviews / visitors / sessions over time. Hour, day, or week buckets.
top_pages- Most-visited URL paths.
top_referrers- Top referring hosts (where the link came from). Counts direct browser visits only; AI-mediated traffic is excluded because the AI sets its own host as referrer or strips it; see
traffic_class_breakdownfor that split. top_sources- UTM source / medium / campaign breakdowns. Tag your shared links to see exactly what worked. Direct browser visits only (same reason as
top_referrers). breakdown- Visit counts by browser / OS / device type / country.
list_events- All custom event names with counts.
event_details- Drill into one event. Optional
group_by_propertyto slice by a custom prop. compare_periods- "Was last week better than the week before?" Head-to-head metric comparison.
top_user_agents- The top User-Agents that visited, with traffic_class. See exactly which AI agents (ChatGPT-User, Claude-User, GPTBot, ...) and crawlers fetched your pages.
traffic_class_breakdown- What share of your traffic was bots vs real users.
top_timezones/top_languages- Quasi-geo and locale signals from
Intl.DateTimeFormatandnavigator.language. No IP lookups. color_scheme_breakdown- Share of visitors with system dark mode on. Useful product signal.
viewport_breakdown- Real usable viewport widths, bucketed (mobile_xs / mobile / tablet / desktop / desktop_xl).
engagement_overview- Real reading time + scroll depth. Counts only when the tab is active, not just open.
Custom events
Pageviews are auto-tracked. Anything else you want, call mcpa('track', ...)
in your code:
// somewhere in your app
window.mcpa('track', 'signup', { plan: 'pro' });
window.mcpa('track', 'video_played', { duration_seconds: 42 });
Up to 20 properties per event. Strings, numbers, booleans only. Then ask Claude:
"How many signups last week, broken down by plan?" and it'll call
event_details with group_by_property: "plan".
Self-exclude (for builders)
Don't poison your own analytics with your own visits. Once on each browser/device:
https://your-site.com/?mcpa_exclude=1
The tracker stores a flag in localStorage and stops sending events
from that browser. Undo with ?mcpa_exclude=0. Survives navigation,
not browser-data clears.
FAQ
Why no dashboard?
Because dashboards are where data goes to die. You open it, scan the same five widgets, close it. mcp-analytics turns the workflow inside out: ask a question, get an answer. The agent does the chart-reading for you.
Will my agent figure this out without docs?
Yes. We expose get_started_guide as an MCP tool. Once your
connector URL is wired in, your agent will call it automatically when
it doesn't know what to do next. These human docs are just trust signal.
How does the free tier work?
Free up to 100,000 hits per month, unlimited sites. No card. After that we'll have paid tiers, but the free tier covers the vast majority of indie / side-project sites and we don't plan to take that away.
Can I export my raw data?
Yes. Completely. Every row, every column, every event you've sent us. No paywall, no API rate-limit, no "Enterprise tier" gate. Free users and paid users get the same export. You can leave whenever you want and take everything with you.
We don't lock you in. You'll stay because the product is good, not because leaving is painful.
What's the bot classification?
Every event gets one of eight traffic_class labels: user
(real human in their own browser), ai_user_action (a person asked an
LLM to fetch your page like Claude-User, ChatGPT-User, Perplexity-User),
ai_search (AI search-engine indexers like PerplexityBot), ai_training
(training crawlers like GPTBot, ClaudeBot), search_index (Googlebot,
Bingbot, ...), social_unfurl (Slackbot, link previews),
scanner (security/uptime/perf monitoring), bot_other
(recognized but not in any specific bucket).
Classification combines UA-pattern matching against ~70 curated patterns,
IP-CIDR lookups against vendor-published ranges (refreshed every 6h from OpenAI,
Google, Bing, AWS/GCP/Cloudflare), and reverse-DNS for Anthropic. Default analytics
queries show user + ai_user_action as "humans", a
person reading your content, whether through their own browser or via an AI
assistant. Use top_user_agents and traffic_class_breakdown
to see the full split.
OAuth?
Yes. Add mcp-analytics.com/mcp as a custom connector, your client
discovers our authorization server, registers itself dynamically (RFC 7591), and
runs the OAuth 2.1 + PKCE flow. We never see a long-lived bearer token in your
client; refresh-tokens rotate. Revoke any connected client any time from
Settings.
Where is my data stored?
In Germany, EU jurisdiction, GDPR scope. Visitor IPs are hashed in-memory for the session identifier and then dropped, so they don't land in the analytics database. We never share or sell your data. See the privacy policy for the full data-controller breakdown and sub-processor list.