---
title: "List search query statistics"
method: GET
path: "/projects/{project_id}/analytics/query-stats"
tags: ["analytics"]
---

# List search query statistics

`GET /projects/{project_id}/analytics/query-stats`

## Request

- Base URL: `https://eu.bisibility.com/api/v1`
- URL: `https://eu.bisibility.com/api/v1/projects/{project_id}/analytics/query-stats`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `/api/auth/oauth2/authorize`, token URL `/api/auth/oauth2/token`, scopes: `api:read`)

## Path parameters

- `project_id` string, required: Public project ID; membership and token scope are enforced.

## Query parameters

- `start_date` string, required
- `end_date` string, required
- `connection_id` string
- `query` string
- `limit` integer
- `clicks_min` integer
- `impressions_min` integer
- `position_max` number
- `page_path` string
- `page_path_match` 'contains' | 'prefix'
- `query_match` 'equals' | 'contains'

## Headers

- `Bisibility-API-Version` 'v1'
- `X-Bisibility-Source` 'sdk' | 'cli' | 'mcp'

## Response `200`

JSON response

- SearchPerformanceQueryStatsResponse: Rows are the provider's aggregate over all countries and devices for the range; filter by query is exact match unless query_match=contains.
  - `connection` AnalyticsConnection, required
    - `id` string, required
    - `label` string, required
    - `provider` string, required
  - `result` object, required
    - `row_cap` integer, required: Maximum number of rows this request can return.
    - `rows_returned` integer, required: Rows carried in this response after all filters.
    - `sort` 'clicks_desc', required: Rows are ordered by clicks, highest first.
    - `truncated` boolean, required: True exactly when this response carries row_cap rows; more matching rows may exist. clicks_min, impressions_min and position_max are applied after the source cap, so when they are set a false value does not prove that no further matching rows exist.
  - `rows` SearchPerformanceQueryStat[], required
    - `clicks` integer, required
    - `ctr` number, required
    - `impressions` integer, required
    - `page` string, nullable
    - `position` number, required
    - `query` string, required
  - `scope` object, required
    - `country` unknown, required
    - `device` unknown, required
    - `dimensions` string[], required: Dimensions the source grouped rows by: query, or query and page when page_path is set.
    - `end_date` string, date, required
    - `page_path` string, nullable, required: Page path filter applied, or null when none was requested.
    - `query_match` 'equals' | 'contains', required: Match semantics applied to the query filter: exact match unless query_match=contains.
    - `start_date` string, date, required

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: No eligible search-performance source is connected.
- `409`: Unsupported API version
- `422`: Provider authorization must be renewed (re-auth needed).
- `429`: Rate limited

## Changes

- **2026-10-19** `a6e1ec0dec82`: 6 breaking, 1 warning, 9 info
  - added the new path request parameter `project_id`
  - for the `query` request parameter `connection_id`, the minLength was increased from `0` to `1`
  - for the `query` request parameter `page_path`, the minLength was increased from `0` to `1`
  - for the `query` request parameter `query`, the minLength was increased from `0` to `1`
  - …12 more

[Operation history](https://skmtc.dev/bisibility/apis/bisibility-public-api/changes/projects/:project_id/analytics/query-stats/get.md)

---

[API](https://skmtc.dev/bisibility/apis/bisibility-public-api.md) · [All operations](https://skmtc.dev/bisibility/apis/bisibility-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bisibility/apis/bisibility-public-api/revisions/a6e1ec0dec82?raw)
