View as Markdown
Google Search Console icon

Google Search Console ACTION

Query Search Analytics

Query Google Search Console search analytics for one property and one date range: clicks, impressions, CTR and average position, optionally grouped by dimensions and filtered. This is the main traffic-reporting tool for a site.

Use for any single-date-range question about how a site performs in Google Search — top queries, top pages, country or device splits, daily or hourly trends, the CTR or average position of a term. Use Compare Search Analytics instead for period-over-period questions (month over month, year over year, "did the update hurt us") — it fetches both ranges and joins them for you. Use Inspect URLs for index status, canonicals and crawl state; this tool only reports traffic.

Returns the API response unchanged — rows (each { keys, clicks, impressions, ctr, position }, where keys lines up positionally with dimensions), responseAggregationType and metadata — plus row_count, has_more (the page came back full, so more rows probably exist), next_start_row (pass it back as startRow) and returned_totals (clicks and impressions summed over the RETURNED rows only).

Reading the numbers. ctr is a 0-1 fraction (0.1428 means 14.3%) and position is a 1-indexed float where LOWER is better. Both are impression-weighted, so never re-average them across rows — a plain mean is wrong. returned_totals is not the property total, least of all when grouping by query: Google omits anonymized (rare) queries, so the sum of query rows is materially LESS than the same range grouped by date. For a true total, query with no dimensions or with date. And check has_more before reporting a count or a "top N" — a truncated first page is not the whole answer.

Scoping to one page or segment. Set subdomainFilter — the filter VALUE, despite the legacy prop name — together with filterDimension and filterOperator. For "page X only" that is filterDimension: page, filterOperator: equals, value = the full URL. Selecting a matching URL-prefix property instead is NOT equivalent: a prefix property covers every page under it, so the numbers come back for the whole prefix. Use advancedDimensionFilters for multi-condition filters; it is ignored whenever subdomainFilter is set.

Freshness. The most recent 2-3 days are not final and are omitted under dataState: final (the default), so a range ending today comes back one to three rows short. When the user asks for "the last N days" and every day needs a figure, set dataState: all.

Discover has no query dimension (400 "Request for DISCOVER cannot be grouped by query"). When the user asks for Discover queries, do not stop to ask: report Discover pages instead (searchType: discover, dimensions: ["page"]) and say why.

Example. siteUrl="sc-domain:example.com", startDate="2025-09-01", endDate="2026-08-31", dimensions=["query"], rowLimit=10 returns rows such as { keys: ["example brand"], clicks: 41, impressions: 287, ctr: 0.1429, position: 2.4 } plus row_count: 10, has_more: true and next_start_row: 10.

There is no fields parameter — rows are already minimal, so rowLimit plus has_more/next_start_row is the payload lever. Quota: 1,200 queries per minute per site. See the documentation

  • Action
  • Read only
  • OAuth
  • SDK
  • MCP

IMPLEMENTATION

Call this tool

Connect a user's Google Search Console account once, then configure and run Query Search Analytics from your backend or agent.

import { PipedreamClient } from "@pipedream/sdk"

const pd = new PipedreamClient({
  projectId: process.env.PIPEDREAM_PROJECT_ID!,
  clientId: process.env.PIPEDREAM_CLIENT_ID!,
  clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
  projectEnvironment: "production",
})

const result = await pd.actions.run({
  id: "google_search_console-retrieve-site-performance-data",
  externalUserId: "{external_user_id}", // any stable ID for this user in your system
  configuredProps: {
    google_search_console: { authProvisionId: "apn_xxxxxxx" },
    siteUrl: "Property (siteUrl)",
    startDate: "Start Date (YYYY-MM-DD)",
  },
})

console.log(result)

SCHEMA

Inputs

Pipedream supplies the connected account. Your application provides the operation-specific values below. Dynamic inputs are resolved against that user's account.

Query Search Analytics inputs
Property Type Description
siteUrl Property (siteUrl) string
Exact property identifier from List Sitessc-domain:example.com for a domain property, or a URL-prefix such as https://www.example.com/ (trailing slash; scheme and subdomain must match exactly, or the call 403s). Copy it verbatim, never construct it. For traffic questions prefer the domain property when one exists: it covers all subdomains and protocols.
Required
startDate Start Date (YYYY-MM-DD) string
First day of the range, inclusive, YYYY-MM-DD Pacific Time — e.g. 2025-09-01. Search Console keeps 16 months; an earlier date returns a 400. The most recent 2-3 days are not final and are omitted unless dataState is all.
Required
endDate End Date (YYYY-MM-DD) string
Last day of the range, inclusive, YYYY-MM-DD Pacific Time — e.g. 2026-08-31. Reporting lags 2-3 days, so an end date of today returns nothing for the final days unless dataState is all.
Required
dimensions Dimensions string[]
How to group the rows; each row's keys lines up positionally with this list, so ["query","device"] yields keys: ["example brand","MOBILE"]. Leave empty for a single totals row. Combination rules, each a 400 if broken: searchAppearance cannot be combined with ANY other dimension (fetch the appearance types alone, then filter by one with filterDimension: searchAppearance); hour cannot be combined with date, requires dataState: hourly_all, and covers at most 10 days; Discover (searchType: discover) has no query dimension. date returns one row per calendar day, zero-impression days included — so count rows with impressions > 0, not rows, for active days.
Optional
searchType Search Type string
Which Google surface to report on. web (default) is normal Google Search; discover is the Discover feed (no query dimension); googleNews is news.google.com, news is the News tab of Google Search. Sent to the API as type.
Optional
aggregationType Aggregation Type string
How Google aggregates the metrics. auto (default) lets Google choose — by page when grouping by page, by property otherwise. byPage aggregates by URI, byProperty across the whole property, byNewsShowcasePanel is for News Showcase. byProperty is rejected whenever a page dimension or page filter is present: 400 "'BY_PROPERTY' is not a valid aggregation type in the context of the request." The property-level average position is the byProperty number and does NOT equal the average of the byPage rows.
Optional
rowLimit Max Rows integer
Rows to return in this call. Defaults to 50; API maximum 25000, but keep it at 200 or below — 100 rows is ≈13k characters and 400 rows exceeds the output cap and is spilled to a file you cannot read. Size it to the task: 5-10 for a "top query" answer, 200 for a sweep, then page with startRow: next_start_row while has_more is true (there is no page token). The last page is the one returning fewer rows than rowLimit; an empty final page is normal.
Optional
startRow Start Row integer
Zero-based index of the first row to return. Omit for the first page, then pass the next_start_row value from the previous response to page forward.
Optional
subdomainFilter Filter Value string
The value to filter on, for ANY dimension — not just subdomains (Query Search Analytics keeps the legacy key subdomainFilter). Combined with filterDimension and filterOperator into one filter, e.g. filterDimension: page, filterOperator: contains, value https://www.example.com/blog/. page expressions match the FULL URL, scheme and host included, not a path. Setting this makes advancedDimensionFilters ignored.
Optional
filterDimension Filter Dimension string
Dimension the single-filter shortcut applies to; default page. Filtering does not require grouping by the same dimension — you can filter by page while grouping by query. page expressions match the FULL URL, scheme and host included, not a path.
Optional
filterOperator Filter Operator string
How the filter value is compared. String comparison is case-insensitive. includingRegex/excludingRegex use RE2 syntax (no lookahead/lookbehind). Default contains.
Optional
advancedDimensionFilters Advanced Dimension Filters string
JSON for multi-condition filtering, used only when the single-filter shortcut is empty. Accepts either a bare array of filters, which is ANDed into one group — e.g. [{"dimension":"country","operator":"equals","expression":"usa"},{"dimension":"device","operator":"equals","expression":"MOBILE"}] — or the raw API dimensionFilterGroups array, e.g. [{"groupType":"and","filters":[{"dimension":"page","operator":"contains","expression":"/blog/"}]}]. The API only supports groupType: "and"; there is no OR. Regex operators use RE2.
Optional
dataState Data State string
Which data to include. final (default) returns only finalized data, which lags roughly 2-3 days. all also includes the most recent, not-yet-final days and adds metadata.firstIncompleteDate — use it when the user explicitly wants recent or partial numbers. hourly_all is required by the hour dimension.
Optional

REFERENCE

Tool details

Behavior hints are published with the component in the Pipedream registry and surface as MCP tool annotations, so an agent can reason about a tool before it calls it.

Registry key
google_search_console-retrieve-site-performance-data
Version
1.1.0
App
Google Search Console
Authentication
OAuth
Read-only
Yes
Destructive
No
Open world
Yes