Skip to main content
Glama
AdLoop: Google Ads, Reddit Ads & GA4

AdLoop: Google Ads, Reddit Ads & GA4

Analytics report

run_ga4_report
Read-only

Runs a custom GA4 report with dimensions, metrics, filters, ordering, paging and comparison periods. Queries the GA4 Data API and flags sampling, thresholding or quota issues that skew results.

Instructions

Run a custom GA4 report with optional filters, ordering, paging and a comparison period.

Returns the property, the date range, the dimension and metric headers, one row per dimension combination (values as strings), row_count and total_row_count (plus next_offset while more rows remain). At least one dimension or metric is required. With compare_start/compare_end the comparison period is a second date range: every row then carries a dateRange value of "current" or "comparison", and date_ranges maps both labels to their dates. Invalid filters or ordering return "Validation failed" with details, before anything is sent. insights[] says when GA4 thresholded or sampled the data, grouped rows into "(other)", or the property is close to its API quota, because each makes numbers differ from the GA4 interface. Reports over time (a date-type dimension) or comparing periods also return the property's annotations in those dates, which often explain a jump in the rows.

Queries the GA4 Data API. Dimensions and metrics: https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "run_ga4_report"
  }
}

Input Schema

NameRequiredDescriptionDefault
limitNoMaximum number of rows returned (positive).
offsetNoZero-based row offset for paging; pass next_offset from the previous result to get the following page.
metricsNoGA4 metric API names, e.g. sessions, totalUsers, newUsers, screenPageViews, keyEvents, eventCount, bounceRate.
order_byNoSort order as [{"field": <name>, "desc": true|false}]; each field must be one of the requested dimensions or metrics.
dimensionsNoGA4 dimension API names, e.g. date, pagePath, sessionSource, sessionMedium, country, deviceCategory, eventName. Custom ones (customEvent:...) and every valid name are listed by list_ga4_dimensions_and_metrics.
compare_endNoEnd of the comparison period.
date_rangesNoUp to four named periods in one report, replacing date_range_start/end (not combinable with compare_start/end): [{"start": "2026-10-01", "end": "2026-10-31", "name": "october"}, {"start": "2025-10-01", "end": "2025-10-31", "name": "october_last_year"}]. Rows then carry a dateRange value with the name. Names default to range_1, range_2, ...
property_idNoGA4 property as "properties/123456789" (see get_account_summaries). If empty, uses the default from config.
compare_startNoStart of the comparison period (same formats as date_range_start). Set together with compare_end.
currency_codeNoISO 4217 code (e.g. "EUR") to report revenue and cost metrics in that currency instead of the property's own.
metric_filterNoConditions on metrics, applied after aggregation, all of which must hold (AND). Each is {"field": <metric>, "op": <op>, "value": <number>}; op is EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL (or =, <, <=, >, >=), or BETWEEN with "value": [from, to]. Optional "not": true. Groups work as in dimension_filter. Example: [{"field": "sessions", "op": ">", "value": 100}].
date_range_endNoEnd date, same formats as date_range_start.today
date_range_startNoStart date: "today", "yesterday", "NdaysAgo" (e.g. "7daysAgo", "28daysAgo", "90daysAgo"), or "YYYY-MM-DD".7daysAgo
dimension_filterNoConditions on dimensions, all of which must hold (AND). Each is {"field": <dimension>, "op": <match>, "value": <string>}; op is EXACT (default), BEGINS_WITH, ENDS_WITH, CONTAINS, FULL_REGEXP, PARTIAL_REGEXP, or IN_LIST with "values": [<strings>]. Optional keys: "case_sensitive" (default false) and "not": true to exclude matches. Example: [{"field": "sessionDefaultChannelGroup", "op": "EXACT", "value": "Paid Search"}]. For OR, put a group in the list: {"any_of": [<conditions>]} matches when any holds, {"all_of": [...]} when all hold; groups take "not" too and nest up to three levels. Example: [{"any_of": [{"field": "sessionSource", "value": "google"}, {"field": "sessionSource", "value": "bing"}]}].

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.41.4
    • addedInput schema / properties / currency_code
      Added value: +{
      +  "default": "",
      +  "description": "ISO 4217 code (e.g. \"EUR\") to report revenue and cost\nmetrics in that currency instead of the property's own.",
      +  "type": "string"
      +}
    • addedInput schema / properties / date_ranges
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Up to four named periods in one report, replacing\ndate_range_start/end (not combinable with compare_start/end):\n[{\"start\": \"2026-10-01\", \"end\": \"2026-10-31\", \"name\": \"october\"},\n{\"start\": \"2025-10-01\", \"end\": \"2025-10-31\", \"name\":\n\"october_last_year\"}]. Rows then carry a dateRange value with the\nname. Names default to range_1, range_2, ..."
      +}
    • changedInput schema / properties / dimension_filter / description
      Previous value: -"Conditions on dimensions, all of which must hold\n(AND). Each is {\"field\": <dimension>, \"op\": <match>, \"value\":\n<string>}; op is EXACT (default), BEGINS_WITH, ENDS_WITH,\nCONTAINS, FULL_REGEXP, PARTIAL_REGEXP, or IN_LIST with \"values\":\n[<strings>]. Optional keys: \"case_sensitive\" (default false) and\n\"not\": true to exclude matches. Example: [{\"field\":\n\"sessionDefaultChannelGroup\", \"op\": \"EXACT\", \"value\": \"Paid\nSearch\"}]."New value: +"Conditions on dimensions, all of which must hold\n(AND). Each is {\"field\": <dimension>, \"op\": <match>, \"value\":\n<string>}; op is EXACT (default), BEGINS_WITH, ENDS_WITH,\nCONTAINS, FULL_REGEXP, PARTIAL_REGEXP, or IN_LIST with \"values\":\n[<strings>]. Optional keys: \"case_sensitive\" (default false) and\n\"not\": true to exclude matches. Example: [{\"field\":\n\"sessionDefaultChannelGroup\", \"op\": \"EXACT\", \"value\": \"Paid\nSearch\"}]. For OR, put a group in the list: {\"any_of\":\n[<conditions>]} matches when any holds, {\"all_of\": [...]} when\nall hold; groups take \"not\" too and nest up to three levels.\nExample: [{\"any_of\": [{\"field\": \"sessionSource\", \"value\":\n\"google\"}, {\"field\": \"sessionSource\", \"value\": \"bing\"}]}]."
    • changedInput schema / properties / metric_filter / description
      Previous value: -"Conditions on metrics, applied after aggregation, all\nof which must hold (AND). Each is {\"field\": <metric>, \"op\": <op>,\n\"value\": <number>}; op is EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL,\nGREATER_THAN, GREATER_THAN_OR_EQUAL (or =, <, <=, >, >=), or\nBETWEEN with \"value\": [from, to]. Optional \"not\": true.\nExample: [{\"field\": \"sessions\", \"op\": \">\", \"value\": 100}]."New value: +"Conditions on metrics, applied after aggregation, all\nof which must hold (AND). Each is {\"field\": <metric>, \"op\": <op>,\n\"value\": <number>}; op is EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL,\nGREATER_THAN, GREATER_THAN_OR_EQUAL (or =, <, <=, >, >=), or\nBETWEEN with \"value\": [from, to]. Optional \"not\": true. Groups\nwork as in dimension_filter.\nExample: [{\"field\": \"sessions\", \"op\": \">\", \"value\": 100}]."
  2. Changed12 schema fields changedv0.27.1
    • addedInput schema / properties / compare_end
      Added value: +{
      +  "default": "",
      +  "description": "End of the comparison period.",
      +  "type": "string"
      +}
    • addedInput schema / properties / compare_start
      Added value: +{
      +  "default": "",
      +  "description": "Start of the comparison period (same formats as\ndate_range_start). Set together with compare_end.",
      +  "type": "string"
      +}
    • addedInput schema / properties / date_range_end / description
      Added value: +"End date, same formats as date_range_start."
    • addedInput schema / properties / date_range_start / description
      Added value: +"Start date: \"today\", \"yesterday\", \"NdaysAgo\" (e.g.\n\"7daysAgo\", \"28daysAgo\", \"90daysAgo\"), or \"YYYY-MM-DD\"."
    • addedInput schema / properties / dimension_filter
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Conditions on dimensions, all of which must hold\n(AND). Each is {\"field\": <dimension>, \"op\": <match>, \"value\":\n<string>}; op is EXACT (default), BEGINS_WITH, ENDS_WITH,\nCONTAINS, FULL_REGEXP, PARTIAL_REGEXP, or IN_LIST with \"values\":\n[<strings>]. Optional keys: \"case_sensitive\" (default false) and\n\"not\": true to exclude matches. Example: [{\"field\":\n\"sessionDefaultChannelGroup\", \"op\": \"EXACT\", \"value\": \"Paid\nSearch\"}]."
      +}
    • addedInput schema / properties / dimensions / description
      Added value: +"GA4 dimension API names, e.g. date, pagePath,\nsessionSource, sessionMedium, country, deviceCategory, eventName.\nCustom ones (customEvent:...) and every valid name are listed by\nlist_ga4_dimensions_and_metrics."
    • addedInput schema / properties / limit / description
      Added value: +"Maximum number of rows returned (positive)."
    • addedInput schema / properties / metric_filter
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Conditions on metrics, applied after aggregation, all\nof which must hold (AND). Each is {\"field\": <metric>, \"op\": <op>,\n\"value\": <number>}; op is EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL,\nGREATER_THAN, GREATER_THAN_OR_EQUAL (or =, <, <=, >, >=), or\nBETWEEN with \"value\": [from, to]. Optional \"not\": true.\nExample: [{\"field\": \"sessions\", \"op\": \">\", \"value\": 100}]."
      +}
    • addedInput schema / properties / metrics / description
      Added value: +"GA4 metric API names, e.g. sessions, totalUsers, newUsers,\nscreenPageViews, keyEvents, eventCount, bounceRate."
    • addedInput schema / properties / offset
      Added value: +{
      +  "default": 0,
      +  "description": "Zero-based row offset for paging; pass next_offset from the\nprevious result to get the following page.",
      +  "type": "integer"
      +}
    • addedInput schema / properties / order_by
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Sort order as [{\"field\": <name>, \"desc\": true|false}]; each\nfield must be one of the requested dimensions or metrics."
      +}
    • addedInput schema / properties / property_id / description
      Added value: +"GA4 property as \"properties/123456789\" (see\nget_account_summaries). If empty, uses the default from config."
  3. First observedv0.9.0

TDQS

A4.1/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/non-destructive; the description goes far beyond by disclosing the row shape, string-typed values, row_count/total_row_count/next_offset paging, the 'current'/'comparison' dateRange labeling and date_ranges mapping, pre-flight 'Validation failed' errors before any request is sent, and insights[] for thresholding, sampling, '(other)' grouping and quota proximity. This is exactly the kind of behavioral context annotations cannot carry.

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 capability sentence is front-loaded and each subsequent block (return shape, comparison, validation, insights, annotations) is a distinct concern. It runs long for a description, but nearly every clause adds information an agent needs to interpret results, with only minor redundancy against the schema.

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

Completeness5/5

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

For a 14-parameter reporting tool with an output schema, the description still covers the non-obvious parts an agent cannot get from structured fields: how paging advances, how comparison labels appear, why numbers differ from the GA4 UI, and failure behavior. Nothing material to calling or interpreting the tool is missing.

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

Parameters4/5

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

Schema description coverage is 100%, so the schema alone would justify a 3. The description adds cross-parameter semantics the schema only partly encodes: that compare_start/compare_end turns the comparison into a second date range observable in every row, and that insights[] relates to the reported numbers — both help the agent interpret parameter effects.

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

Purpose4/5

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

The opening sentence gives a specific verb plus resource ('Run a custom GA4 report') and enumerates the capability surface (filters, ordering, paging, comparison period). Siblings such as run_gsc_report, run_realtime_report, run_ga4_funnel and run_ga4_attribution are not named, so the agent must infer from the tool name which of the GA4 reporters to pick.

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

Usage Guidelines3/5

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

There is one hard precondition ('At least one dimension or metric is required') and an implicit cue that date-type dimensions matter for time-series, but no explicit when-to-use versus run_ga4_funnel, run_ga4_attribution, run_realtime_report or run_gaql. Usage is implied by the capability list rather than stated as decision guidance.

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

Deploy Server

Other Tools