NEWAI content checker: see which pages read like AI text

APIRank tracker

Rank tracker API. Your Google positions in your own dashboard.

Every keyword you track in MarketingTracer, with its position per month, the page that ranks and where your competitors stand. Your dashboard gets it from four endpoints; your AI assistant gets the same four as MCP tools.

Per keyword

Position now, last time, and per month.

Per page

Which of your pages ranks, and where.

Competitors

Their position on every keyword you track.

In your plan

100 keywords per site, no extra fee.

Four endpoints, four MCP tools

Each endpoint is a POST to /rest/v1/<endpoint> on app.marketingtracer.com. Your AI assistant calls the same data through the MCP tool under each endpoint.

Endpoint and MCP toolWhat you get
serp.summary
get_serp_summary
Whether measuring is on, how many of your keywords are in use, the months with data and when we last measured.
serp.keywords
get_serp_keywords
Every tracked keyword: position, previous position, the change, six months of positions, the position per own page and per competitor, and the search volume.
serp.keyword
get_serp_keyword
One keyword up close: the whole top of the latest measurement, and the position per month of every domain in it.
serp.competitors
get_serp_competitors
Your competitors, plus the domains that show up most often in the tops of your keywords.

Every endpoint takes site_id. serp.summary and serp.keywords take month (YYYY-MM) for an earlier month. serp.keywords also takes group, limit (1 to 10,000, default 1,000) and cursor. serp.keyword takes the keyword_id from serp.keywords.

A keyword, as the API returns it

curl -X POST https://app.marketingtracer.com/rest/v1/serp.keywords \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"site_id": "YOUR_SITE_ID", "group": "prio", "limit": 1}'

From a real shop, with its domain and id changed and shortened where you see …:

{
  "data": [{
    "id": "6ae0d00f1a123fbf9d03c6d2",
    "keyword": "auto zonnescherm",
    "country": "nl",
    "device": "desktop",
    "group": "prio",
    "starred": false,
    "search_volume": 5400,
    "last_measured_month": "2026-10",
    "position": 2,
    "previous_position": null,
    "change": null,
    "positions": [
      {"month": "2026-09", "position": null, "measured": false},
      {"month": "2026-10", "position": 2, "measured": true}
    ],
    "pages": [{
      "url": "https://www.example-shop.com/nl/interieur/auto-zonneschermen.html",
      "positions": [{"month": "2026-09", "position": null}, {"month": "2026-10", "position": 2}]
    }],
    "competitors": [{"domain": "…", "positions": […]}],
    …
  }],
  "meta": {"site_id": "YOUR_SITE_ID", "next_cursor": "6ae0d00f1a123fbf9d03c6d2", "total": 12}
}

This shop added the keyword in October, so previous_position and change are still null; after the next measurement they fill in. A position of null with measured: true means you were not in the measured top that month. A keyword is a keyword plus a country plus a device; the same words on mobile are a separate keyword with their own id.

Positions in the report you already send

On the first of the month your report script asks serp.keywords with last month's month and writes the positions into your own template. The app reads the same endpoint, so nobody has to explain why the PDF says 4 and the dashboard says 5.

A warning when a keyword leaves the top 10

MarketingTracer does not send rank alerts; with the API you build exactly the one you want. Run through the list after each measurement and look at change. A keyword that went from 8 to 14 shows up in your own Slack channel or ticket board the next morning, with the page that lost it.

Every endpoint, argument and field

Generated from the same definitions the API itself runs on, and the example answers are tested against them, so this reference is never behind. 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; 429 rate_limited. The machine-readable version is openapi.json.

serp.summary

POST /rest/v1/serp.summary · MCP tool get_serp_summary

Returns the Rank tracker status of one site: whether measuring is on, whether the site is in its trial, how deep each measurement goes, the months with data, how many keywords are in use of the site's quota, and when the latest and the next measurement are. Positions are real Google results per keyword, country and device, separate from Search Console.

Arguments

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
monthstring, YYYY-MMLast month to show, YYYY-MM, for a report of an earlier month. Defaults to this month.

Example request

curl -X POST https://app.marketingtracer.com/rest/v1/serp.summary \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"YOUR_SITE_ID"}'

Example response · A real answer, anonymised and shortened to two items per list.

{
  "data": {
    "measuring_enabled": true,
    "trial": false,
    "own_domain": "example-shop.com",
    "depth": 20,
    "months": ["2026-09", "2026-10"],
    "report_month": null,
    "quota": {"used": 10, "total": 100},
    "last_measured_at": "2026-10-29T23:20:05Z",
    "next_measurement_at": "2026-11-28T23:15:00Z",
    "can_set_plan": true,
    "can_buy": false
  },
  "meta": {"site_id": "YOUR_SITE_ID"}
}

Response fields · in data:

FieldTypeWhat it is
measuring_enabledbooleanWhether the Rank tracker is measuring at all right now (one switch for all sites).
trialbooleanWhether the site is in its free trial. The Rank tracker does not measure during the trial.
own_domainstringThe domain of the site, without www.
depthintegerHow deep each measurement goes: 20 means the top 20. A position below that is null.
monthsarray<string>The months serp.keywords returns, YYYY-MM, oldest first: the six months before this month (or before month), plus that month itself once it has a measurement.
report_monthstring or nullThe month asked for with month; null when month was not given.
quotaobjectKeywords this calendar month.
quota.usedintegerKeywords (keyword, country and device) measured or queued this calendar month, including ones deleted since; deleting a keyword does not give its slot back.
quota.totalintegerKeywords the site's plan allows.
last_measured_atstring or nullWhen the site's newest measurement of any keyword came in, ISO 8601 UTC; null before the first one. Not limited by month.
next_measurement_atstring or nullWhen the next scheduled measurement starts, ISO 8601 UTC; null for a report of an earlier month.
can_set_planbooleanWhether the caller may set a measuring plan for the site (white label admins).
can_buybooleanWhether the caller may buy a bigger plan for the site.

serp.keywords

POST /rest/v1/serp.keywords · MCP tool get_serp_keywords

Returns the tracked keywords of one site, oldest first, one item per keyword, country and device: the site's best position in the latest measured month and in the measured month before, the change, the position per month, the position per month of each own page that ranked and of each followed competitor, plus the monthly search volume. A position is null when the site was not in the measured top, or when nothing was measured that month (measured false).

Arguments

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
monthstring, YYYY-MMLast month of the series, YYYY-MM, for a report of an earlier month. Defaults to this month.
groupstringOnly the keywords in this group.
limitinteger, 1 to 10,000, default 1,000Keywords per call.
cursorstringmeta.next_cursor of the previous call, for the next page.

Example request

curl -X POST https://app.marketingtracer.com/rest/v1/serp.keywords \
  -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": [
    {
      "id": "6ae0d00f1a123fbf9d03c6d2",
      "keyword": "auto zonnescherm",
      "country": "nl",
      "device": "desktop",
      "group": "prio",
      "starred": false,
      "target_url": null,
      "search_volume": 5400,
      "state": "ok",
      "paused": false,
      "last_measured_month": "2026-10",
      "position": 2,
      "previous_position": null,
      "change": null,
      "positions": [
        {"month": "2026-09", "position": null, "measured": false},
        {"month": "2026-10", "position": 2, "measured": true}
      ],
      "pages": [
        {
          "url": "https://www.example-shop.com/sunshades",
          "positions": [{"month": "2026-09", "position": null}, {"month": "2026-10", "position": 2}]
        }
      ],
      "competitors": []
    },
    {
      "id": "6ae0d00f1a123fbf9d03c6d4",
      "keyword": "automatten",
      "country": "nl",
      "device": "desktop",
      "group": "overig",
      "starred": false,
      "target_url": null,
      "search_volume": 4400,
      "state": "ok",
      "paused": false,
      "last_measured_month": "2026-10",
      "position": null,
      "previous_position": null,
      "change": null,
      "positions": [
        {"month": "2026-09", "position": null, "measured": false},
        {"month": "2026-10", "position": null, "measured": true}
      ],
      "pages": [],
      "competitors": []
    }
  ],
  "meta": {"site_id": "YOUR_SITE_ID", "next_cursor": "2", "total": 10}
}

Response fields · data is a list; each item has:

FieldTypeWhat it is
idstringThe keyword id; keyword_id in serp.keyword.
keywordstringThe keyword as tracked.
countrystringTwo-letter country code of the Google that is measured, e.g. nl.
devicestringdesktop or mobile.
groupstring or nullThe group the keyword is in; null without a group.
starredbooleanWhether the keyword has a star.
target_urlstring or nullThe page that should rank for this keyword; null when not set.
search_volumeinteger or nullAverage searches per month in this country; null when not known yet.
statestringnew (waiting for its first measurement), queued, ok or error.
pausedbooleanWhether the keyword falls outside the plan's keyword count and is not measured (starred keywords count first, then the oldest).
last_measured_monthstring or nullThe latest month in the series with a measurement, YYYY-MM; null when no month has one.
positioninteger or nullThe site's best position at the last measurement of last_measured_month; null when not in the measured top or without a measurement.
previous_positioninteger or nullThe site's best position in the measured month before last_measured_month (its last measurement that month); null when not in the top or without such a month.
changeinteger or nullPlaces gained between the last two measured months (positive is up); a month outside the measured top counts as depth + 1. Null with fewer than two measured months.
positionsarrayThe best position of the site per month, oldest first.
positions[].monthstringYYYY-MM.
positions[].positioninteger or nullThe best position that month; null when not in the top or not measured.
positions[].measuredbooleanWhether the keyword was measured that month.
pagesarrayEach own page that ranked for the keyword, with its position per month.
pages[].urlstringThe page.
pages[].positionsarrayPer month, oldest first.
pages[].positions[].monthstringYYYY-MM.
pages[].positions[].positioninteger or nullThe position of this page; null when not in the measured top or not measured that month.
competitorsarrayEach followed competitor (also when it never ranked), with its best position per month.
competitors[].domainstringThe competitor.
competitors[].positionsarrayPer month, oldest first.
competitors[].positions[].monthstringYYYY-MM.
competitors[].positions[].positioninteger or nullThe best position of this domain; null when not in the measured top or not measured that month.

serp.keyword

POST /rest/v1/serp.keyword · MCP tool get_serp_keyword

Returns one tracked keyword up close: the organic top of its latest measurement (every result with its position, domain, URL and whether it is the site's own page), and the position per month of every other domain in that top, of each followed competitor and of each own page.

Arguments

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.
keyword_id (required)stringThe id from serp.keywords.

Example request

curl -X POST https://app.marketingtracer.com/rest/v1/serp.keyword \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"YOUR_SITE_ID","keyword_id":"6ae0d00f1a123fbf9d03c6d2"}'

Example response · A real answer, anonymised and shortened to two items per list.

{
  "data": {
    "id": "6ae0d00f1a123fbf9d03c6d2",
    "keyword": "auto zonnescherm",
    "country": "nl",
    "device": "desktop",
    "measured_at": "2026-10-29T23:06:31Z",
    "months": [{"month": "2026-09", "measured": false}, {"month": "2026-10", "measured": true}],
    "top": [
      {
        "position": 1,
        "domain": "halfords.nl",
        "url": "https://www.halfords.nl/auto/interieur-accessoires/zonnescherm-auto",
        "own": false
      },
      {
        "position": 2,
        "domain": "example-shop.com",
        "url": "https://www.example-shop.com/sunshades",
        "own": true
      }
    ],
    "pages": [
      {
        "url": "https://www.example-shop.com/sunshades",
        "positions": [{"month": "2026-09", "position": null}, {"month": "2026-10", "position": 2}]
      }
    ],
    "domains": [
      {
        "domain": "halfords.nl",
        "positions": [{"month": "2026-09", "position": null}, {"month": "2026-10", "position": 1}]
      }
    ]
  },
  "meta": {"site_id": "YOUR_SITE_ID"}
}

Response fields · in data:

FieldTypeWhat it is
idstringThe keyword id.
keywordstringThe keyword.
countrystringTwo-letter country code.
devicestringdesktop or mobile.
measured_atstring or nullWhen the latest measurement came in, ISO 8601 UTC; null before the first one (top is then empty).
monthsarrayThe six months before this month, plus this month once it has a measurement, oldest first.
months[].monthstringYYYY-MM.
months[].measuredbooleanWhether the keyword was measured that month.
toparrayThe organic results of the latest measurement, best first.
top[].positionintegerThe organic position in Google.
top[].domainstringThe domain, without www.
top[].urlstringThe page.
top[].ownbooleanWhether it is a page of the site itself.
pagesarrayEach own page that ranked, with its position per month.
pages[].urlstringThe page.
pages[].positionsarrayPer month, oldest first.
pages[].positions[].monthstringYYYY-MM.
pages[].positions[].positioninteger or nullThe position of this page; null when not in the measured top or not measured that month.
domainsarrayEach other domain in the latest top, plus each followed competitor, with its best position per month.
domains[].domainstringThe domain.
domains[].positionsarrayPer month, oldest first.
domains[].positions[].monthstringYYYY-MM.
domains[].positions[].positioninteger or nullThe best position of this domain; null when not in the measured top or not measured that month.

serp.competitors

POST /rest/v1/serp.competitors · MCP tool get_serp_competitors

Returns the followed competitors of one site (one list shared by the Rank tracker, Core Web Vitals and AI Insights), and suggestions: the domains that show up most often in the latest tops of the site's tracked keywords.

Arguments

ArgumentTypeWhat it does
site_id (required)stringThe site: its id from list_sites, or the id in the app’s address.

Example request

curl -X POST https://app.marketingtracer.com/rest/v1/serp.competitors \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"site_id":"YOUR_SITE_ID"}'

Example response · A real answer, anonymised and shortened to two items per list.

{
  "data": {
    "competitors": [],
    "suggestions": [{"domain": "bol.com", "keywords": 5}, {"domain": "anwb.nl", "keywords": 5}]
  },
  "meta": {"site_id": "YOUR_SITE_ID"}
}

Response fields · in data:

FieldTypeWhat it is
competitorsarray<string>The followed competitors, at most 6 domains.
suggestionsarrayAt most 6 domains, other than the site and its followed competitors, that are most often in the latest tops of the tracked keywords, most first.
suggestions[].domainstringThe domain.
suggestions[].keywordsintegerFor how many tracked keywords it is in the latest top (once per keyword).
White-label / agency

Rankings for every client. From your own domain.

One key reads the Rank tracker of every client site you can open, so one script fills the reports of all your clients. On a white-label dashboard the API answers on your own domain. The whole dashboard is white label: your domain, logo and colours, and team roles that set which modules each role sees.

ProductThe Rank tracker APIAI visibility API APIThe MarketingTracer API

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.

What is a rank tracker API?

A rank tracker API gives the Google positions of your keywords to your own software. This one gives the keywords you track in MarketingTracer: your position, your pages and your competitors, per month.

Can I look up any keyword on demand?

No. The API returns the keywords you track, with their history. Add a keyword in the app and it gets its first measurement shortly after.

Are these positions from Search Console?

No. They are real Google results, measured per keyword, country and device, and separate from Search Console. The average positions from Search Console are in the Search Console MCP.

Which countries and devices?

34 countries, desktop or mobile, chosen per keyword when you add it. The country and the device stay fixed after that, so every month compares with the one before.

How fresh are the numbers?

As fresh as the Rank tracker in the app: the API always returns the latest measurement. serp.summary tells you when that was.

Does it work during the free trial?

The API works, but the Rank tracker starts measuring when you subscribe, so serp.keywords stays empty during the trial.

Can I get Google's AI Overview for my keywords?

Yes, through aiinsights.ai_overviews in the AI visibility API.

What does it cost?

Nothing extra: the API is part of every plan, with 100 keywords per site and more on request. Prices are on the pricing page.