APIAnalytics
Google Analytics 4 API. Channels, pages, audience and conversions for your own dashboard.
You connect each site's Google Analytics 4 property in MarketingTracer, and we keep the connection running. With one API key, you pull site totals, daily trends, channels, pages, audience, conversions and referrers for every client site into your own dashboard, report or AI assistant. The REST API and the MCP server are in every plan at no extra cost.
Totals and daily
Site totals with period comparison, plus daily sessions, engaged sessions, users and conversions.
Report breakdowns
Channels, sources, landing pages, viewed pages, audience, events, e-commerce products and external referrers.
Shared filters
Pass channel, source, landing page, folder, country and device across reports to drill down step by step.
In every plan
One personal API key for REST and MCP, with 60 calls a minute across all your sites.
Google Analytics 4 endpoints in REST and the MCP server
Send a POST with a JSON body or a GET with query parameters to /rest/v1/. Your personal API key goes in the header as a Bearer token. Pass the site_id from list_sites or copy it from the site's address in the app.
Every endpoint takes a date range as from and to or as days (default 28). The range ends yesterday because today's Google Analytics 4 figures are incomplete. Set compare to previous_period or previous_year (52 weeks back, so weekdays match). Filter by any combination of channel, source_medium, landing_page, path_prefix, country and device.
| Endpoint | MCP tool | What it returns |
|---|---|---|
analytics.summary | get_analytics_summary | Site totals for sessions, engaged sessions, engagement rate, users, new users, views, views per session, average session duration, conversions and revenue with period comparison, plus a daily series for both windows. |
analytics.channels | get_analytics_channels | Sessions, engagement, users, views, conversions and revenue per GA4 channel group (Organic Search, Direct, Referral, AI Assistant and more), share of sessions and previous-period figures. |
analytics.sources | get_analytics_sources | The summary metrics per source and medium (such as google / organic or chatgpt.com / referral), share of sessions and previous-period figures. |
analytics.landing_pages | get_analytics_landing_pages | The summary metrics per entry page path and full URL, share of sessions and previous-period figures. |
analytics.pages | get_analytics_pages | Page views, sessions, users, engagement rate and average session duration per viewed page path and URL, plus share of views and previous-period figures. |
analytics.audience | get_analytics_audience | The summary metrics by country, city, device, browser, language or new_vs_returning, with share of sessions and previous-period figures. |
analytics.events | get_analytics_events | Event count, key event conversions, users and revenue per GA4 event name, alongside the previous period. |
analytics.products | get_analytics_products | E-commerce item revenue, items purchased and items viewed per product name, alongside the previous period. |
analytics.referrers | get_analytics_referrers | External referring URLs and domains paired with the landing page on your site, sessions, engaged sessions, views, previous-period figures and a domain_only flag. |
In Claude Code or Cursor, the get_analytics_* tools return the same reports. The MCP server also includes the free-form get_analytics tool (MCP only). Use it to request any GA4 dimension and metric, filter paths by regular expression with path_regex, or roll pages up into URL folders with group_by_section.
What a call to analytics.summary returns
Pass site_id and optional period or filter arguments. By default, days is 28 and compare is previous_period.
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.summary \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","days":28}'
{
"data": {
"compare": "previous_period",
"sessions": {"value": 1150, "previous": 1031, "change": 119, "change_pct": 11.5},
"engaged_sessions": {"value": 752, "previous": 703, "change": 49, "change_pct": 7},
"engagement_rate_pct": {"value": 65.4, "previous": 68.2, "change": -2.8, "change_pct": -4.1},
"users": {"value": 727, "previous": 674, "change": 53, "change_pct": 7.9},
"new_users": {"value": 669, "previous": 622, "change": 47, "change_pct": 7.6},
"views": {"value": 2668, "previous": 2379, "change": 289, "change_pct": 12.1},
"views_per_session": {"value": 2.32, "previous": 2.31, "change": 0.01, "change_pct": 0.4},
"avg_session_duration_seconds": {"value": 166.2, "previous": 178.4, "change": -12.2, "change_pct": -6.8},
"conversions": {"value": 291, "previous": 205, "change": 86, "change_pct": 42},
"revenue_eur": {"value": 0, "previous": 0, "change": 0, "change_pct": null},
"daily": [
{
"date": "2026-10-06",
"sessions": 37,
"engaged_sessions": 26,
"users": 33,
"conversions": 6,
"previous_date": "2026-09-08",
"previous_sessions": 40,
"previous_engaged_sessions": 27,
"previous_users": 34,
"previous_conversions": 7
},
{
"date": "2026-10-07",
"sessions": 52,
"engaged_sessions": 32,
"users": 37,
"conversions": 14,
"previous_date": "2026-09-09",
"previous_sessions": 37,
"previous_engaged_sessions": 29,
"previous_users": 33,
"previous_conversions": 12
},
…
]
},
"meta": {
"site_id": "YOUR_SITE_ID",
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Every total carries value, previous, change and change_pct (for engagement_rate_pct, change is in percentage points). Each item in daily pairs a date from the current window with previous_date from the comparison window, so a two-line chart plots straight from the array. When sessions is 0, engagement_rate_pct, views_per_session and avg_session_duration_seconds come back as null. A previous value of 0 also gives change_pct: null, as on revenue_eur above. If Google Analytics 4 is not connected for the site, the call returns HTTP 409 with error code not_connected.
Drill from channels to sources to landing pages with the same filters
A Monday report shows conversions up in Organic Search while mobile engagement dipped. Pass channel: "Organic Search" to analytics.sources to separate google / organic from other search engines. Next, call analytics.landing_pages with source_medium: "google / organic", path_prefix: "/rental/" and device: "mobile".
The session filters (channel, source_medium, landing_page, path_prefix, country and device) work together across analytics.summary and the session breakdowns. Every row includes its previous object (for the preceding window or previous_year on seasonal shops), so your dashboard renders the comparison from one request.
See which external pages and AI assistants send visitors, and where they land
When a client gets mentioned on a forum, a partner blog or in an AI assistant, analytics.referrers pairs each referrer_url and referrer_domain with the landing_page on the client's site, plus sessions, engaged_sessions and views for both periods. Search engines and self-referrals are already filtered out.
Combine it with source_medium: "chatgpt.com / referral" to inspect a single source. Many browsers trim the referrer header to the origin. When that happens, referrer_url holds https://domain and domain_only is true, so your report can tell a domain-level referrer apart from a full article URL.
Put audience, key events and e-commerce product revenue on one client scorecard
Call analytics.audience with by set to country, city, device, browser, language or new_vs_returning. Each breakdown shows who visits the site and how their engagement compares with the previous period.
Next to audience, analytics.events lists every GA4 event name with total count, conversions, users and revenue_eur. For webshops that send item data to GA4, analytics.products adds revenue_eur, purchased and viewed per product.
Endpoints, arguments and field descriptions
Every endpoint is a POST with a JSON body; reading endpoints also take a GET with the same arguments in the query string. Send your API key as Authorization: Bearer YOUR_API_KEY. Every answer is {"data": …, "meta": {…}}: meta.site_id always, meta.next_cursor and meta.total for a list, meta.period where the endpoint covers a period. An error is {"error": {"code", "message"}} with the HTTP status: 400 invalid_argument, unknown_argument or missing_argument; 401 not_authenticated; 403 no_access or tool_off; 404 not_found; 409 not_connected (a connection the endpoint needs, such as Google Analytics 4, is missing); 429 rate_limited; 502 google_error (Google returned an error). The machine-readable version is openapi.json.
analytics.summary
POST /rest/v1/analytics.summary · MCP tool get_analytics_summary
Returns the Google Analytics 4 totals of one site for the period against the previous period: sessions, engaged sessions, engagement rate, users, new users, page views, views per session, average session duration, conversions (key events) and revenue, each as value, previous, change and change in percent; plus per day the sessions, engaged sessions, users and conversions of both periods. The period runs up to yesterday at the latest. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.summary \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","days":28}'
Example response · A real answer, anonymised; daily shortened to two days (a 28-day period has 28).
{
"data": {
"compare": "previous_period",
"sessions": {"value": 1150, "previous": 1031, "change": 119, "change_pct": 11.5},
"engaged_sessions": {"value": 752, "previous": 703, "change": 49, "change_pct": 7},
"engagement_rate_pct": {"value": 65.4, "previous": 68.2, "change": -2.8, "change_pct": -4.1},
"users": {"value": 727, "previous": 674, "change": 53, "change_pct": 7.9},
"new_users": {"value": 669, "previous": 622, "change": 47, "change_pct": 7.6},
"views": {"value": 2668, "previous": 2379, "change": 289, "change_pct": 12.1},
"views_per_session": {"value": 2.32, "previous": 2.31, "change": 0.01, "change_pct": 0.4},
"avg_session_duration_seconds": {"value": 166.2, "previous": 178.4, "change": -12.2, "change_pct": -6.8},
"conversions": {"value": 291, "previous": 205, "change": 86, "change_pct": 42},
"revenue_eur": {"value": 0, "previous": 0, "change": 0, "change_pct": null},
"daily": [
{
"date": "2026-10-06",
"sessions": 37,
"engaged_sessions": 26,
"users": 33,
"conversions": 6,
"previous_date": "2026-09-08",
"previous_sessions": 40,
"previous_engaged_sessions": 27,
"previous_users": 34,
"previous_conversions": 7
},
{
"date": "2026-10-07",
"sessions": 52,
"engaged_sessions": 32,
"users": 37,
"conversions": 14,
"previous_date": "2026-09-09",
"previous_sessions": 37,
"previous_engaged_sessions": 29,
"previous_users": 33,
"previous_conversions": 12
}
]
},
"meta": {
"site_id": "YOUR_SITE_ID",
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · in data:
| Field | Type | What it is |
|---|---|---|
compare | string | previous_period or previous_year: what the previous figures are. |
sessions | object | Sessions in the period, against the previous period. |
sessions.value | number or null | This period; null when it does not apply (no sessions). |
sessions.previous | number or null | The previous period; null when it does not apply. |
sessions.change | number or null | value minus previous. |
sessions.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
engaged_sessions | object | Engaged sessions in the period, against the previous period. |
engaged_sessions.value | number or null | This period; null when it does not apply (no sessions). |
engaged_sessions.previous | number or null | The previous period; null when it does not apply. |
engaged_sessions.change | number or null | value minus previous. |
engaged_sessions.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
engagement_rate_pct | object | Engagement rate, 0-100, in the period, against the previous period. |
engagement_rate_pct.value | number or null | This period; null when it does not apply (no sessions). |
engagement_rate_pct.previous | number or null | The previous period; null when it does not apply. |
engagement_rate_pct.change | number or null | value minus previous, in percentage points. |
engagement_rate_pct.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
users | object | Users in the period, against the previous period. |
users.value | number or null | This period; null when it does not apply (no sessions). |
users.previous | number or null | The previous period; null when it does not apply. |
users.change | number or null | value minus previous. |
users.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
new_users | object | New users in the period, against the previous period. |
new_users.value | number or null | This period; null when it does not apply (no sessions). |
new_users.previous | number or null | The previous period; null when it does not apply. |
new_users.change | number or null | value minus previous. |
new_users.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
views | object | Page views in the period, against the previous period. |
views.value | number or null | This period; null when it does not apply (no sessions). |
views.previous | number or null | The previous period; null when it does not apply. |
views.change | number or null | value minus previous. |
views.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
views_per_session | object | Page views per session in the period, against the previous period. |
views_per_session.value | number or null | This period; null when it does not apply (no sessions). |
views_per_session.previous | number or null | The previous period; null when it does not apply. |
views_per_session.change | number or null | value minus previous. |
views_per_session.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
avg_session_duration_seconds | object | Average session duration in seconds in the period, against the previous period. |
avg_session_duration_seconds.value | number or null | This period; null when it does not apply (no sessions). |
avg_session_duration_seconds.previous | number or null | The previous period; null when it does not apply. |
avg_session_duration_seconds.change | number or null | value minus previous. |
avg_session_duration_seconds.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
conversions | object | Conversions (key events) in the period, against the previous period. |
conversions.value | number or null | This period; null when it does not apply (no sessions). |
conversions.previous | number or null | The previous period; null when it does not apply. |
conversions.change | number or null | value minus previous. |
conversions.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
revenue_eur | object | Revenue in the period, against the previous period. |
revenue_eur.value | number or null | This period; null when it does not apply (no sessions). |
revenue_eur.previous | number or null | The previous period; null when it does not apply. |
revenue_eur.change | number or null | value minus previous. |
revenue_eur.change_pct | number or null | The change in percent of previous; null when previous is 0 or null. |
daily | array | Per day of the period, oldest first, next to the matching day of the previous period. |
daily[].date | string | The day, YYYY-MM-DD. |
daily[].sessions | integer | Sessions. |
daily[].engaged_sessions | integer | Engaged sessions. |
daily[].users | integer | Users. |
daily[].conversions | integer | Conversions (key events). |
daily[].previous_date | string | The matching day of the previous period, YYYY-MM-DD. |
daily[].previous_sessions | integer | Sessions on previous_date. |
daily[].previous_engaged_sessions | integer | Engaged sessions on previous_date. |
daily[].previous_users | integer | Users on previous_date. |
daily[].previous_conversions | integer | Conversions on previous_date. |
analytics.channels
POST /rest/v1/analytics.channels · MCP tool get_analytics_channels
Returns the sessions of one site per channel (Organic Search, Direct, Referral, AI Assistant, …) in the period, most sessions first: all metrics, the share of all sessions and the same figures in the previous period. Always lists every channel; the channel filter does not apply here. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.channels \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"channel": "Organic Search",
"sessions": 742,
"engaged_sessions": 520,
"engagement_rate_pct": 70.1,
"users": 471,
"new_users": 417,
"views": 1534,
"views_per_session": 2.07,
"avg_session_duration_seconds": 183.7,
"conversions": 147,
"revenue_eur": 0,
"share_pct": 64.4,
"previous": {
"sessions": 696,
"engaged_sessions": 500,
"engagement_rate_pct": 71.8,
"users": 466,
"new_users": 421,
"views": 1508,
"views_per_session": 2.17,
"avg_session_duration_seconds": 180.7,
"conversions": 121,
"revenue_eur": 0
}
},
{
"channel": "Direct",
"sessions": 378,
"engaged_sessions": 216,
"engagement_rate_pct": 57.1,
"users": 246,
"new_users": 237,
"views": 1042,
"views_per_session": 2.76,
"avg_session_duration_seconds": 138.5,
"conversions": 140,
"revenue_eur": 0,
"share_pct": 32.8,
"previous": {
"sessions": 316,
"engaged_sessions": 188,
"engagement_rate_pct": 59.5,
"users": 197,
"new_users": 186,
"views": 838,
"views_per_session": 2.65,
"avg_session_duration_seconds": 170.7,
"conversions": 83,
"revenue_eur": 0
}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 7,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
channel | string | The channel, as Google Analytics names it. |
sessions | integer | Sessions. |
engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
users | integer | Users (active users, as Google Analytics counts them). |
new_users | integer | Users who came for the first time. |
views | integer | Page views. |
views_per_session | number or null | Page views per session; null without sessions. |
avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
conversions | integer | Key events (conversions as set up in Google Analytics). |
revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
share_pct | number or null | Share of the sessions of the whole list, 0-100. |
previous | object or null | The same figures in the previous period; null when it did not occur then. |
previous.sessions | integer | Sessions. |
previous.engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
previous.engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
previous.users | integer | Users (active users, as Google Analytics counts them). |
previous.new_users | integer | Users who came for the first time. |
previous.views | integer | Page views. |
previous.views_per_session | number or null | Page views per session; null without sessions. |
previous.avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
previous.conversions | integer | Key events (conversions as set up in Google Analytics). |
previous.revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
analytics.sources
POST /rest/v1/analytics.sources · MCP tool get_analytics_sources
Returns the sessions of one site per source / medium (google / organic, chatgpt.com / referral, (direct) / (none)) in the period, most sessions first: all metrics, the share of the sessions in the list and the same figures in the previous period. Use channel to see the sources of one channel. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.sources \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"source_medium": "google / organic",
"source": "google",
"medium": "organic",
"sessions": 711,
"engaged_sessions": 496,
"engagement_rate_pct": 69.8,
"users": 448,
"new_users": 396,
"views": 1478,
"views_per_session": 2.08,
"avg_session_duration_seconds": 181.3,
"conversions": 145,
"revenue_eur": 0,
"share_pct": 61.7,
"previous": {
"sessions": 665,
"engaged_sessions": 479,
"engagement_rate_pct": 72,
"users": 443,
"new_users": 399,
"views": 1424,
"views_per_session": 2.14,
"avg_session_duration_seconds": 180.2,
"conversions": 111,
"revenue_eur": 0
}
},
{
"source_medium": "(direct) / (none)",
"source": "(direct)",
"medium": "(none)",
"sessions": 378,
"engaged_sessions": 216,
"engagement_rate_pct": 57.1,
"users": 246,
"new_users": 237,
"views": 1042,
"views_per_session": 2.76,
"avg_session_duration_seconds": 138.5,
"conversions": 140,
"revenue_eur": 0,
"share_pct": 32.8,
"previous": {
"sessions": 316,
"engaged_sessions": 188,
"engagement_rate_pct": 59.5,
"users": 197,
"new_users": 186,
"views": 838,
"views_per_session": 2.65,
"avg_session_duration_seconds": 170.7,
"conversions": 83,
"revenue_eur": 0
}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 16,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
source_medium | string | Source / medium, as Google Analytics gives it; use it as the source_medium filter. |
source | string | The source (google, chatgpt.com, (direct)). |
medium | string or null | The medium (organic, referral, cpc, (none)); null when Google Analytics gives none. |
sessions | integer | Sessions. |
engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
users | integer | Users (active users, as Google Analytics counts them). |
new_users | integer | Users who came for the first time. |
views | integer | Page views. |
views_per_session | number or null | Page views per session; null without sessions. |
avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
conversions | integer | Key events (conversions as set up in Google Analytics). |
revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
share_pct | number or null | Share of the sessions of the whole list, 0-100. |
previous | object or null | The same figures in the previous period; null when it did not occur then. |
previous.sessions | integer | Sessions. |
previous.engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
previous.engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
previous.users | integer | Users (active users, as Google Analytics counts them). |
previous.new_users | integer | Users who came for the first time. |
previous.views | integer | Page views. |
previous.views_per_session | number or null | Page views per session; null without sessions. |
previous.avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
previous.conversions | integer | Key events (conversions as set up in Google Analytics). |
previous.revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
analytics.landing_pages
POST /rest/v1/analytics.landing_pages · MCP tool get_analytics_landing_pages
Returns the sessions of one site per landing page (the first page of a session) in the period, most sessions first: all metrics, the share of the sessions in the list and the same figures in the previous period. Combine with channel or source_medium to see where a channel lands. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.landing_pages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"path": "/rental/tens-device",
"url": "https://www.example-shop.com/rental/tens-device",
"sessions": 414,
"engaged_sessions": 307,
"engagement_rate_pct": 74.2,
"users": 357,
"new_users": 328,
"views": 997,
"views_per_session": 2.41,
"avg_session_duration_seconds": 230.7,
"conversions": 75,
"revenue_eur": 0,
"share_pct": 35.9,
"previous": {
"sessions": 464,
"engaged_sessions": 322,
"engagement_rate_pct": 69.4,
"users": 394,
"new_users": 372,
"views": 1011,
"views_per_session": 2.18,
"avg_session_duration_seconds": 206.2,
"conversions": 68,
"revenue_eur": 0
}
},
{
"path": "/",
"url": "https://www.example-shop.com/",
"sessions": 193,
"engaged_sessions": 105,
"engagement_rate_pct": 54.4,
"users": 152,
"new_users": 110,
"views": 495,
"views_per_session": 2.56,
"avg_session_duration_seconds": 156.4,
"conversions": 12,
"revenue_eur": 0,
"share_pct": 16.8,
"previous": {
"sessions": 150,
"engaged_sessions": 97,
"engagement_rate_pct": 64.7,
"users": 125,
"new_users": 87,
"views": 394,
"views_per_session": 2.63,
"avg_session_duration_seconds": 153.2,
"conversions": 8,
"revenue_eur": 0
}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 172,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
path | string | The path of the landing page, as Google Analytics gives it; (not set) when unknown. |
url | string or null | The full address of the page; null for (not set). |
sessions | integer | Sessions. |
engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
users | integer | Users (active users, as Google Analytics counts them). |
new_users | integer | Users who came for the first time. |
views | integer | Page views. |
views_per_session | number or null | Page views per session; null without sessions. |
avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
conversions | integer | Key events (conversions as set up in Google Analytics). |
revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
share_pct | number or null | Share of the sessions of the whole list, 0-100. |
previous | object or null | The same figures in the previous period; null when it did not occur then. |
previous.sessions | integer | Sessions. |
previous.engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
previous.engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
previous.users | integer | Users (active users, as Google Analytics counts them). |
previous.new_users | integer | Users who came for the first time. |
previous.views | integer | Page views. |
previous.views_per_session | number or null | Page views per session; null without sessions. |
previous.avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
previous.conversions | integer | Key events (conversions as set up in Google Analytics). |
previous.revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
analytics.pages
POST /rest/v1/analytics.pages · MCP tool get_analytics_pages
Returns the page views of one site per page (every viewed page, not only landing pages) in the period, most views first: views, the sessions and users that viewed the page, engagement and duration of those sessions, the share of all views and the same figures in the previous period. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.pages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"path": "/rental/tens-device",
"url": "https://www.example-shop.com/rental/tens-device",
"views": 597,
"sessions": 486,
"users": 396,
"engagement_rate_pct": 76.3,
"avg_session_duration_seconds": 139.4,
"share_pct": 22.4,
"previous": {
"views": 632,
"sessions": 528,
"users": 431,
"engagement_rate_pct": 71.2,
"avg_session_duration_seconds": 131
}
},
{
"path": "/cart/list",
"url": "https://www.example-shop.com/cart/list",
"views": 391,
"sessions": 78,
"users": 4,
"engagement_rate_pct": 80.8,
"avg_session_duration_seconds": 227.7,
"share_pct": 14.7,
"previous": {
"views": 372,
"sessions": 74,
"users": 3,
"engagement_rate_pct": 89.2,
"avg_session_duration_seconds": 277.5
}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 250,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
path | string | The path of the page, as Google Analytics gives it. |
url | string or null | The full address of the page; null for (not set). |
views | integer | Page views. |
sessions | integer | Sessions in which the page was viewed. |
users | integer | Users who viewed the page. |
engagement_rate_pct | number or null | Engagement rate of those sessions, 0-100; null without sessions. |
avg_session_duration_seconds | number or null | Average duration of those sessions in seconds; null without sessions. |
share_pct | number or null | Share of the views of the whole list, 0-100. |
previous | object or null | The same figures in the previous period; null when the page had no views then. |
previous.views | integer | Page views. |
previous.sessions | integer | Sessions in which the page was viewed. |
previous.users | integer | Users who viewed the page. |
previous.engagement_rate_pct | number or null | Engagement rate, 0-100. |
previous.avg_session_duration_seconds | number or null | Average session duration in seconds. |
analytics.audience
POST /rest/v1/analytics.audience · MCP tool get_analytics_audience
Returns the sessions of one site per country, city, device, browser, language or new versus returning (by) in the period, most sessions first: all metrics, the share of the sessions in the list and the same figures in the previous period. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
by | one of country, city, device, browser, language, new_vs_returning | country, city, device (desktop, mobile, tablet), browser, language or new_vs_returning (new, returning). Defaults to country. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.audience \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","by":"country","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"key": "Netherlands",
"sessions": 1023,
"engaged_sessions": 716,
"engagement_rate_pct": 70,
"users": 610,
"new_users": 552,
"views": 2488,
"views_per_session": 2.43,
"avg_session_duration_seconds": 182.9,
"conversions": 278,
"revenue_eur": 0,
"share_pct": 88.9,
"previous": {
"sessions": 964,
"engaged_sessions": 664,
"engagement_rate_pct": 68.9,
"users": 610,
"new_users": 558,
"views": 2268,
"views_per_session": 2.35,
"avg_session_duration_seconds": 188.8,
"conversions": 197,
"revenue_eur": 0
}
},
{
"key": "United States",
"sessions": 73,
"engaged_sessions": 15,
"engagement_rate_pct": 20.5,
"users": 73,
"new_users": 72,
"views": 109,
"views_per_session": 1.49,
"avg_session_duration_seconds": 7.2,
"conversions": 8,
"revenue_eur": 0,
"share_pct": 6.3,
"previous": {
"sessions": 23,
"engaged_sessions": 18,
"engagement_rate_pct": 78.3,
"users": 23,
"new_users": 23,
"views": 59,
"views_per_session": 2.57,
"avg_session_duration_seconds": 16.6,
"conversions": 8,
"revenue_eur": 0
}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 23,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
key | string | The country, city, device, browser, language or new / returning, as Google Analytics gives it (English names). |
sessions | integer | Sessions. |
engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
users | integer | Users (active users, as Google Analytics counts them). |
new_users | integer | Users who came for the first time. |
views | integer | Page views. |
views_per_session | number or null | Page views per session; null without sessions. |
avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
conversions | integer | Key events (conversions as set up in Google Analytics). |
revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
share_pct | number or null | Share of the sessions of the whole list, 0-100. |
previous | object or null | The same figures in the previous period; null when it did not occur then. |
previous.sessions | integer | Sessions. |
previous.engaged_sessions | integer | Engaged sessions: longer than 10 seconds, two or more page views, or a conversion. |
previous.engagement_rate_pct | number or null | Engaged sessions as a share of sessions, 0-100; null without sessions. |
previous.users | integer | Users (active users, as Google Analytics counts them). |
previous.new_users | integer | Users who came for the first time. |
previous.views | integer | Page views. |
previous.views_per_session | number or null | Page views per session; null without sessions. |
previous.avg_session_duration_seconds | number or null | Average session duration in seconds; null without sessions. |
previous.conversions | integer | Key events (conversions as set up in Google Analytics). |
previous.revenue_eur | number | Revenue, in the currency of the Google Analytics property (usually euro). |
analytics.events
POST /rest/v1/analytics.events · MCP tool get_analytics_events
Returns the events of one site per event name (page_view, scroll, purchase, form_submit, …) in the period, most first: how often, how many of them count as conversions (key events), the users and the revenue, and the same in the previous period. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.events \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"event": "page_view",
"count": 2668,
"conversions": 0,
"users": 725,
"revenue_eur": 0,
"previous": {"count": 2379, "conversions": 0, "users": 672, "revenue_eur": 0}
},
{
"event": "user_engagement",
"count": 1991,
"conversions": 0,
"users": 509,
"revenue_eur": 0,
"previous": {"count": 1802, "conversions": 0, "users": 481, "revenue_eur": 0}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 10,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
event | string | The event name. |
count | integer | How often the event happened. |
conversions | integer | How many of them are key events (0 when the event is not a key event). |
users | integer | Users with the event. |
revenue_eur | number | Revenue with the event, in the currency of the property. |
previous | object or null | The same in the previous period; null when the event did not occur then. |
previous.count | integer | How often. |
previous.conversions | integer | Key events. |
previous.users | integer | Users. |
previous.revenue_eur | number | Revenue. |
analytics.products
POST /rest/v1/analytics.products · MCP tool get_analytics_products
Returns the e-commerce products of one site in the period, most revenue first: revenue, items bought and items viewed, and the same in the previous period. Empty when the site sends no e-commerce data to Google Analytics. The filters do not apply here (product data has no sessions). Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.products \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · Illustrative: the account behind the other examples sends no e-commerce data, so these products are made up in the exact shape of the answer.
{
"data": [
{
"product": "TENS device, 4 weeks",
"revenue_eur": 1188,
"purchased": 33,
"viewed": 412,
"previous": {"revenue_eur": 972, "purchased": 27, "viewed": 380}
},
{
"product": "Electrode pads (4 pack)",
"revenue_eur": 89.7,
"purchased": 10,
"viewed": 61,
"previous": null
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 14,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
product | string | The product name (item name). |
revenue_eur | number | Revenue from the product, in the currency of the property. |
purchased | integer | Items bought. |
viewed | integer | Times the item was viewed. |
previous | object or null | The same in the previous period; null when the product did not occur then. |
previous.revenue_eur | number | Revenue. |
previous.purchased | integer | Items bought. |
previous.viewed | integer | Times viewed. |
analytics.referrers
POST /rest/v1/analytics.referrers · MCP tool get_analytics_referrers
Returns the pages on other sites that sent visitors to one site in the period, per referring page and landing page, most sessions first: sessions, engaged sessions and page views, and the same in the previous period. Search engines and the site itself are left out. Browsers often pass only the domain of the referring site, not the page; then referrer_url is the domain and domain_only is true. Combine with source_medium (chatgpt.com / referral) for one source. The filters narrow everything down (all at once); meta.period gives the period and the previous period. Fails with 409 not_connected when Google Analytics 4 is not connected for the site.
Arguments
| Argument | Type | What it does |
|---|---|---|
site_id (required) | string | The site: its id from list_sites, or the id in the app’s address. |
from | string, YYYY-MM-DD | First day of the period, YYYY-MM-DD; give it together with to. |
to | string, YYYY-MM-DD | Last day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days. |
days | integer, 1 to 366, default 28 | Without from and to: the last this many days up to yesterday. Defaults to 28. |
compare | one of previous_period, previous_year | What the previous figures are: previous_period (the same number of days just before) or previous_year (the same days 52 weeks earlier, same weekdays; for periods up to 364 days). Defaults to previous_period. |
channel | string | Only sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …). |
source_medium | string | Only sessions from this source / medium, exactly as in analytics.sources (google / organic). |
landing_page | string | Only sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post). |
path_prefix | string | Only sessions that started on a page whose path begins with this (/blog/). |
country | string | Only sessions from this country, in English as in analytics.audience (Netherlands). |
device | one of desktop, mobile, tablet, smart tv | Only sessions on this kind of device. |
limit | integer, 1 to 500, default 100 | Items per call. |
cursor | string | meta.next_cursor of the previous call, for the next page. |
Example request
curl -X POST https://app.marketingtracer.com/rest/v1/analytics.referrers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site_id":"YOUR_SITE_ID","limit":2}'
Example response · A real answer, anonymised and shortened to two items per list.
{
"data": [
{
"referrer_url": "https://www.example-forum.com",
"referrer_domain": "example-forum.com",
"domain_only": true,
"landing_page": "/rental/tens-device",
"landing_url": "https://www.example-shop.com/rental/tens-device",
"sessions": 7,
"engaged_sessions": 2,
"views": 8,
"previous": {"sessions": 0, "engaged_sessions": 0, "views": 0}
},
{
"referrer_url": "https://l.wl.co",
"referrer_domain": "l.wl.co",
"domain_only": true,
"landing_page": "/rental/tens-device",
"landing_url": "https://www.example-shop.com/rental/tens-device",
"sessions": 3,
"engaged_sessions": 1,
"views": 4,
"previous": {"sessions": 0, "engaged_sessions": 0, "views": 0}
}
],
"meta": {
"site_id": "YOUR_SITE_ID",
"next_cursor": "2",
"total": 5,
"period": {
"from": "2026-10-06",
"to": "2026-11-02",
"compare_from": "2026-09-08",
"compare_to": "2026-10-05"
}
}
}
Response fields · data is a list; each item has:
| Field | Type | What it is |
|---|---|---|
referrer_url | string | The referring page without query string; only https://domain when the browser passed no more. |
referrer_domain | string | The domain of the referring site, without www. |
domain_only | boolean | Whether only the domain of the referring page is known. |
landing_page | string | The path of the page the visitor arrived on. |
landing_url | string or null | The full address of that page; null when unknown. |
sessions | integer | Sessions. |
engaged_sessions | integer | Engaged sessions. |
views | integer | Page views. |
previous | object or null | The same in the previous period; null when it did not occur then. |
previous.sessions | integer | Sessions. |
previous.engaged_sessions | integer | Engaged sessions. |
previous.views | integer | Page views. |
White-label Google Analytics 4 API. On your own domain, under your name.
When your white-label dashboard runs on your own domain, the REST API and the MCP server answer at that address too. One personal API key works across every client site you can access. You decide whether your clients also get the API and the MCP.
Free 14-day trial
MarketingTracer smart A.I. tool shows you what you need to rank. Then we'll help you get it done.
- No credit card required
- No installation needed
- No strings attached
FAQ
Something else? Ask us.
Is the Google Analytics 4 API included in every plan?
Yes. The Google Analytics 4 endpoints and MCP tools are included in every plan at no extra cost. One personal API key from the MCP page in the app works for both the REST API and the MCP server across all your sites. See the pricing page for plan details.
Which date ranges and comparisons can I request?
Pass from and to (YYYY-MM-DD) together, or set days (default 28) for a rolling window ending yesterday. Today is excluded because today's Google Analytics 4 data is not complete. Set compare to previous_period for the preceding window of equal length, or previous_year for the same days 52 weeks earlier so weekdays match.
How do the shared filters work across endpoints?
Pass any combination of channel, source_medium, landing_page, path_prefix, country and device on analytics.summary and the session-based lists. All filters you pass apply together. Two endpoints work differently: analytics.channels always lists every channel and ignores channel, and analytics.products takes no session filters because GA4 product rows are item-scoped.
How do I connect Claude Code or Cursor to the Google Analytics 4 MCP tools?
Point your editor at /rest/mcp/server on app.marketingtracer.com or on your own white-label domain. Pass your personal API key from the MCP page in the app as a Bearer token. Ready-to-paste setup commands for Claude Code and Cursor are on the SEO MCP page.
What is the rate limit, and can guest users read analytics data?
You get 60 calls per minute per key across the REST API and the MCP server together. Every endpoint and MCP tool is read-only, and users with guest access on a site can read the Google Analytics 4 endpoints too.
What happens when Google Analytics 4 is not connected, or when a row has zero sessions?
If Google Analytics 4 is not connected for a site, the endpoint returns HTTP 409 with error code not_connected. When a period or row has 0 sessions, ratios and averages (engagement_rate_pct, views_per_session and avg_session_duration_seconds) return null. On breakdown rows, previous is also null if that row did not appear in the comparison window.
Why is domain_only true on some rows in analytics.referrers?
Many browsers strip the full path from the referrer header on cross-site links and send only the origin. When Google Analytics 4 receives only the domain, referrer_url is https://domain and domain_only is true. If the browser passed the full page address, domain_only is false.