NEWAI content checker: see which pages read like AI text

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.

EndpointMCP toolWhat it returns
analytics.summaryget_analytics_summarySite 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.channelsget_analytics_channelsSessions, 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.sourcesget_analytics_sourcesThe summary metrics per source and medium (such as google / organic or chatgpt.com / referral), share of sessions and previous-period figures.
analytics.landing_pagesget_analytics_landing_pagesThe summary metrics per entry page path and full URL, share of sessions and previous-period figures.
analytics.pagesget_analytics_pagesPage views, sessions, users, engagement rate and average session duration per viewed page path and URL, plus share of views and previous-period figures.
analytics.audienceget_analytics_audienceThe summary metrics by country, city, device, browser, language or new_vs_returning, with share of sessions and previous-period figures.
analytics.eventsget_analytics_eventsEvent count, key event conversions, users and revenue per GA4 event name, alongside the previous period.
analytics.productsget_analytics_productsE-commerce item revenue, items purchased and items viewed per product name, alongside the previous period.
analytics.referrersget_analytics_referrersExternal 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.

Which mobile landing pages under /rental/ grew in google / organic this month?
get_analytics_landing_pages
source_mediumpath_prefixdevicesessionsconversionsprevious

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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly 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:

FieldTypeWhat it is
comparestringprevious_period or previous_year: what the previous figures are.
sessionsobjectSessions in the period, against the previous period.
sessions.valuenumber or nullThis period; null when it does not apply (no sessions).
sessions.previousnumber or nullThe previous period; null when it does not apply.
sessions.changenumber or nullvalue minus previous.
sessions.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
engaged_sessionsobjectEngaged sessions in the period, against the previous period.
engaged_sessions.valuenumber or nullThis period; null when it does not apply (no sessions).
engaged_sessions.previousnumber or nullThe previous period; null when it does not apply.
engaged_sessions.changenumber or nullvalue minus previous.
engaged_sessions.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
engagement_rate_pctobjectEngagement rate, 0-100, in the period, against the previous period.
engagement_rate_pct.valuenumber or nullThis period; null when it does not apply (no sessions).
engagement_rate_pct.previousnumber or nullThe previous period; null when it does not apply.
engagement_rate_pct.changenumber or nullvalue minus previous, in percentage points.
engagement_rate_pct.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
usersobjectUsers in the period, against the previous period.
users.valuenumber or nullThis period; null when it does not apply (no sessions).
users.previousnumber or nullThe previous period; null when it does not apply.
users.changenumber or nullvalue minus previous.
users.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
new_usersobjectNew users in the period, against the previous period.
new_users.valuenumber or nullThis period; null when it does not apply (no sessions).
new_users.previousnumber or nullThe previous period; null when it does not apply.
new_users.changenumber or nullvalue minus previous.
new_users.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
viewsobjectPage views in the period, against the previous period.
views.valuenumber or nullThis period; null when it does not apply (no sessions).
views.previousnumber or nullThe previous period; null when it does not apply.
views.changenumber or nullvalue minus previous.
views.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
views_per_sessionobjectPage views per session in the period, against the previous period.
views_per_session.valuenumber or nullThis period; null when it does not apply (no sessions).
views_per_session.previousnumber or nullThe previous period; null when it does not apply.
views_per_session.changenumber or nullvalue minus previous.
views_per_session.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
avg_session_duration_secondsobjectAverage session duration in seconds in the period, against the previous period.
avg_session_duration_seconds.valuenumber or nullThis period; null when it does not apply (no sessions).
avg_session_duration_seconds.previousnumber or nullThe previous period; null when it does not apply.
avg_session_duration_seconds.changenumber or nullvalue minus previous.
avg_session_duration_seconds.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
conversionsobjectConversions (key events) in the period, against the previous period.
conversions.valuenumber or nullThis period; null when it does not apply (no sessions).
conversions.previousnumber or nullThe previous period; null when it does not apply.
conversions.changenumber or nullvalue minus previous.
conversions.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
revenue_eurobjectRevenue in the period, against the previous period.
revenue_eur.valuenumber or nullThis period; null when it does not apply (no sessions).
revenue_eur.previousnumber or nullThe previous period; null when it does not apply.
revenue_eur.changenumber or nullvalue minus previous.
revenue_eur.change_pctnumber or nullThe change in percent of previous; null when previous is 0 or null.
dailyarrayPer day of the period, oldest first, next to the matching day of the previous period.
daily[].datestringThe day, YYYY-MM-DD.
daily[].sessionsintegerSessions.
daily[].engaged_sessionsintegerEngaged sessions.
daily[].usersintegerUsers.
daily[].conversionsintegerConversions (key events).
daily[].previous_datestringThe matching day of the previous period, YYYY-MM-DD.
daily[].previous_sessionsintegerSessions on previous_date.
daily[].previous_engaged_sessionsintegerEngaged sessions on previous_date.
daily[].previous_usersintegerUsers on previous_date.
daily[].previous_conversionsintegerConversions 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
channelstringThe channel, as Google Analytics names it.
sessionsintegerSessions.
engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
usersintegerUsers (active users, as Google Analytics counts them).
new_usersintegerUsers who came for the first time.
viewsintegerPage views.
views_per_sessionnumber or nullPage views per session; null without sessions.
avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
conversionsintegerKey events (conversions as set up in Google Analytics).
revenue_eurnumberRevenue, in the currency of the Google Analytics property (usually euro).
share_pctnumber or nullShare of the sessions of the whole list, 0-100.
previousobject or nullThe same figures in the previous period; null when it did not occur then.
previous.sessionsintegerSessions.
previous.engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
previous.engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
previous.usersintegerUsers (active users, as Google Analytics counts them).
previous.new_usersintegerUsers who came for the first time.
previous.viewsintegerPage views.
previous.views_per_sessionnumber or nullPage views per session; null without sessions.
previous.avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
previous.conversionsintegerKey events (conversions as set up in Google Analytics).
previous.revenue_eurnumberRevenue, 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
source_mediumstringSource / medium, as Google Analytics gives it; use it as the source_medium filter.
sourcestringThe source (google, chatgpt.com, (direct)).
mediumstring or nullThe medium (organic, referral, cpc, (none)); null when Google Analytics gives none.
sessionsintegerSessions.
engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
usersintegerUsers (active users, as Google Analytics counts them).
new_usersintegerUsers who came for the first time.
viewsintegerPage views.
views_per_sessionnumber or nullPage views per session; null without sessions.
avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
conversionsintegerKey events (conversions as set up in Google Analytics).
revenue_eurnumberRevenue, in the currency of the Google Analytics property (usually euro).
share_pctnumber or nullShare of the sessions of the whole list, 0-100.
previousobject or nullThe same figures in the previous period; null when it did not occur then.
previous.sessionsintegerSessions.
previous.engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
previous.engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
previous.usersintegerUsers (active users, as Google Analytics counts them).
previous.new_usersintegerUsers who came for the first time.
previous.viewsintegerPage views.
previous.views_per_sessionnumber or nullPage views per session; null without sessions.
previous.avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
previous.conversionsintegerKey events (conversions as set up in Google Analytics).
previous.revenue_eurnumberRevenue, 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
pathstringThe path of the landing page, as Google Analytics gives it; (not set) when unknown.
urlstring or nullThe full address of the page; null for (not set).
sessionsintegerSessions.
engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
usersintegerUsers (active users, as Google Analytics counts them).
new_usersintegerUsers who came for the first time.
viewsintegerPage views.
views_per_sessionnumber or nullPage views per session; null without sessions.
avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
conversionsintegerKey events (conversions as set up in Google Analytics).
revenue_eurnumberRevenue, in the currency of the Google Analytics property (usually euro).
share_pctnumber or nullShare of the sessions of the whole list, 0-100.
previousobject or nullThe same figures in the previous period; null when it did not occur then.
previous.sessionsintegerSessions.
previous.engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
previous.engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
previous.usersintegerUsers (active users, as Google Analytics counts them).
previous.new_usersintegerUsers who came for the first time.
previous.viewsintegerPage views.
previous.views_per_sessionnumber or nullPage views per session; null without sessions.
previous.avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
previous.conversionsintegerKey events (conversions as set up in Google Analytics).
previous.revenue_eurnumberRevenue, 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
pathstringThe path of the page, as Google Analytics gives it.
urlstring or nullThe full address of the page; null for (not set).
viewsintegerPage views.
sessionsintegerSessions in which the page was viewed.
usersintegerUsers who viewed the page.
engagement_rate_pctnumber or nullEngagement rate of those sessions, 0-100; null without sessions.
avg_session_duration_secondsnumber or nullAverage duration of those sessions in seconds; null without sessions.
share_pctnumber or nullShare of the views of the whole list, 0-100.
previousobject or nullThe same figures in the previous period; null when the page had no views then.
previous.viewsintegerPage views.
previous.sessionsintegerSessions in which the page was viewed.
previous.usersintegerUsers who viewed the page.
previous.engagement_rate_pctnumber or nullEngagement rate, 0-100.
previous.avg_session_duration_secondsnumber or nullAverage 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
byone of country, city, device, browser, language, new_vs_returningcountry, city, device (desktop, mobile, tablet), browser, language or new_vs_returning (new, returning). Defaults to country.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
keystringThe country, city, device, browser, language or new / returning, as Google Analytics gives it (English names).
sessionsintegerSessions.
engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
usersintegerUsers (active users, as Google Analytics counts them).
new_usersintegerUsers who came for the first time.
viewsintegerPage views.
views_per_sessionnumber or nullPage views per session; null without sessions.
avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
conversionsintegerKey events (conversions as set up in Google Analytics).
revenue_eurnumberRevenue, in the currency of the Google Analytics property (usually euro).
share_pctnumber or nullShare of the sessions of the whole list, 0-100.
previousobject or nullThe same figures in the previous period; null when it did not occur then.
previous.sessionsintegerSessions.
previous.engaged_sessionsintegerEngaged sessions: longer than 10 seconds, two or more page views, or a conversion.
previous.engagement_rate_pctnumber or nullEngaged sessions as a share of sessions, 0-100; null without sessions.
previous.usersintegerUsers (active users, as Google Analytics counts them).
previous.new_usersintegerUsers who came for the first time.
previous.viewsintegerPage views.
previous.views_per_sessionnumber or nullPage views per session; null without sessions.
previous.avg_session_duration_secondsnumber or nullAverage session duration in seconds; null without sessions.
previous.conversionsintegerKey events (conversions as set up in Google Analytics).
previous.revenue_eurnumberRevenue, 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
eventstringThe event name.
countintegerHow often the event happened.
conversionsintegerHow many of them are key events (0 when the event is not a key event).
usersintegerUsers with the event.
revenue_eurnumberRevenue with the event, in the currency of the property.
previousobject or nullThe same in the previous period; null when the event did not occur then.
previous.countintegerHow often.
previous.conversionsintegerKey events.
previous.usersintegerUsers.
previous.revenue_eurnumberRevenue.

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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
productstringThe product name (item name).
revenue_eurnumberRevenue from the product, in the currency of the property.
purchasedintegerItems bought.
viewedintegerTimes the item was viewed.
previousobject or nullThe same in the previous period; null when the product did not occur then.
previous.revenue_eurnumberRevenue.
previous.purchasedintegerItems bought.
previous.viewedintegerTimes 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

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
fromstring, YYYY-MM-DDFirst day of the period, YYYY-MM-DD; give it together with to.
tostring, YYYY-MM-DDLast day of the period, YYYY-MM-DD (yesterday at the latest); give it together with from. At most 366 days.
daysinteger, 1 to 366, default 28Without from and to: the last this many days up to yesterday. Defaults to 28.
compareone of previous_period, previous_yearWhat 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.
channelstringOnly sessions from this channel, as Google Analytics names it (Organic Search, Direct, Referral, Organic Social, Paid Search, Email, AI Assistant, …).
source_mediumstringOnly sessions from this source / medium, exactly as in analytics.sources (google / organic).
landing_pagestringOnly sessions that started on this page: its path, exactly as in analytics.landing_pages (/blog/post).
path_prefixstringOnly sessions that started on a page whose path begins with this (/blog/).
countrystringOnly sessions from this country, in English as in analytics.audience (Netherlands).
deviceone of desktop, mobile, tablet, smart tvOnly sessions on this kind of device.
limitinteger, 1 to 500, default 100Items per call.
cursorstringmeta.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:

FieldTypeWhat it is
referrer_urlstringThe referring page without query string; only https://domain when the browser passed no more.
referrer_domainstringThe domain of the referring site, without www.
domain_onlybooleanWhether only the domain of the referring page is known.
landing_pagestringThe path of the page the visitor arrived on.
landing_urlstring or nullThe full address of that page; null when unknown.
sessionsintegerSessions.
engaged_sessionsintegerEngaged sessions.
viewsintegerPage views.
previousobject or nullThe same in the previous period; null when it did not occur then.
previous.sessionsintegerSessions.
previous.engaged_sessionsintegerEngaged sessions.
previous.viewsintegerPage views.
White label / agency

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.

API hubSEO API overview MCPGoogle Search Console MCP AI assistant trafficAI visibility API MCPSEO MCP server

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
Start your 14-day trial

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.