# get_site_analytics

Source: https://modulify.ai/docs/api/analytics/get-site-analytics

Reads a site's visitor numbers over a fixed period, the six headline metrics plus a visitors series to chart.

- Title: Read visitor analytics
- Scope: `analytics:read`
- Access: Read only
- Endpoint: `POST /v1/get_site_analytics`

The six numbers are `visitors`, `visits`, `pageviews`, `viewsPerVisit`, `bounceRate` and `visitDuration`. `period` defaults to `7d`. `day` is today so far, from midnight UTC, `24h` is the current hour and the 23 before it, `7d`, `30d` and `90d` are the last 7, 30 and 90 days counting today, `12mo` is this month and the 11 before it, and `all` is all time.

The response echoes the `period` and the `interval` of the series, `hour` for `day` and `24h`, `month` for `12mo` and `all`, otherwise `day`. The values sit in `visitorsSeries`, and `seriesLabels` are the UTC start of each bucket as ISO timestamps. The series never runs past the present: when the period reaches now, its last bucket is the one still in progress and `lastBucketPartial` is `true`, so that last value is not final and a low number there is not a drop in traffic.

`published` says whether the site is live right now. A site that was never published answers with zeros, while a site taken offline still returns its history. If the analytics backend cannot answer, the call fails with an error rather than reporting zeros, so a failure never means no traffic.

Each call costs 2 of the 1,200 analytics lookups access tokens share per site per hour, one for the totals and one for the series, as [Rate limits and result size](https://modulify.ai/docs/mcp/tokens-and-scopes#rate-limits-and-result-size) explains. A part already cached costs nothing, and neither does a site that was never published. Over that limit it fails with `Access tokens, through MCP clients or the API, used their 1,200 analytics lookups for this site this hour. Wait and try again!` See [The six metrics](https://modulify.ai/docs/grow/analytics#the-six-metrics).

## Request

Call it with a `POST` to `https://api.modulify.ai/v1/get_site_analytics`, sending the inputs below as a JSON object. The token needs the `analytics:read` scope.

It only reads and changes nothing, so retrying it is safe.

```bash
curl -X POST https://api.modulify.ai/v1/get_site_analytics \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"PROJECT_ID"}'
```

Over MCP, the same method is the [get_site_analytics tool](https://modulify.ai/docs/mcp/analytics/get-site-analytics).

## Inputs

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Yes | The site id. |
| `period` | string | No | The window to report on: `day` (today so far), `24h`, `7d`, `30d`, `90d`, `12mo` or `all`. Defaults to `7d`, and anything outside this list is refused before the call runs. |

## Response

Every call answers with the [JSON envelope](https://modulify.ai/docs/api/requests-and-responses#the-response) of `success`, `message`, `data`, `code` and `version`. `data` holds the result described above, and on a method that returns a total, `count` carries it. The [response headers](https://modulify.ai/docs/api/requests-and-responses#headers-on-every-method-call) carry the call's `X-Request-Id` and what is left of your per-minute budget in `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. [Errors](https://modulify.ai/docs/api/errors) explains every status code a call can answer with.