Stats API
The Stats API provides read-only access to aggregated analytics data for your sites. All endpoints return privacy-respecting, aggregated metrics without exposing individual user data.
Endpoints Overview
The Stats API includes 13 endpoints covering all core analytics dimensions:
- Overview: Aggregate metrics and timeseries
- Content: Pages, entry pages, exit pages
- Sources: Traffic sources and referrers
- Technology: Devices, browsers, operating systems
- Geography: Countries, regions, cities
- Events: Custom events and conversions
- Real-time: Current active visitors
GET /stats/overview
Retrieve aggregate metrics and timeseries data for a specified date range.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)compare(optional): Enable comparison with previous period (true/false)timezone(optional): IANA timezone for date aggregation
Response:
{
"data": {
"metrics": {
"visitors": 12543,
"pageviews": 28941,
"bounce_rate": 42.3,
"visit_duration": 185
},
"timeseries": [
{ "date": "2025-01-01", "visitors": 421, "pageviews": 987 },
{ "date": "2025-01-02", "visitors": 438, "pageviews": 1024 }
]
},
"meta": {
"sampled": false,
"filtered_bot_traffic": 234
}
}
Example (cURL):
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31"
Example (JavaScript):
const response = await fetch(
'https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31',
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
const data = await response.json();
console.log(data.data.metrics);
GET /stats/pages
Retrieve top pages with engagement metrics.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)limit(optional): Number of results (default: 100, max: 1000)page(optional): Page number for pagination (default: 1)
Response:
{
"data": {
"pages": [
{
"pathname": "/pricing",
"pageviews": 4521,
"visitors": 3214,
"bounce_rate": 38.2,
"avg_time_on_page": 145
},
{
"pathname": "/features",
"pageviews": 3987,
"visitors": 2876,
"bounce_rate": 41.5,
"avg_time_on_page": 178
}
],
"pagination": {
"total": 247,
"page": 1,
"limit": 100
}
}
}
Example (cURL):
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.ovyxa.com/api/v1/stats/pages?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31&limit=20"
GET /stats/sources
Retrieve traffic sources classified by type (search, social, direct, referral).
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)
Response:
{
"data": {
"sources": [
{
"source": "Google",
"source_type": "search",
"visitors": 5421,
"pageviews": 12834,
"bounce_rate": 39.8
},
{
"source": "Direct / None",
"source_type": "direct",
"visitors": 3214,
"pageviews": 7891,
"bounce_rate": 45.2
},
{
"source": "twitter.com",
"source_type": "social",
"visitors": 1876,
"pageviews": 4321,
"bounce_rate": 52.3
}
]
}
}
Example (JavaScript):
const response = await fetch(
'https://api.ovyxa.com/api/v1/stats/sources?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31',
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
const { data } = await response.json();
console.log(data.sources);
GET /stats/entry-pages
Retrieve pages where visitors first land on your site.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)
Response:
{
"data": {
"entry_pages": [
{
"pathname": "/",
"entries": 8234,
"entry_rate": 45.2,
"bounce_rate": 38.1
},
{
"pathname": "/blog/privacy-analytics",
"entries": 2156,
"entry_rate": 12.1,
"bounce_rate": 41.7
}
]
}
}
GET /stats/exit-pages
Retrieve pages where visitors exit your site.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)
Response:
{
"data": {
"exit_pages": [
{
"pathname": "/pricing",
"exits": 3421,
"exit_rate": 75.6
},
{
"pathname": "/contact",
"exits": 2987,
"exit_rate": 82.3
}
]
}
}
GET /stats/devices
Retrieve visitor breakdown by device type.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)
Response:
{
"data": {
"devices": [
{
"device": "Desktop",
"visitors": 7834,
"percentage": 62.4
},
{
"device": "Mobile",
"visitors": 3987,
"percentage": 31.8
},
{
"device": "Tablet",
"visitors": 722,
"percentage": 5.8
}
]
}
}
Example (cURL):
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.ovyxa.com/api/v1/stats/devices?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31"
GET /stats/browsers
Retrieve visitor breakdown by browser, optionally filtered by device type.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)device(optional): Filter by device type (Desktop/Mobile/Tablet)
Response:
{
"data": {
"browsers": [
{
"browser": "Chrome",
"visitors": 6543,
"percentage": 52.1
},
{
"browser": "Safari",
"visitors": 3421,
"percentage": 27.3
},
{
"browser": "Firefox",
"visitors": 1654,
"percentage": 13.2
}
]
}
}
Example (JavaScript with filter):
const response = await fetch(
'https://api.ovyxa.com/api/v1/stats/browsers?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31&device=Mobile',
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
GET /stats/operating-systems
Retrieve visitor breakdown by operating system, optionally filtered by device type.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)device(optional): Filter by device type (Desktop/Mobile/Tablet)
Response:
{
"data": {
"operating_systems": [
{
"os": "Windows",
"visitors": 5432,
"percentage": 43.2
},
{
"os": "macOS",
"visitors": 3214,
"percentage": 25.6
},
{
"os": "iOS",
"visitors": 2187,
"percentage": 17.4
},
{
"os": "Android",
"visitors": 1721,
"percentage": 13.8
}
]
}
}
GET /stats/countries
Retrieve visitor breakdown by country.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)
Response:
{
"data": {
"countries": [
{
"country_code": "US",
"country_name": "United States",
"visitors": 4532,
"percentage": 36.1
},
{
"country_code": "GB",
"country_name": "United Kingdom",
"visitors": 2341,
"percentage": 18.7
},
{
"country_code": "FR",
"country_name": "France",
"visitors": 1876,
"percentage": 15.0
}
]
}
}
Example (cURL):
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.ovyxa.com/api/v1/stats/countries?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31"
GET /stats/regions
Retrieve visitor breakdown by region within a country (Phase 2 feature).
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)country(required): ISO country code (e.g., "US")
Response:
{
"data": {
"regions": [
{
"region_code": "CA",
"region_name": "California",
"visitors": 1243,
"percentage": 27.4
},
{
"region_code": "NY",
"region_name": "New York",
"visitors": 876,
"percentage": 19.3
}
]
}
}
GET /stats/cities
Retrieve visitor breakdown by city within a region (Phase 2 feature).
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)region(required): Region code (e.g., "CA")
Response:
{
"data": {
"cities": [
{
"city": "San Francisco",
"visitors": 432,
"percentage": 34.8
},
{
"city": "Los Angeles",
"visitors": 387,
"percentage": 31.1
}
]
}
}
GET /stats/events
Retrieve custom event statistics, optionally filtered by event name.
Parameters:
site_id(required): Site identifierdate_from(required): Start date (YYYY-MM-DD)date_to(required): End date (YYYY-MM-DD)event_name(optional): Filter by specific event name
Response:
{
"data": {
"events": [
{
"event_name": "signup",
"total_count": 342,
"unique_visitors": 298,
"conversion_rate": 2.4
},
{
"event_name": "purchase",
"total_count": 87,
"unique_visitors": 82,
"conversion_rate": 0.7
}
]
}
}
Example (filtered):
const response = await fetch(
'https://api.ovyxa.com/api/v1/stats/events?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31&event_name=signup',
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
GET /stats/realtime
Retrieve current active visitors and their activity (5-minute window).
Parameters:
site_id(required): Site identifier
Response:
{
"data": {
"active_visitors": 23,
"current_pages": [
{
"pathname": "/pricing",
"visitors": 8
},
{
"pathname": "/features",
"visitors": 6
},
{
"pathname": "/",
"visitors": 5
}
],
"current_sources": [
{
"source": "Google",
"visitors": 12
},
{
"source": "Direct / None",
"visitors": 7
}
]
},
"meta": {
"timestamp": "2025-01-15T14:32:18Z"
}
}
Example (cURL):
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://api.ovyxa.com/api/v1/stats/realtime?site_id=xxx"
Example (JavaScript with polling):
// Poll every 30 seconds for real-time updates
setInterval(async () => {
const response = await fetch(
'https://api.ovyxa.com/api/v1/stats/realtime?site_id=xxx',
{ headers: { 'Authorization': 'Bearer YOUR_TOKEN' } }
);
const { data } = await response.json();
updateDashboard(data.active_visitors, data.current_pages);
}, 30000);
Error Handling
All Stats API endpoints return standard HTTP status codes:
200 OK: Request successful400 Bad Request: Invalid parameters401 Unauthorized: Invalid or missing authentication403 Forbidden: Insufficient permissions404 Not Found: Site not found429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error
Error Response Example:
{
"error": {
"code": "invalid_date_range",
"message": "date_from must be before date_to"
}
}
Best Practices
- Cache responses: Stats data doesn't change frequently - cache for 5-10 minutes
- Use appropriate date ranges: Smaller ranges return faster
- Paginate large results: Use
limitandpageparameters - Filter when possible: Use optional filters to reduce response size
- Handle rate limits gracefully: Implement exponential backoff