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 Error (401)​

{
"message": "Unauthenticated."
}

Forbidden Error (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 Error (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."
]
}
}

Rate Limit Error (429 Too Many Requests)​

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."
}