---
title: "Live web analytics query (Growth+)"
method: POST
path: "/web_analytics/query"
tags: ["AI & Agent Traffic"]
---

# Live web analytics query (Growth+)

`POST /web_analytics/query`

## Request

- Base URL: `https://api.llmpulse.ai/api/v1`
- URL: `https://api.llmpulse.ai/api/v1/web_analytics/query`
- Auth: API key in header `Authorization`

Runs a read-only query, written in the connected provider's native format, against the project's property and returns columns and rows: a GA4 Data API runReport body, an Adobe Analytics or Customer Journey Analytics report request, Matomo Reporting API parameters (get methods only), PostHog HogQL, a Plausible Stats API v2 query or a Piano getData body. The connected property, site, report suite or project is always used and any property field in the query is ignored. Rows default to 100 and are capped at 5,000. Identical queries are answered from a 10-minute cache (cached: true). A query the provider rejects returns ERR_WEB_ANALYTICS_INVALID_QUERY (422) with the provider's own validation message. Each uncached query spends the customer's provider API quota. A read: no writable key is needed. Supported providers: Google Analytics 4, Adobe Analytics or Customer Journey Analytics, Matomo, PostHog, Plausible and Piano, connected on the AI Traffic page. Requires the Growth plan or above; otherwise ERR_PLAN_REQUIRED. Without a connected provider returns ERR_WEB_ANALYTICS_NOT_CONNECTED (404); a provider that refuses the stored credentials returns ERR_WEB_ANALYTICS_ACCESS_REVOKED (403); an unavailable provider, an exhausted provider quota, more than 20 uncached queries a minute or too many running at once for the project returns ERR_WEB_ANALYTICS_UPSTREAM (503): wait for the number of seconds in Retry-After before retrying.

## Request body

- object
  - `project_id` integer, required
  - `query` unknown, required

## Response `200`

Query result as columns and rows

- WebAnalyticsQueryResponse
  - `project_id` integer
  - `provider` 'google_analytics' | 'adobe_analytics' | 'matomo' | 'posthog' | 'plausible' | 'piano'
  - `property` string
  - `columns` object[]
    - `name` string
    - `kind` string: dimension or metric, when the provider says.
    - `type` string: The provider's column type, when it says (PostHog).
    - `label` string: The provider's display label, when it sends one (Piano).
  - `rows` array[]: One array per row, values in column order: strings, numbers or null.
    - unknown[]
      - unknown
  - `row_count` integer: Rows in this response (at most 5,000).
  - `total_rows` integer: Rows the provider has for the query, when it reports it.
  - `truncated` boolean: True when the provider has more rows than returned; page with its own offset or page field.
  - `totals` object: Metric totals by metric name, when the query asked for them.
  - `notes` string[]: Provider caveats: sampling, thresholds, more rows available.
  - `meta` object: Provider metadata such as GA4 time zone, currency and remaining property quota.
  - `fetched_at` string, date-time: When the provider answered.
  - `cached` boolean: True when the answer came from the 10-minute cache instead of the provider.
  - `query` object: The request as sent to the provider, with the connected property forced and limits applied.
  - `request_id` string

## Other responses

- `403`: Access forbidden
- `404`: Resource not found
- `422`: Invalid parameters
- `503`: Upstream provider unavailable, retry after the number of seconds in the Retry-After header: Google's own value when it sent one, otherwise 900 after a quota error and 60 after an outage

## Changes

- **2026-10-10** `bfef7c3dc382`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/llmpulse/apis/llm-pulse-api/changes/web_analytics/query/post.md)

---

[API](https://skmtc.dev/llmpulse/apis/llm-pulse-api.md) - [All operations](https://skmtc.dev/llmpulse/apis/llm-pulse-api/llms.txt) - [OpenAPI document](https://skmtc.dev/llmpulse/apis/llm-pulse-api/revisions/38a31f123641?raw)
