Skip to main content

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

ParameterTypeRequiredDescription
idstringYesThe page id from Get Pages - a short, URL-safe string (not a UUID). A malformed value returns 422.

Query Parameters

ParameterTypeRequiredDefaultDescription
typestringNosummaryWhich breakdown to return. One of summary, daily, sources, countries, devices, paths, partners, realtime.
datestringNolast7daysDate 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.
timezonestringNostore timezoneIANA 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.
limitintegerNo10Maximum 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_sourceintegerNo5Maximum 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.13 means 0.13%. Do not multiply by 100.
  • Revenue is in major currency units. amount is 450.0, not minor units, and currency is a lowercase ISO code (pln). Report it verbatim.
  • Per-visitor rates can be null. conversion_rate_percent and revenue_per_visitor are precomputed per currency; they are null when there were no visitors, and they are absent on devices rows.
  • avg_duration_seconds is 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.

FieldTypeNullableDescription
fromstringNoFirst day of the window (YYYY-MM-DD, inclusive).
tostringNoLast day of the window (YYYY-MM-DD, inclusive).
timezonestringNoIANA timezone used for the day boundaries.

Revenue Entry

The objects in every revenue array. One entry per currency.

FieldTypeNullableDescription
currencystringNoLowercase ISO currency code.
amountnumberNoRevenue in major currency units (e.g. 450.0).
ordersintegerNoNumber of orders.
conversion_rate_percentnumberYesOrders / visitors, already a percentage (0.24 means 0.24%). null when there were no visitors. Absent on devices rows.
revenue_per_visitornumberYesAmount / 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
}
]
}
}
FieldTypeNullableDescription
summary.visitorsintegerNoUnique visitors in the period.
summary.pageviewsintegerNoTotal pageviews in the period.
summary.views_per_visitnumberNoAverage pageviews per visit.
summary.avg_duration_secondsintegerNoAverage visit duration, in seconds.
summary.bounce_rate_percentnumberNoBounce rate, already a percentage (0.13 means 0.13%).
summary.revenuearrayNoRevenue 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": []
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
daily[].datestringNoThe day (YYYY-MM-DD).
daily[].visitorsintegerNoUnique visitors on that day.
daily[].revenuearrayNoRevenue 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
}
]
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
sources[].sourcestringNoSource label (e.g. Google, Direct).
sources[].visitorsintegerNoUnique visitors from this source.
sources[].revenuearrayNoRevenue per currency for this source. See Revenue Entry.
sources[].urlsarrayNoTop referrer URLs within this source.
urls[].referrerstringNoThe referrer URL.
urls[].visitorsintegerNoUnique visitors from this referrer.
urls[].revenuearrayNoRevenue per currency for this referrer. See Revenue Entry.
urls[].truncatedbooleanYestrue 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": []
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
countries[].country_codestringYesISO country code (e.g. PL). null when the visitor's country is unknown.
countries[].country_namestringNoEnglish country name (e.g. Poland, Unknown).
countries[].visitorsintegerNoUnique visitors from this country.
countries[].revenuearrayNoRevenue 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": []
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
devices[].device_typestringNoDevice type (e.g. mobile, desktop, tablet).
devices[].pageviewsintegerNoPageviews from this device type.
devices[].percentagenumberNoShare of total pageviews (0-100).
devices[].revenuearrayNoRevenue 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": []
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
paths[].page_urlstringNoA path/section on the page (e.g. /, /pricing).
paths[].visitorsintegerNoUnique visitors on this path.
paths[].revenuearrayNoRevenue 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
}
]
}
]
}
FieldTypeNullableDescription
currencystringYesPrimary currency the rows are ordered by. null when the page has no revenue.
partners[].partnerstringNoPartner identifier (the ?ref= value).
partners[].visitorsintegerNoUnique visitors attributed to this partner.
partners[].revenuearrayNoRevenue 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
}
FieldTypeNullableDescription
visitorsintegerNoVisitors 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."
}