get-aggregate-stats
Retrieve aggregate site statistics like visitors, pageviews, bounce rate, and visit duration over a specified time period, enabling quick overview and summary analysis.
Instructions
Get aggregate stats for a site over a time period (visitors, pageviews, bounce rate, etc.). Use this for summary/overview questions.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| site_id | Yes | Domain of the site (e.g. 'example.com') | |
| metrics | No | Metrics to retrieve | |
| date_range | No | Time period. Use a preset like '30d' or a custom range ['2024-01-01', '2024-01-31'] | 30d |
| filters | No | Filters array using Plausible v2 syntax, e.g. [['is', 'event:page', ['/blog*']]] |
Implementation Reference
- src/index.ts:103-140 (handler)The MCP server.tool registration and handler for 'get-aggregate-stats'. The handler calls client.query() with site_id, metrics, date_range, and optional filters, then formats the aggregate result into a readable JSON response.
server.tool( "get-aggregate-stats", "Get aggregate stats for a site over a time period (visitors, pageviews, bounce rate, etc.). Use this for summary/overview questions.", { site_id: z.string().describe("Domain of the site (e.g. 'example.com')"), metrics: metricsSchema, date_range: dateRangeSchema, filters: filtersSchema, }, async ({ site_id, metrics, date_range, filters }) => { const result = await client.query({ site_id, metrics, date_range, filters: filters ?? undefined, }); // Format the aggregate result readably const row = result.results[0]; const formatted: Record<string, unknown> = {}; metrics.forEach((m, i) => { formatted[m] = row?.metrics[i]; }); return { content: [ { type: "text", text: JSON.stringify( { site_id, date_range, metrics: formatted }, null, 2 ), }, ], }; } ); - src/index.ts:64-70 (schema)Shared zod schema for date_range used by get-aggregate-stats. Supports preset strings ('30d', 'month', etc.) or custom [start, end] tuples.
const dateRangeSchema = z .union([ z.enum(["day", "7d", "30d", "month", "6mo", "12mo", "year", "all"]), z.tuple([z.string(), z.string()]).describe("Custom range: [start, end] in YYYY-MM-DD format"), ]) .describe("Time period. Use a preset like '30d' or a custom range ['2024-01-01', '2024-01-31']") .default("30d"); - src/index.ts:72-92 (schema)Shared zod schema for metrics array used by get-aggregate-stats. Enumerates valid Plausible metrics (visitors, pageviews, bounce_rate, etc.).
const metricsSchema = z .array( z.enum([ "visitors", "visits", "pageviews", "views_per_visit", "bounce_rate", "visit_duration", "events", "scroll_depth", "percentage", "conversion_rate", "group_conversion_rate", "average_revenue", "total_revenue", "time_on_page", ]) ) .describe("Metrics to retrieve") .default(["visitors", "pageviews", "bounce_rate", "visit_duration"]); - src/index.ts:94-99 (schema)Shared zod schema for filters used by get-aggregate-stats. Uses z.any() for the Plausible v2 filter syntax.
const filtersSchema = z .array(z.any()) .optional() .describe( "Filters array using Plausible v2 syntax, e.g. [['is', 'event:page', ['/blog*']]]" ); - src/plausible-client.ts:61-79 (helper)The query() method on PlausibleClient that the get-aggregate-stats handler calls. It POSTs to /api/v2/query with the provided params.
async query(params: PlausibleQueryParams): Promise<PlausibleQueryResult> { const response = await fetch(`${this.baseUrl}/api/v2/query`, { method: "POST", headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify(params), }); if (!response.ok) { const body = await response.text(); throw new Error( `Plausible API error (${response.status}): ${body}` ); } return response.json() as Promise<PlausibleQueryResult>; }