Skip to main content

Search Console

Term → page

Which page Google sent a click to, for search terms you name.

GET/sites/{siteId}/search/term-pages
Term → page
curl --request GET \
  --url 'https://truestat.io/api/v1/sites/{siteId}/search/term-pages' \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "path": "/tools/youtube-title-checker",
      "term": "youtube title checker",
      "clicks": 7,
      "hostname": "codivupload.com",
      "impressions": 138
    }
  ],
  "meta": {
    "page": {
      "limit": 100,
      "offset": 0,
      "has_more": false
    },
    "range": {
      "to": "2026-09-16T00:00:00.000Z",
      "tz": "UTC",
      "from": "2025-09-16T00:00:00.000Z",
      "clamped": false
    },
    "site_id": "6fed8980-a119-4a9c-a4d4-53e448ef9f9e"
  }
}

The pairing between a search term and the page Google chose to show for it.

Google's figures — see totals for why they do not reconcile with the rest of your analytics.

The one without a cap

Terms embeds up to three landing pages per term, which is enough for most reading. This endpoint returns every pairing for the terms you name.

Reach for it when three is not enough:

  • One term ranks for a dozen of your pages and you want the whole picture

  • You are auditing which page Google prefers for a query, and the answer is the wrong page

  • You are checking whether two of your pages compete for the same term

terms is required

There is no "all terms" mode. The result is per term, so an unfiltered query would be your site's entire search history crossed with its pages — a large answer to a question nobody asked.

Name the terms, usually the ones terms just returned. There is a cap per request — the terms parameter above states it, and asking for more is refused rather than silently truncated. Send them in batches beyond that.

Separate terms with a newline, not a comma

This matters more than it looks. People search for shoes, red.

Split that on a comma and you look up two terms nobody typed, and both return nothing — which reads as "no data for this term" rather than as a mistake in the request. So the separator is a newline (%0A once url-encoded):

curl -G https://truestat.io/api/v1/sites/$SITE_ID/search/term-pages \
  -H "Authorization: Bearer $TRUESTAT_API_KEY" \
  --data-urlencode "period=last30d" \
  --data-urlencode "terms=youtube title checker
yt title checker"

--data-urlencode with a literal newline inside the quotes is the simplest way to do this from a shell. In code, join your terms with "\n" before encoding.

Reading the result

Rows carry the term back in term, so a response covering several terms can be grouped without tracking the order you sent them in.

A term appearing with two of your pages, both with meaningful clicks, usually means those pages compete for it — and consolidating them tends to rank better than either did alone.

Authorizations

Authorizationstringheaderrequired

An API key from Settings → API keys. Scopes available: analytics:read, sites:read, sites:write, settings:read, settings:write, goals:read, goals:write, funnels:read, funnels:write, notes:read, notes:write, alerts:read, alerts:write, team:read, team:write, revenue:read, revenue:write.

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path parameters

siteIdstring (uuid)pathrequired
The site's id, from `GET /sites`. A site that is not yours and a site that does not exist both answer 403, so this cannot be used to discover other people's ids.

Query parameters

termsstringqueryrequired
The search terms to look up, separated by newlines (`%0A` when url-encoded). Usually the terms `/search/terms` just returned. At most 25.
periodenum<string>query
A named window, resolved in `tz`. Cannot be combined with `from`/`to` — a request carrying both is refused rather than guessed at.
options:todayyesterdaylast24hlast7dlast30dlast12mmonthyearall
fromstring (date-time)query
Start of the window, ISO 8601 with an offset. Must be given together with `to`.
tostring (date-time)query
End of the window. Must be given together with `from`.
tzstringquerydefault: UTC
IANA timezone for day boundaries. `period=today&tz=Europe/Istanbul` means the reader's today, not the server's. Defaults to UTC.
botsenum<string>querydefault: excluded
Whether crawler traffic is counted. Excluded by default — the `/ai/*` endpoints report it separately and always include it.
options:excludedincluded
limitintegerquerydefault: 100
Rows per page, 1 to 1000.
offsetintegerquerydefault: 0
Rows to skip.

Response

application/json

The answer.

dataunknown
See the example.
metaobject