Skip to main content
Glama
wonyoungseong

GA4 MCP Server

ga4_run_report

Generate Google Analytics 4 reports by specifying dimensions, metrics, and date ranges to retrieve website or app performance data for analysis.

Instructions

Runs a Google Analytics Data API report. Returns analytics data based on the specified dimensions, metrics, and date ranges.

Hints for arguments

Hints for dimensions

The dimensions list must consist solely of either:

  1. Standard dimensions from https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#dimensions

  2. Custom dimensions for the property. Use ga4_custom_dimensions_metrics to retrieve custom dimensions.

Hints for metrics

The metrics list must consist solely of either:

  1. Standard metrics from https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics

  2. Custom metrics for the property. Use ga4_custom_dimensions_metrics to retrieve custom metrics.

Hints for dateRanges

Examples:

  • Single range: [{"startDate": "2025-01-01", "endDate": "2025-01-31"}]

  • Relative: [{"startDate": "30daysAgo", "endDate": "yesterday"}]

  • Multiple: [{"startDate": "2025-01-01", "endDate": "2025-01-31", "name": "Jan"}, {"startDate": "2025-02-01", "endDate": "2025-02-28", "name": "Feb"}]

Hints for dimensionFilter

Example: {"filter": {"fieldName": "eventName", "stringFilter": {"matchType": "BEGINS_WITH", "value": "page"}}}

Hints for orderBys

Example: [{"dimension": {"dimensionName": "eventName"}, "desc": false}] or [{"metric": {"metricName": "eventCount"}, "desc": true}]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
propertyIdYesThe Google Analytics property ID. Accepted formats: '123456789' or 'properties/123456789'
dateRangesYesList of date ranges for the report
dimensionsYesList of dimension names (e.g., 'eventName', 'country', 'deviceCategory')
metricsYesList of metric names (e.g., 'activeUsers', 'eventCount', 'sessions')
dimensionFilterNoFilter expression for dimensions
metricFilterNoFilter expression for metrics
orderBysNoList of order by specifications
limitNoMaximum number of rows to return (default: 10000, max: 250000)
offsetNoRow offset for pagination (0-indexed)
currencyCodeNoISO4217 currency code (e.g., 'USD', 'EUR', 'JPY')
returnPropertyQuotaNoWhether to return property quota information

Implementation Reference

  • The main handler function runReport that executes the Google Analytics Data API report. It constructs the request, calls the API with all parameters (dimensions, metrics, date ranges, filters, orderBys, limit, offset, currencyCode, returnPropertyQuota), and returns the response.
    export async function runReport(params: RunReportParams): Promise<ToolResponse> { try { const client = await getAnalyticsDataClient(); const propertyName = constructPropertyResourceName(params.propertyId); // Build the request body const requestBody: Record<string, unknown> = { property: propertyName, dateRanges: params.dateRanges, dimensions: params.dimensions.map(name => ({ name })), metrics: params.metrics.map(name => ({ name })), }; if (params.dimensionFilter) { requestBody.dimensionFilter = params.dimensionFilter; } if (params.metricFilter) { requestBody.metricFilter = params.metricFilter; } if (params.orderBys && params.orderBys.length > 0) { requestBody.orderBys = params.orderBys; } if (params.limit !== undefined) { requestBody.limit = params.limit; } if (params.offset !== undefined) { requestBody.offset = params.offset; } if (params.currencyCode) { requestBody.currencyCode = params.currencyCode; } if (params.returnPropertyQuota !== undefined) { requestBody.returnPropertyQuota = params.returnPropertyQuota; } const response = await client.properties.runReport({ property: propertyName, requestBody: requestBody, }); return createSuccessResponse(response.data); } catch (error) { return createErrorResponse(`Failed to run report for ${params.propertyId}`, error); } }
  • TypeScript interface definitions for report parameters including DateRange, FilterExpression, OrderBy, and RunReportParams that define the input schema structure for the ga4_run_report tool.
    interface DateRange { startDate: string; endDate: string; name?: string; } interface FilterExpression { filter?: { fieldName: string; stringFilter?: { matchType: string; value: string; caseSensitive?: boolean; }; numericFilter?: { operation: string; value: { int64Value?: string; doubleValue?: number; }; }; inListFilter?: { values: string[]; caseSensitive?: boolean; }; betweenFilter?: { fromValue: { int64Value?: string; doubleValue?: number }; toValue: { int64Value?: string; doubleValue?: number }; }; emptyFilter?: Record<string, never>; }; andGroup?: { expressions: FilterExpression[] }; orGroup?: { expressions: FilterExpression[] }; notExpression?: FilterExpression; } interface OrderBy { dimension?: { dimensionName: string; orderType?: string; }; metric?: { metricName: string; }; desc?: boolean; } interface RunReportParams { propertyId: string; dateRanges: DateRange[]; dimensions: string[]; metrics: string[]; dimensionFilter?: FilterExpression; metricFilter?: FilterExpression; orderBys?: OrderBy[]; limit?: number; offset?: number; currencyCode?: string; returnPropertyQuota?: boolean; }
  • MCP tool registration definition for ga4_run_report with name, description including hints for dimensions, metrics, dateRanges, filters, and orderBys, plus the complete inputSchema defining all parameters and their requirements.
    name: "ga4_run_report", description: `Runs a Google Analytics Data API report. Returns analytics data based on the specified dimensions, metrics, and date ranges. ## Hints for arguments ### Hints for dimensions The dimensions list must consist solely of either: 1. Standard dimensions from https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#dimensions 2. Custom dimensions for the property. Use ga4_custom_dimensions_metrics to retrieve custom dimensions. ### Hints for metrics The metrics list must consist solely of either: 1. Standard metrics from https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics 2. Custom metrics for the property. Use ga4_custom_dimensions_metrics to retrieve custom metrics. ### Hints for dateRanges Examples: - Single range: [{"startDate": "2025-01-01", "endDate": "2025-01-31"}] - Relative: [{"startDate": "30daysAgo", "endDate": "yesterday"}] - Multiple: [{"startDate": "2025-01-01", "endDate": "2025-01-31", "name": "Jan"}, {"startDate": "2025-02-01", "endDate": "2025-02-28", "name": "Feb"}] ### Hints for dimensionFilter Example: {"filter": {"fieldName": "eventName", "stringFilter": {"matchType": "BEGINS_WITH", "value": "page"}}} ### Hints for orderBys Example: [{"dimension": {"dimensionName": "eventName"}, "desc": false}] or [{"metric": {"metricName": "eventCount"}, "desc": true}]`, inputSchema: { type: "object" as const, properties: { propertyId: { type: "string", description: "The Google Analytics property ID. Accepted formats: '123456789' or 'properties/123456789'", }, dateRanges: { type: "array", items: { type: "object", properties: { startDate: { type: "string", description: "Start date (YYYY-MM-DD, yesterday, today, NdaysAgo)" }, endDate: { type: "string", description: "End date (YYYY-MM-DD, yesterday, today, NdaysAgo)" }, name: { type: "string", description: "Optional name for the date range" }, }, required: ["startDate", "endDate"], }, description: "List of date ranges for the report", }, dimensions: { type: "array", items: { type: "string" }, description: "List of dimension names (e.g., 'eventName', 'country', 'deviceCategory')", }, metrics: { type: "array", items: { type: "string" }, description: "List of metric names (e.g., 'activeUsers', 'eventCount', 'sessions')", }, dimensionFilter: { type: "object", description: "Filter expression for dimensions", }, metricFilter: { type: "object", description: "Filter expression for metrics", }, orderBys: { type: "array", items: { type: "object" }, description: "List of order by specifications", }, limit: { type: "number", description: "Maximum number of rows to return (default: 10000, max: 250000)", }, offset: { type: "number", description: "Row offset for pagination (0-indexed)", }, currencyCode: { type: "string", description: "ISO4217 currency code (e.g., 'USD', 'EUR', 'JPY')", }, returnPropertyQuota: { type: "boolean", description: "Whether to return property quota information", }, }, required: ["propertyId", "dateRanges", "dimensions", "metrics"], }, },
  • The routing switch case that maps the ga4_run_report tool name to the runReport handler function, extracting all parameters from the args object and passing them to the handler.
    case "ga4_run_report": return await runReport({ propertyId: args.propertyId as string, dateRanges: args.dateRanges as Array<{ startDate: string; endDate: string; name?: string }>, dimensions: args.dimensions as string[], metrics: args.metrics as string[], dimensionFilter: args.dimensionFilter as Record<string, unknown> | undefined, metricFilter: args.metricFilter as Record<string, unknown> | undefined, orderBys: args.orderBys as Array<Record<string, unknown>> | undefined, limit: args.limit as number | undefined, offset: args.offset as number | undefined, currencyCode: args.currencyCode as string | undefined, returnPropertyQuota: args.returnPropertyQuota as boolean | undefined, });
  • Helper functions used by the runReport handler: constructPropertyResourceName (formats property ID for GA4 API), createSuccessResponse (formats successful MCP responses), and createErrorResponse (formats error responses).
    export function constructPropertyResourceName(propertyId: string | number): string { let propertyNum: number | null = null; if (typeof propertyId === "number") { propertyNum = propertyId; } else if (typeof propertyId === "string") { const trimmed = propertyId.trim(); if (/^\d+$/.test(trimmed)) { propertyNum = parseInt(trimmed, 10); } else if (trimmed.startsWith("properties/")) { const numericPart = trimmed.split("/")[1]; if (numericPart && /^\d+$/.test(numericPart)) { propertyNum = parseInt(numericPart, 10); } } } if (propertyNum === null) { throw new Error( `Invalid property ID: ${propertyId}. ` + "A valid property value is either a number or a string starting " + "with 'properties/' and followed by a number." ); } return `properties/${propertyNum}`; } /** * Creates a successful MCP tool response with JSON data. */ export function createSuccessResponse(data: unknown): ToolResponse { return { content: [ { type: "text", text: JSON.stringify(data, null, 2), }, ], }; } /** * Creates an error MCP tool response. */ export function createErrorResponse(message: string, error?: unknown): ToolResponse { let errorMessage = message; if (error) { if (error instanceof Error) { errorMessage += `: ${error.message}`; } else if (typeof error === "string") { errorMessage += `: ${error}`; } else { errorMessage += `: ${JSON.stringify(error)}`; } } return { content: [ { type: "text", text: errorMessage, }, ], isError: true, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wonyoungseong/ga4-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server