The dashboard is at /dashboard/sites/{siteId}/analytics. It has four tabs: Overview, Crawlers, Pages, and Alerts.
Query parameters
All dashboard data comes from GET /api/v1/analytics/{siteId}/dashboard. Supported query parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| from | ISO date | 30 days ago | Start of period |
| to | ISO date | today | End of period |
| granularity | day | week | day | Timeseries bucket size |
| bots | string[] | all verified | Filter to specific bot slugs |
| path | string | — | Filter to paths matching this pattern |
| score | critical | warning | good | unscanned | all | all | Filter pages by crawlability score |
| tab | overview | crawlers | pages | alerts | overview | Active tab (affects pagination) |
| page | integer | 1 | Page number for the Pages tab |
| per_page | integer | 25 | Rows per page |
Response shape
{
"siteId": "uuid",
"domain": "example.com",
"period": {
"from": "2026-04-18",
"to": "2026-05-18",
"days": 30,
"granularity": "day"
},
"metrics": { ... },
"timeseries": [ ... ],
"botBreakdown": [ ... ],
"topPages": [ ... ],
"alerts": [ ... ],
"pagination": { ... },
"dataLastUpdatedAt": "2026-05-18T12:00:00Z"
}
The response is edge-cached for 60 seconds (s-maxage=60, stale-while-revalidate=300).
Metrics panel
The metrics object shows four headline numbers, each with a trend vs. the equal-length prior period:
{
"totalVisits": 1240,
"totalVisitsPrev": 980,
"totalVisitsTrend": 26,
"uniquePages": 34,
"uniquePagesPrev": 29,
"uniquePagesTrend": 17,
"activeBots": 5,
"activeBotsPrev": 4,
"activeBotsTrend": 25,
"avgVisitsPerDay": 41,
"avgVisitsPerDayPrev": 33,
"avgVisitsPerDayTrend": 24
}
- totalVisits — total crawler visits in the selected period
- uniquePages — distinct paths crawled
- activeBots — distinct bot names seen
- avgVisitsPerDay —
totalVisits / days
Trend values are percentages; positive means more activity than the prior period.
Timeseries chart
The timeseries array has one entry per day (or week when granularity=week). Missing days are filled in with zero values so the chart is contiguous.
[
{
"date": "2026-05-17",
"total": 84,
"byCategory": {
"ai-training": 42,
"ai-search": 31,
"seo": 8,
"unknown": 3
},
"byBot": {
"GPTBot": 38,
"ClaudeBot": 28
}
}
]
Bot breakdown (Crawlers tab)
Each entry in botBreakdown represents one crawler:
{
"bot": "GPTBot",
"slug": "gptbot",
"category": "ai-training",
"color": "#10b981",
"verified": true,
"visits": 412,
"share": 33.2,
"trend": 18,
"sparkline": [12, 15, 9, 14, 18, ...],
"topPath": "/blog/ai-readiness",
"lastSeen": "2026-05-18",
"isNew": false
}
- share — percentage of total visits in the period
- trend — percentage change vs. prior period;
nullif the bot had zero visits previously - sparkline — up to 30 daily visit counts, oldest first
- isNew —
trueif the bot had zero visits in the prior period
Top pages
Up to 5 entries on the Overview tab; full paginated list on the Pages tab. Each entry:
{
"path": "/blog/ai-readiness",
"visits": 210,
"topCrawler": "GPTBot",
"topCrawlerColor": "#10b981",
"trend": 12,
"sparkline": [8, 11, 7, ...],
"crawlabilityScore": 74
}
- crawlabilityScore — the most recent crawlability score for this path, or
nullif the path has never been scanned - topCrawler — bot with the most visits to this path in the period
Score filter
The score query parameter filters the Pages tab by crawlability score segment:
| Value | Score range |
|-------|------------|
| critical | < 40 |
| warning | 40–69 |
| good | ≥ 70 |
| unscanned | no score recorded |
| all | no filter |