mcp
get_organic_traffic
MCP tool that returns the 28-day GA4 + GSC snapshot for an audit: sessions, daily trend, top landing pages, top queries, indexed pages.
What this tool does
get_organic_traffic returns a 28-day snapshot of organic traffic for an audit, pulled from the user’s linked Google Analytics 4 and Google Search Console properties.
- Returns
connected: falseif the user has not linked Google yet: the rest of the fields are then empty. - When connected:
sessions_28d(total organic sessions),sessions_trend(daily series),top_landing_pages(URL + sessions),top_queries(query + clicks + impressions), andindexed_pagesfrom GSC. - Cached 24 hours server-side per audit, so repeat calls are cheap and idempotent.
- Always tied to a specific
audit_id; the data window is relative to that audit’screated_at.
Why it matters
SEO audits without traffic data tell agents what to fix, but not what to fix first. get_organic_traffic lets an agent rank failing pages by real organic value so the recommendations land on URLs that actually move revenue.
Concrete workflows:
- A “where do I start?” agent calls
get_auditfor findings andget_organic_trafficfor sessions, then drafts a fix-list ordered bysessions_28dper landing page. - A query-gap agent reads
top_queries(high impressions, low clicks) and rewrites the matching page’s title and meta description to lift CTR.
How to use it
The user must connect Google Analytics 4 and Search Console inside the MetricSpot dashboard first. When unconnected, the tool still succeeds, it returns connected: false so agents can degrade gracefully and tell the user how to link Google.
Input schema
{
"type": "object",
"properties": {
"audit_id": { "type": "string", "minLength": 1 }
},
"required": ["audit_id"]
}
Response schema sample
{
"audit_id": "aud_01HZ8X9YP7K3T2N6Q5",
"connected": true,
"sessions_28d": 14328,
"sessions_trend": [
{ "date": "2026-04-15", "sessions": 482 },
{ "date": "2026-04-16", "sessions": 511 },
{ "date": "2026-04-17", "sessions": 539 }
],
"top_landing_pages": [
{ "url": "https://example.com/", "sessions": 5104 },
{ "url": "https://example.com/pricing", "sessions": 2871 },
{ "url": "https://example.com/blog/launch", "sessions": 1942 }
],
"top_queries": [
{ "query": "example pricing", "clicks": 612, "impressions": 8412 },
{ "query": "example alternative", "clicks": 387, "impressions": 5101 }
],
"indexed_pages": 184
}
When Google is not linked:
{
"audit_id": "aud_01HZ8X9YP7K3T2N6Q5",
"connected": false,
"sessions_28d": null,
"indexed_pages": null
}
Claude Code
claude mcp add --transport http metricspot https://mcp.metricspot.com/mcp \
--header "Authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"
Prompt:
For MetricSpot audit
aud_01HZ8X9YP7K3T2N6Q5, pull the organic traffic snapshot and tell me which top-10 query has the worst CTR.
Cursor
.cursor/mcp.json:
{
"mcpServers": {
"metricspot": {
"url": "https://mcp.metricspot.com/mcp",
"headers": {
"Authorization": "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
}
Prompt:
Combine the audit findings with
get_organic_trafficand list the failing pages that bring in the most sessions.
Python (rank pages by traffic)
import httpx, json
HEADERS = {
"content-type": "application/json",
"accept": "application/json, text/event-stream",
"authorization": "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx",
}
r = httpx.post("https://mcp.metricspot.com/mcp", headers=HEADERS, json={
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "get_organic_traffic",
"arguments": {"audit_id": "aud_01HZ8X9YP7K3T2N6Q5"},
},
}, timeout=30.0)
snap = json.loads(r.json()["result"]["content"][0]["text"])
if not snap["connected"]:
print("Connect GA4 + GSC at app.metricspot.com/settings/integrations")
else:
for q in snap.get("top_queries", [])[:5]:
ctr = q["clicks"] / q["impressions"] if q["impressions"] else 0
print(f"{q['query']}: CTR {ctr:.1%} ({q['clicks']} / {q['impressions']})")
Node / TypeScript (raw HTTP)
const res = await fetch("https://mcp.metricspot.com/mcp", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json, text/event-stream",
authorization: "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "get_organic_traffic",
arguments: { audit_id: "aud_01HZ8X9YP7K3T2N6Q5" },
},
}),
});
const snap = JSON.parse((await res.json()).result.content[0].text);
if (snap.connected) {
console.log(`${snap.sessions_28d} sessions in last 28d`);
}
Common errors
| Code | When | Action |
|---|---|---|
UNAUTHORIZED (401) | Missing or invalid Bearer token | Issue a key at https://app.metricspot.com/settings/api-keys |
AUDIT_NOT_FOUND (404) | audit_id doesn’t belong to this account | Call list_audits for valid ids |
FORBIDDEN (403) | Token lacks the Google scope | Reissue the key with default scopes after linking Google |
UPSTREAM_FAILED (5xx) | GA4 or GSC API outage | Retry; the response is cached 24h once successful |
Frequently asked questions
Why is connected: false even though I see traffic in GA4?
The connection lives on the MetricSpot side: the user must visit app.metricspot.com/settings/integrations and link Google Analytics 4 and Search Console explicitly. MetricSpot reads GA4 via the Analytics Data API and GSC via the Search Console API; both require OAuth grants the user authorizes once.
Why a 28-day window?
It matches how GSC reports its top queries by default and is short enough to reflect recent changes (post-deploy, post-launch) while long enough to smooth weekly seasonality. The window is not configurable in v1.
How fresh is the data?
GA4 data is typically 24-48 hours behind real time, per Google’s processing window. GSC data lags 2-3 days. The MCP response is cached 24 hours per audit_id server-side, so repeat calls in the same day return the same snapshot.
Sources
Last updated 2026-05-13