Skip to main content

Search Console

Terms

What people searched for before Google showed them your site.

GET/sites/{siteId}/search/terms
Terms
curl --request GET \
  --url 'https://truestat.io/api/v1/sites/{siteId}/search/terms' \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "ctr": 0.047,
      "term": "youtube title checker",
      "pages": [
        {
          "path": "/tools/youtube-title-checker",
          "clicks": 7,
          "hostname": "codivupload.com"
        }
      ],
      "clicks": 7,
      "position": 5.08,
      "impressions": 149
    }
  ],
  "meta": {
    "page": {
      "limit": 100,
      "offset": 0,
      "has_more": true
    },
    "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 search terms that produced impressions and clicks, most clicked first.

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

Each term brings its landing pages

Every row carries up to three pages in pages, most clicked first. They tell you which of your pages Google chose to show for that term — often not the one you would have picked.

They cost nothing extra. The pages come from one further query over the terms that survived the limit, not one query per term, so a page of terms is two round trips whatever its length.

Why three

Three is what the dashboard's tooltip shows, and keeping the same number here means the two agree.

It also keeps this response a predictable size. A term ranking for forty pages would otherwise return a payload forty times its neighbour's, which is an unpleasant surprise for anything paging through results.

When three is not enough — auditing which page Google prefers for a query, say — term → page lifts the cap for terms you name.

The field is clicks, not visitors

Google reports that somebody clicked a result. It does not say who, so these cannot be joined to the visitors your script counted, and calling them visitors would invite exactly that join.

ctr is clicks / impressions as a fraction — multiply by 100 for a percentage.

A worked reading

{
  "term": "invoice template generator",
  "clicks": 7,
  "impressions": 149,
  "position": 5.08,
  "ctr": 0.047,
  "pages": [
    { "hostname": "example.com", "path": "/tools/invoice-template", "clicks": 7 }
  ]
}

Shown 149 times at an average position of five, clicked seven times. A term sitting at position five with a low CTR usually means the title and description are not earning the click — which is something you can fix, unlike the position itself.

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

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