> This page is for Data API, version v2 (default).
> For other versions, use one of these documentation indexes:
> - v2 (default): https://developers.webflow.com/data/v2.0.0/llms.txt
> - v2 Beta: https://developers.webflow.com/data/v2.0.0-beta/llms.txt
> - v1: https://developers.webflow.com/data/v1.0.0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.webflow.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.webflow.com/_mcp/server.

# Working with Analyze

> Use the Webflow Analyze API to read site analytics: traffic, top pages, top dimensions, top events, and time on page.

The Analyze API lets you read a site's analytics through the Data API: traffic, top pages, top dimensions, top events, and time on page. Use it to build dashboards, sync metrics into other tools, or answer questions about how visitors use a site.

Every report is a read-only `GET` request. All reports share one filter model and report over a time window you choose.

> **Analyze add-on required**
>
> Analyze endpoints require an access token with the `sites:read` scope and a workspace that has the Analyze add-on.

## Choose a report

Each report answers a different question. Pick the one that matches what you want to measure.

#### [Traffic](/data/reference/analyze/traffic)

A daily time series of sessions, users, or page views over a window.

#### [Top pages](/data/reference/analyze/top-pages)

The most-visited pages, ranked by sessions, users, or page views.

#### [Top dimensions](/data/reference/analyze/top-dimensions)

The top values for a dimension you choose: country, device, traffic source, and more.

#### [Top events](/data/reference/analyze/top-events)

The top events, ranked by how often they occurred.

#### [Time on page](/data/reference/analyze/time-on-page)

The average time spent on a page, as one value or bucketed by day or week.

## Core concepts

### Metric scopes

Most reports measure activity in one of three units, set with `metricScope`:

* `session`: a single visit that groups a visitor's activity.
* `user`: a unique visitor.
* `pageview`: a single page load.

Support varies by report. Traffic and Time on page take any of the three. Top dimensions takes `session` or `user`. Top pages returns all three counts per row and uses `sortBy` to rank them. Top events counts how many times each event occurred and doesn't use a `metricScope`.

### Time windows

Pass `startTime` and `endTime` as UTC timestamps ending in `Z`, for example `2026-04-01T00:00:00Z`. Numeric offsets such as `-04:00` or `+00:00` aren't accepted.

A few rules apply to every report:

* The window can span at most **100 days**.
* The earliest supported `startTime` is **`2025-04-09T00:00:00Z`**.

### Bucket time zones

Reports that return buckets also report how those buckets were cut. Traffic is always bucketed, so it requires `bucketTimeZone`. Top pages and Top events return buckets only when you request `timeseries[bucketTimeZone]`. Time on page returns buckets only when you request both `timeseries[granularityPeriod]` and `timeseries[bucketTimeZone]`.

`bucketTimeZone` must be a valid IANA time zone. Use canonical names such as `UTC` or `America/New_York`. Bucket timestamps are still returned as UTC instants. For example, `America/New_York` local midnight on April 1, 2026 is returned as `2026-04-01T04:00:00.000Z`. Invalid time zones return `400 analyze_input_validation`.

### Filtering

Narrow any report to a subset of traffic in one of two ways:

* **Top-level query parameters**: shortcuts for common dimensions, such as `country`, `deviceType`, `trafficSource`, and `browser`. For example, `?country=US&deviceType=desktop`.
* **The `filter` parameter**: the full supported set, with operators. Use bracket notation: scalars take one value (`filter[country][eq]=US`), and arrays use indexed brackets (`filter[country][in][0]=US&filter[country][in][1]=CA`). Comma-separated values aren't supported.

Each dimension accepts `eq`, `in`, `ne`, or `nin`. Filter a given dimension in one place only: either a top-level parameter or a `filter` entry, not both. Using both returns `400 analyze_filter_conflict`. Each report supports its own set of dimensions; see the `filter` parameter on the report's reference page for the list.

> **Finding values to filter by**
>
> To filter by an enumerable dimension, call [Top dimensions](/data/reference/analyze/top-dimensions) with that `dimension` and reuse each row's `attributeKey` as the filter value. For example, `dimension=browser` returns `Chrome`, which you pass as `filter[browser][eq]=Chrome` or the `browser=Chrome` shortcut.

## Rate and concurrency limits

Analyze applies two limits in addition to standard authentication:

* **Rate limit**: the standard per-minute Data API [rate limit](/data/reference/rate-limits), based on the site plan.
* **Concurrency limit**: each access token can have one Analyze request in flight at a time, across all Analyze endpoints.

If either limit is exceeded, the request fails with `429 Too Many Requests` and a `Retry-After` header. Serialize your Analyze calls: wait for one to finish before starting the next, and retry after the `Retry-After` interval.

## Errors

Analyze validates each request and returns `400 Bad Request` with a `code` that identifies the rule that failed:

| Code                         | Meaning                                                                |
| :--------------------------- | :--------------------------------------------------------------------- |
| `time_range_too_wide`        | The window spans more than 100 days.                                   |
| `before_historical_floor`    | `startTime` is earlier than `2025-04-09T00:00:00Z`.                    |
| `invalid_time_range`         | `endTime` isn't greater than `startTime`.                              |
| `analyze_input_validation`   | A parameter value is invalid. See the `message` field for details.     |
| `analyze_filter_conflict`    | A dimension was set both as a top-level parameter and inside `filter`. |
| `analyze_unsupported_filter` | The request used a dimension or operator the report doesn't support.   |

A `403 Forbidden` means the token is missing the `sites:read` scope, or the workspace doesn't have the Analyze add-on.

## Walkthrough: Build a traffic view

Imagine you're building a weekly traffic digest for a client. They want to know how desktop visitors from the UK engaged with their site last week. This walkthrough pulls that report step by step, starting broad and narrowing down with filters.

#### Request the traffic report

Call the Traffic report with a window, a `metricScope`, a `bucketTimeZone`, and a `deviceType` shortcut.

```bash
curl --request GET \
  --url 'https://api.webflow.com/v2/sites/{site_id}/analyze/reports/traffic?startTime=2026-04-01T00:00:00Z&endTime=2026-04-08T00:00:00Z&metricScope=session&bucketTimeZone=UTC&deviceType=desktop' \
  --header 'authorization: Bearer YOUR_API_TOKEN' \
  --header 'accept: application/json'
```

#### Read the response

Each `data` point is one bucket. Because this request used `bucketTimeZone=UTC`, the bucket timestamps are UTC midnight. The `bucketing` field echoes the bucket settings, and `filter` confirms how the report was scoped.

```json
{
  "report": "traffic",
  "metricScope": "session",
  "window": {
    "startTime": "2026-04-01T00:00:00Z",
    "endTime": "2026-04-08T00:00:00Z"
  },
  "bucketing": {
    "granularityPeriod": "day",
    "bucketTimeZone": "UTC"
  },
  "data": [
    { "timestamp": "2026-04-01T00:00:00Z", "count": 1234 },
    { "timestamp": "2026-04-02T00:00:00Z", "count": 1180 },
    { "timestamp": "2026-04-03T00:00:00Z", "count": 1310 },
    { "timestamp": "2026-04-04T00:00:00Z", "count": 1095 },
    { "timestamp": "2026-04-05T00:00:00Z", "count": 742 },
    { "timestamp": "2026-04-06T00:00:00Z", "count": 688 },
    { "timestamp": "2026-04-07T00:00:00Z", "count": 1021 }
  ],
  "filter": { "deviceType": { "eq": "desktop" } }
}
```

#### Narrow it further

Add another dimension to focus the view. Here, `country=GB` limits the report to visitors from the United Kingdom. The filter value is the ISO code (`GB`), not the country name.

```bash
curl --request GET \
  --url 'https://api.webflow.com/v2/sites/{site_id}/analyze/reports/traffic?startTime=2026-04-01T00:00:00Z&endTime=2026-04-08T00:00:00Z&metricScope=session&bucketTimeZone=UTC&deviceType=desktop&country=GB' \
  --header 'authorization: Bearer YOUR_API_TOKEN' \
  --header 'accept: application/json'
```

From here, swap in another report to answer a different question: [Top pages](/data/reference/analyze/top-pages) for your most-visited content, or [Top dimensions](/data/reference/analyze/top-dimensions) to rank visitors by country, device, or traffic source.