Get Page Analytics
Retrieve a single analytics breakdown for one page.
One call returns one breakdown, selected with the type parameter. Map the
question to a type: summary for totals and revenue, daily for trends,
sources for referrers, countries, devices, paths for sections within the
page, partners for affiliate performance, or realtime for a live count. To
assemble a dashboard, call this endpoint in parallel with different type
values.
The {id} is the page id returned by Get Pages.
Request
GET /pages/{id}/analytics
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The page id from Get Pages - a short, URL-safe string (not a UUID). A malformed value returns 422. |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | No | summary | Which breakdown to return. One of summary, daily, sources, countries, devices, paths, partners, realtime. |
date | string | No | last7days | Date range. Either a named slug (today, last7days, last14days, last30days, last3months, lastMonth, monthToDate, yearToDate, last12months, all) or a custom range as YYYY-MM-DD,YYYY-MM-DD (inclusive). Same vocabulary as Get a Statistic. Ignored for type=realtime. |
timezone | string | No | store timezone | IANA timezone name (e.g. Europe/Warsaw). Determines how the date range and visitor days are bucketed, and is echoed back in date_range.timezone. Defaults to your store's timezone. |
limit | integer | No | 10 | Maximum rows for the list breakdowns (sources, countries, devices, paths, partners). Range 1-50. An out-of-range value returns 422 (it is not clamped). |
urls_per_source | integer | No | 5 | Maximum referrer URLs per source bucket. Applies to type=sources only. Range 1-15. An out-of-range value returns 422. |
A malformed id, an unknown type, a malformed date, an unknown timezone,
or an out-of-range limit / urls_per_source returns a 422 (see
Validation Error).
Example Request - summary, last 7 days
curl -X GET "https://cart.easy.tools/api/v1/pages/DeIS7b/analytics?type=summary" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request - top 5 sources for a custom range
curl -X GET "https://cart.easy.tools/api/v1/pages/DeIS7b/analytics?type=sources&limit=5&date=2026-06-01,2026-06-30&timezone=Europe/Warsaw" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Example Request - live visitor count
curl -X GET "https://cart.easy.tools/api/v1/pages/DeIS7b/analytics?type=realtime" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Response
Success Response (200)
The body shape is determined by the requested type, and every shape carries a
type field echoing it. All breakdowns except realtime include a date_range
(the resolved window the figures cover). The list breakdowns (daily,
sources, countries, devices, paths, partners) also include a top-level
currency - the primary currency the rows are ordered by, or null when the
page has no revenue.
Reading the numbers
- Percentages are already percentages. Any field whose name ends in
_percent(bounce_rate_percent,conversion_rate_percent) is the percentage value itself -0.13means0.13%. Do not multiply by 100. - Revenue is in major currency units.
amountis450.0, not minor units, andcurrencyis a lowercase ISO code (pln). Report it verbatim. - Per-visitor rates can be null.
conversion_rate_percentandrevenue_per_visitorare precomputed per currency; they arenullwhen there were no visitors, and they are absent ondevicesrows. avg_duration_secondsis in seconds.
Date Range
Present on every breakdown except realtime. It is the server's resolution of
your date slug and timezone into concrete dates.
| Field | Type | Nullable | Description |
|---|---|---|---|
from | string | No | First day of the window (YYYY-MM-DD, inclusive). |
to | string | No | Last day of the window (YYYY-MM-DD, inclusive). |
timezone | string | No | IANA timezone used for the day boundaries. |
Revenue Entry
The objects in every revenue array. One entry per currency.
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | No | Lowercase ISO currency code. |
amount | number | No | Revenue in major currency units (e.g. 450.0). |
orders | integer | No | Number of orders. |
conversion_rate_percent | number | Yes | Orders / visitors, already a percentage (0.24 means 0.24%). null when there were no visitors. Absent on devices rows. |
revenue_per_visitor | number | Yes | Amount / visitors, in this row's currency. null when there were no visitors. Absent on devices rows. |
Summary (type=summary)
Period totals - visitors, pageviews, bounce rate, and revenue per currency.
{
"type": "summary",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"summary": {
"visitors": 1234,
"pageviews": 2210,
"views_per_visit": 1.79,
"avg_duration_seconds": 47,
"bounce_rate_percent": 0.13,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
]
}
}
| Field | Type | Nullable | Description |
|---|---|---|---|
summary.visitors | integer | No | Unique visitors in the period. |
summary.pageviews | integer | No | Total pageviews in the period. |
summary.views_per_visit | number | No | Average pageviews per visit. |
summary.avg_duration_seconds | integer | No | Average visit duration, in seconds. |
summary.bounce_rate_percent | number | No | Bounce rate, already a percentage (0.13 means 0.13%). |
summary.revenue | array | No | Revenue per currency. See Revenue Entry. Empty when there is no revenue. |
Daily (type=daily)
Per-day visitor and revenue trend, one row per day in the window.
{
"type": "daily",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"daily": [
{
"date": "2026-06-03",
"visitors": 42,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
]
},
{
"date": "2026-06-04",
"visitors": 38,
"revenue": []
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
daily[].date | string | No | The day (YYYY-MM-DD). |
daily[].visitors | integer | No | Unique visitors on that day. |
daily[].revenue | array | No | Revenue per currency for that day. See Revenue Entry. |
A range longer than 120 inclusive days returns an empty daily array. Request a
shorter range, or use type=summary.
Sources (type=sources)
Traffic sources, each with a drill-down of its top referrer URLs (capped by
urls_per_source).
{
"type": "sources",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"sources": [
{
"source": "Google",
"visitors": 120,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
],
"urls": [
{
"referrer": "https://google.com/search?q=example",
"visitors": 80,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
],
"truncated": false
}
]
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
sources[].source | string | No | Source label (e.g. Google, Direct). |
sources[].visitors | integer | No | Unique visitors from this source. |
sources[].revenue | array | No | Revenue per currency for this source. See Revenue Entry. |
sources[].urls | array | No | Top referrer URLs within this source. |
urls[].referrer | string | No | The referrer URL. |
urls[].visitors | integer | No | Unique visitors from this referrer. |
urls[].revenue | array | No | Revenue per currency for this referrer. See Revenue Entry. |
urls[].truncated | boolean | Yes | true when the referrer URL was shortened because it exceeded the length cap. |
Countries (type=countries)
Visitors and revenue by country.
{
"type": "countries",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"countries": [
{
"country_code": "PL",
"country_name": "Poland",
"visitors": 540,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
]
},
{
"country_code": null,
"country_name": "Unknown",
"visitors": 5,
"revenue": []
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
countries[].country_code | string | Yes | ISO country code (e.g. PL). null when the visitor's country is unknown. |
countries[].country_name | string | No | English country name (e.g. Poland, Unknown). |
countries[].visitors | integer | No | Unique visitors from this country. |
countries[].revenue | array | No | Revenue per currency for this country. See Revenue Entry. |
Devices (type=devices)
Device-type split. Unlike the other breakdowns, device rows are keyed by
pageviews (not visitors), and percentage is the row's share of total
pageviews. The revenue rows omit the per-visitor rate fields.
{
"type": "devices",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"devices": [
{
"device_type": "mobile",
"pageviews": 1320,
"percentage": 59.7,
"revenue": [
{
"currency": "pln",
"amount": 280,
"orders": 2
}
]
},
{
"device_type": "desktop",
"pageviews": 890,
"percentage": 40.3,
"revenue": []
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
devices[].device_type | string | No | Device type (e.g. mobile, desktop, tablet). |
devices[].pageviews | integer | No | Pageviews from this device type. |
devices[].percentage | number | No | Share of total pageviews (0-100). |
devices[].revenue | array | No | Revenue per currency. Each entry carries only currency, amount, and orders - no per-visitor rates. |
Paths (type=paths)
Paths/sections within the page (for example /, /pricing) - not the
public domain. The / row absorbs homepage and unattributed traffic.
{
"type": "paths",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"paths": [
{
"page_url": "/",
"visitors": 980,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
]
},
{
"page_url": "/pricing",
"visitors": 210,
"revenue": []
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
paths[].page_url | string | No | A path/section on the page (e.g. /, /pricing). |
paths[].visitors | integer | No | Unique visitors on this path. |
paths[].revenue | array | No | Revenue per currency for this path. See Revenue Entry. |
Partners (type=partners)
Affiliate partner performance. Only traffic and orders attributed to a ?ref=
partner are counted, so partner revenue can be less than the page's total
revenue.
{
"type": "partners",
"date_range": {
"from": "2026-06-03",
"to": "2026-06-09",
"timezone": "Europe/Warsaw"
},
"currency": "pln",
"partners": [
{
"partner": "affiliate42",
"visitors": 85,
"revenue": [
{
"currency": "pln",
"amount": 450,
"orders": 3,
"conversion_rate_percent": 0.24,
"revenue_per_visitor": 0.36
}
]
}
]
}
| Field | Type | Nullable | Description |
|---|---|---|---|
currency | string | Yes | Primary currency the rows are ordered by. null when the page has no revenue. |
partners[].partner | string | No | Partner identifier (the ?ref= value). |
partners[].visitors | integer | No | Unique visitors attributed to this partner. |
partners[].revenue | array | No | Revenue per currency for this partner. See Revenue Entry. |
Realtime (type=realtime)
Visitors on the page in the last 5 minutes - a live snapshot. This breakdown has
no date_range, and ignores date and timezone.
{
"type": "realtime",
"visitors": 4
}
| Field | Type | Nullable | Description |
|---|---|---|---|
visitors | integer | No | Visitors on the page in the last 5 minutes. |
Error Responses
Unauthorized (401)
{
"message": "Unauthenticated."
}
Forbidden (403)
Returned when your API key has not been granted access to the requested store.
{
"message": "You do not have API access to the requested store."
}
Not Found (404)
Returned when no page with this id exists in your store.
{
"message": "Page not found"
}
Validation Error (422 Unprocessable Entity)
Returned when id is malformed, type is unknown, date is malformed,
timezone is unknown, or limit / urls_per_source is out of range.
{
"message": "The selected type is invalid.",
"errors": {
"type": [
"The selected type is invalid."
]
}
}
Too Many Requests (429)
Returned when you exceed the rate limit. The Retry-After response header gives
the number of seconds to wait.
{
"message": "Too many requests. Please retry after 60 seconds."
}
Service Unavailable (502)
Returned when the analytics data source is temporarily unavailable. Retry shortly; do not treat it as "no data".
{
"message": "The Easypage service is temporarily unavailable. Please retry."
}