Skip to main content
Glama
wonyoungseong

GA4 MCP Server

ga4_run_realtime_report

Retrieve real-time Google Analytics data from the last 30 minutes for immediate insights into user activity and website performance.

Instructions

Runs a Google Analytics Data API realtime report. Returns real-time analytics data for the last 30 minutes.

Hints for arguments

Hints for dimensions

Use realtime dimensions from https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#dimensions Or user-scoped custom dimensions (apiName starting with "customUser:")

Hints for metrics

Use realtime metrics from https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#metrics Note: Realtime reports cannot use custom metrics.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
propertyIdYesThe Google Analytics property ID
dimensionsYesList of realtime dimension names (e.g., 'country', 'city', 'deviceCategory')
metricsYesList of realtime metric names (e.g., 'activeUsers', 'screenPageViews')
dimensionFilterNoFilter expression for dimensions
metricFilterNoFilter expression for metrics
orderBysNoList of order by specifications
limitNoMaximum number of rows to return
returnPropertyQuotaNoWhether to return realtime property quota information

Implementation Reference

  • The main handler function runRealtimeReport that executes the Google Analytics Data API realtime report request. It constructs the request body with dimensions, metrics, and optional filters, then calls client.properties.runRealtimeReport() and returns the response.
    export async function runRealtimeReport(params: RunRealtimeReportParams): Promise<ToolResponse> {
      try {
        const client = await getAnalyticsDataClient();
        const propertyName = constructPropertyResourceName(params.propertyId);
    
        // Build the request body
        const requestBody: Record<string, unknown> = {
          property: propertyName,
          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.returnPropertyQuota !== undefined) {
          requestBody.returnPropertyQuota = params.returnPropertyQuota;
        }
    
        const response = await client.properties.runRealtimeReport({
          property: propertyName,
          requestBody: requestBody,
        });
    
        return createSuccessResponse(response.data);
      } catch (error) {
        return createErrorResponse(`Failed to run realtime report for ${params.propertyId}`, error);
      }
    }
  • Tool schema definition for ga4_run_realtime_report including the name, description with hints for realtime dimensions and metrics, and inputSchema with propertyId, dimensions, metrics, dimensionFilter, metricFilter, orderBys, limit, and returnPropertyQuota properties.
          name: "ga4_run_realtime_report",
          description: `Runs a Google Analytics Data API realtime report. Returns real-time analytics data for the last 30 minutes.
    
    ## Hints for arguments
    
    ### Hints for dimensions
    Use realtime dimensions from https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#dimensions
    Or user-scoped custom dimensions (apiName starting with "customUser:")
    
    ### Hints for metrics
    Use realtime metrics from https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#metrics
    Note: Realtime reports cannot use custom metrics.`,
          inputSchema: {
            type: "object" as const,
            properties: {
              propertyId: {
                type: "string",
                description: "The Google Analytics property ID",
              },
              dimensions: {
                type: "array",
                items: { type: "string" },
                description: "List of realtime dimension names (e.g., 'country', 'city', 'deviceCategory')",
              },
              metrics: {
                type: "array",
                items: { type: "string" },
                description: "List of realtime metric names (e.g., 'activeUsers', 'screenPageViews')",
              },
              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",
              },
              returnPropertyQuota: {
                type: "boolean",
                description: "Whether to return realtime property quota information",
              },
            },
            required: ["propertyId", "dimensions", "metrics"],
          },
        },
  • Tool call routing that handles the ga4_run_realtime_report case by extracting arguments from the args object and calling the runRealtimeReport handler function.
    case "ga4_run_realtime_report":
      return await runRealtimeReport({
        propertyId: args.propertyId as 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,
        returnPropertyQuota: args.returnPropertyQuota as boolean | undefined,
      });
  • TypeScript interface defining the RunRealtimeReportParams type with all the parameters required for the realtime report handler.
    interface RunRealtimeReportParams {
      propertyId: string;
      dimensions: string[];
      metrics: string[];
      dimensionFilter?: FilterExpression;
      metricFilter?: FilterExpression;
      orderBys?: OrderBy[];
      limit?: number;
      returnPropertyQuota?: boolean;
    }
  • Helper function constructPropertyResourceName used by runRealtimeReport to format property IDs into the required 'properties/ID' format for GA4 API calls.
    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}`;
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool returns real-time data for the last 30 minutes and includes hints about API constraints (e.g., realtime-specific dimensions/metrics, no custom metrics), which adds useful context. However, it does not cover other behavioral aspects like authentication requirements, rate limits, error handling, or data format, leaving gaps for a mutation-like operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose in the first sentence, followed by a structured hints section. It avoids redundancy and wastes no words, though the hints could be slightly more integrated into the main description for optimal flow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 parameters, nested objects, no output schema, and no annotations), the description provides a solid foundation with purpose, time scope, and parameter hints. However, it lacks details on output format, error cases, or integration with sibling tools, making it adequate but incomplete for full contextual understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 8 parameters thoroughly. The description adds value through the hints section, which clarifies valid sources for dimensions and metrics (e.g., realtime API schema, user-scoped custom dimensions) and restrictions (no custom metrics), providing semantic context beyond the schema's technical descriptions. This justifies a baseline score of 3 with some enhancement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Runs a Google Analytics Data API realtime report') and resource ('real-time analytics data for the last 30 minutes'), distinguishing it from sibling tools like 'ga4_run_report' (which presumably handles non-realtime reports) and other GA4 tools focused on metadata or configuration.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly indicates usage context by specifying 'real-time analytics data for the last 30 minutes' and the hints section clarifies constraints on dimensions and metrics (e.g., 'Realtime reports cannot use custom metrics'). However, it lacks explicit guidance on when to choose this tool over alternatives like 'ga4_run_report' or other siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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