LSD
APIEndpoint 25 of 41AI Optimization / Tracking / Sampling

AI Rank Tracker API

One AI answer is a sample, not a fact.

A model composes its answer per request. Ask ChatGPT the same local question twice ten minutes apart and the businesses change, and so does their order. That makes “am I showing up in AI?” unanswerable from a single call — the honest answer is a rate. This endpoint asks the same prompt 2-25 times and reports how often each business was named, how often the answer actually recommended it, and where in the argument it landed. Priced per run: 4 credits on ChatGPT and Gemini, 2 on Google AI Mode.

POST /v1/ai/sample · 4 credits / run (async)

POST /v1/ai/sample10 samples · 40 credits
AI answer · sampled"best plumber in Orchard Park NY"

Based on Google reviews and local rankings, the highest-rated plumbers in Austin include ABC Plumbing (4.8 / 542 reviews), Roto-Rooter, and Mr. Rooter. Same-day service is offered by several providers.

Cited sources

ABC Plumbing — Austin, TXabcplumbing.com
Top 10 Plumbers in Austinyelp.com
Austin's Best-Rated Plumbershomeadvisor.com
▌ Ask your agent

These prompts turn a yes/no into a number you can report.

Connect Local SEO Data as an MCP server once (60 seconds, below). Then your agent measures AI recommendation rates on demand. Replace bracketed values with your own.

Baseline a client

Sample Gemini 10 times for [best plumber in Orchard Park NY]. Tell me what share of answers recommended [client name], their average position in the shortlist, and which domains the answers cited for them.

Competitive share

Sample ChatGPT 10 times for [keyword]. Rank every business by shortlist_rate and show me where [client] sits against the top three. Flag any competitor above 0.7.

Did the work move anything

Re-run last month's sample for [keyword] with the same prompt and sample count. Compare shortlist_rate against the stored run and tell me whether the change is larger than the sampling noise.

Find the authority gap

Sample Gemini 10 times for [keyword]. For [client], show cited_domains. If the answers are sourcing them from a directory rather than their own site, tell me which pages to fix.

Real response

What you get back

Real response from an 8-sample Gemini run for 'best snow removal company in Orchard Park NY'. shortlist_rate is the share of answers that recommended the business; cited_domains is which source each answer reached for. Trimmed to two businesses and one run.

response · application/json8 samples · 32 credits
{
  "status": "success",
  "credits_used": 0,
  "data": {
    "job_id": "sample_gDz_VTfDxF",
    "status": "complete",
    "keyword": "best snow removal company in Orchard Park NY",
    "platform": "gemini",
    "samples_requested": 8,
    "samples_returned": 8,
    "samples_refused": 0,
    "samples_shortlist_read": 8,
    "credits_charged": 32,
    "reader_version": 5,
    "businesses": [
      {
        "name": "Modern Landscape & Maintenance",
        "matched_on": "name",
        "domain": "modernlandscapeandmaintenance.com",
        "appearances": 4,
        "appearance_rate": 0.5,
        "shortlist_appearances": 4,
        "shortlist_rate": 0.5,
        "mean_shortlist_rank": 1.25,
        "best_shortlist_rank": 1,
        "cited_domains": [
          { "domain": "maps.google.com", "runs": 3 },
          { "domain": "modernlandscapeandmaintenance.com", "runs": 1 }
        ],
        "runs_seen": [1, 2, 3, 8]
      },
      {
        "name": "WNY Snow Removal LLC",
        "matched_on": "name",
        "domain": "wnysnowremoval.com",
        "name_variants": ["WNY Snow Removal", "WNY Snow Removal LLC"],
        "appearances": 4,
        "appearance_rate": 0.5,
        "shortlist_appearances": 4,
        "shortlist_rate": 0.5,
        "mean_shortlist_rank": 2,
        "best_shortlist_rank": 1,
        "cited_domains": [
          { "domain": "bbb.org", "runs": 2 },
          { "domain": "wnysnowremoval.com", "runs": 2 }
        ],
        "runs_seen": [2, 4, 5, 6]
      }
    ],
    "runs": [
      {
        "run": 4,
        "ok": true,
        "outcome": "answered",
        "shortlist_read": true,
        "businesses": [],
        "recommended_businesses": [
          {
            "shortlist_rank": 1,
            "listed": true,
            "name": "WNY Snow Removal",
            "mention": "WNY Snow Removal: Headquartered locally in Orchard Park, this family-owned company handles everything from routine residential driveways to large commercial lots.",
            "is_top_pick": false,
            "citation": { "url": "https://wnysnowremoval.com/", "domain": "wnysnowremoval.com" }
          }
        ],
        "response_text": "Several reputable local companies provide reliable residential and commercial snow plowing..."
      }
    ]
  }
}
Returns

A rate, not an anecdote

Recommendation rate

How often the answer actually recommends them

shortlist_rate is the share of answered runs whose prose put the business on its shortlist. This is the number a client is asking for when they ask whether AI recommends them. appearance_rate sits alongside it and counts every run that named them at all, recommendation or passing mention — the two say different things, and which one is low is the actionable part.

Position, not just presence

Where in the argument they land

mean_shortlist_rank and best_shortlist_rank average only the runs that listed the business, so being named third in 3 of 10 answers reads as rank 3 at a rate of 0.3 rather than being flattened into one misleading score. Every entry also carries the answer's own sentence in mention, so a report can quote what the AI actually said.

Citation provenance

Which source the model reached for

cited_domains lists the domains the answers cited for each business, most-used first, with a run count. A model sourcing a client from their BBB listing rather than their own site is telling you which page it treats as authoritative for that query — and that is a fixable problem. This is the one output here that points at work rather than just measuring it.

Competitors, free

Everyone named in the same answers

Every run returns every business it named, so one sample gives you the client's rate and the rate of everyone beating them, measured on identical prompts at the identical moment. No separate competitive call, no mismatched timing to explain away.

Honest denominators

A refusal is not an absence

Rates are out of the runs that actually answered. A run the provider lost is refunded and excluded; a run where the model declined the prompt is counted in samples_refused and excluded too, because “I can't help with that” is not evidence a business is invisible. samples_unreadable reports answers no shortlist could be read from.

Auditable merges

One business, every spelling it was given

Answers spell the same business several ways — with and without LLC, with & or the word and. Those fold into one row, and name_variants records every spelling that went into it, so a merge is something you can check rather than trust. reader_version stamps which version of the prose reader produced the shortlist, so you never compare two runs that were read by different code.

Built for

What this is actually for

Prove AI visibility work moved something

Baseline at 0.4, do the work, re-sample at the same count and prompt, report 0.7. Without a rate there is no before and after — only two anecdotes that may differ because the model felt like it.

See the AI Visibility Tool

Answer the client question honestly

“Are we in ChatGPT?” has no yes or no. One call that happens to name them is not a yes, and one that doesn't is not a no. A rate over 10 runs is the first answer that survives the client re-checking it themselves.

Scrape a single answer

Find the page the model trusts

When cited_domains shows a directory outranking the client's own site as the source, you have found a content and authority gap with a specific target. Pair it with citation tracking to see which domains the model leans on across a whole keyword set.

Track AI citations

Benchmark against the local field

Rank every business in the answers by shortlist_rate to see the real competitive set — which is often not the one the client expects, because the businesses AI recommends and the businesses ranking in the map pack are different lists.

Map geographic rankings
vs. the alternatives

Why not just ask ChatGPT a few times yourself?

Because the answer you get depends on when you asked, and reading ten answers by hand is where the errors come from. Manual sampling is unrepeatable, undated, and impossible to hand to a client as evidence. The alternative tools measure a domain's citation share across a corpus, which is a different question from whether an answer recommends a business.

ApproachGives a rateCompetitors includedCitation sourceAgent-ready
Asking ChatGPT by handOnly if you tally it yourselfBy re-reading every answerManualNo
A single AI scrape endpointNo — one drawOne answer's worthPer callYes
Domain-level AI visibility scoresCitation share, not recommendationBy separate lookupAggregatedYes
Local SEO Data AI Rank Tracker APIYes — 2-25 runs per callEvery business named, freePer business, per runNative MCP, agent-first
Connect in 60 seconds

Use it from your agent

Two integration surfaces: MCP for clients that speak MCP, REST API for everything else.

Direct MCP integration

Drop-in support in Claude Desktop, OpenClaw, Hermes Agent, and any MCP-aware client.

Add to your client's MCP config (e.g. claude_desktop_config.json):

{
  "mcpServers": {
    "localseodata": {
      "url": "https://mcp.localseodata.com",
      "headers": {
        "Authorization": "Bearer sk_live_..."
      }
    }
  }
}

REST API

For Perplexity Computer, ChatGPT Custom GPTs, custom agents, and any platform that calls REST endpoints directly.

Base URL:

api.localseodata.com

See the docs for endpoint reference and auth.

Quickstart

Your first call in three lines

Three fields: keyword, platform and samples. Platform accepts 'chat_gpt', 'gemini' or 'google_ai_mode', and AI Mode requires a location. Samples runs 2-25 — below about 5 the rate is too coarse to act on, and 10 is the usual daily figure. This endpoint submits and returns immediately with a job_id and a poll_url: GET that URL until status is 'complete'. Polling is free and does not expire, so a scheduled task can submit on one run and collect on the next. Typical completion is 30-60 seconds, with a tail to about 130. An identical submit inside 10 minutes returns the job already running rather than billing a second one; pass force_new: true to take a second measurement on purpose.

terminal · curl
POST /v1/ai/sample
curl -X POST https://api.localseodata.com/v1/ai/sample \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "keyword": "best snow removal company in Orchard Park NY",
    "platform": "gemini",
    "location": "Orchard Park, NY",
    "samples": 10
  }'
Pricing for this endpoint

Priced per run, because that is what costs us money

Samples × the per-run price, charged at submit. Runs the provider never delivers are refunded; polling for the result is free. There is no subscription and no monthly minimum.

ChatGPT / Gemini
4 credits
per run — 10 samples is 40 credits (~$0.20)
Google AI Mode
2 credits
per run — 10 samples is 20 credits (~$0.10)
Collecting the result
Free
polling costs nothing and does not expire
FAQ

Common questions

What is the AI Rank Tracker API?+
An async endpoint that asks the same prompt 2-25 times on ChatGPT, Gemini or Google AI Mode and reports the distribution: how often each business was named (appearance_rate), how often the answer's own prose recommended it (shortlist_rate), where in the shortlist it landed (mean_shortlist_rank), and which sources the answers cited for it (cited_domains). It exists because a model composes its answer per request, so one call is a sample rather than a fact. Cost is samples × the per-run price: 4 credits a run on ChatGPT and Gemini, 2 on Google AI Mode.
Why can't I just call an AI endpoint once?+
Because the answer changes. In one live 8-run Gemini test on a single local prompt, the answers used three different layouts and named a different set of businesses each time — the client's own recommendation rate came out at 0.5, meaning half the answers recommended them and half did not. A single call would have reported either “yes, ranked first” or “not present”, and both would have been technically true and practically misleading. If you only need one answer, the ChatGPT & Gemini Scraper is the cheaper tool.
What's the difference between appearance_rate and shortlist_rate?+
appearance_rate counts every run that named the business at all, including a passing mention in a sentence. shortlist_rate counts only the runs whose prose actually put the business on the list it was recommending. The gap between them matters: a business named in half the answers but recommended in none of them has a different problem from one that is never mentioned. mention_appearances reports the runs that named it without listing it.
Why are there two different rankings in the response?+
businesses in each run is the platform's structured LISTING, in the order it emitted cards. recommended_businesses is the SHORTLIST read out of the answer's own prose, in the order the answer argued for it. They disagree routinely — a business the prose puts third can sit tenth in the listing. Report the shortlist when a client asks where an AI recommends them. Do not merge the two.
Does this work on Gemini?+
Yes, and Gemini is where it matters most. Gemini sends no structured business block at all, so businesses is empty in every Gemini run and every Gemini figure comes from the prose shortlist. An empty businesses array on Gemini is not evidence that nobody was named — it is the expected shape.
What is reader_version and why should I care?+
The shortlist is our reading of the answer's prose, not data the provider returns. reader_version stamps which version of that reader produced it. Responses are stored and replayable, so before comparing a new job against an older one, confirm the versions match — across a bump the numbers are not comparable, and a reader improvement would read as a ranking drop. This is the field that stops a tooling change being mistaken for a client's performance.
How are businesses with several spellings handled?+
An answer may write “WNY Snow Removal” in one run and “WNY Snow Removal LLC” in the next. Those fold into one row and every spelling is listed in name_variants, so the merge is auditable. Only a legal form, a bare connector, or a tradeless corporate suffix merges — any word naming a different trade leaves the rows separate. Two rows can therefore still be one business: where one name is the other plus a trade word and both carry the same own-site domain in cited_domains, add the two rates. We leave that seam visible rather than guess, because a chain's branches share a domain the same way and a wrong merge cannot be undone from the payload.
What happens if the model refuses the prompt?+
It is counted in samples_refused and excluded from every rate, because a refusal is not evidence a business is absent. It is not refunded — the provider ran the prompt and billed us for it. A run the provider never delivered is different: that is samples_failed, it is refunded, and it is excluded too. Checking samples_refused first is how you tell “the platform is declining this prompt” from “the client is invisible”.
Why is it asynchronous?+
Ten samples take one to three minutes, and a tool call that waited for them outlived what some clients allow. When such a call was cut off the job kept running and the client retried, which submitted and billed a second job. Submitting now takes about a second and returns a job_id, so nothing can interrupt it; you collect from the poll URL, which is free and does not expire. It also means a scheduled task can submit on one turn and collect on the next.
Will I be charged twice if I retry?+
No. An identical submit inside 10 minutes returns the job already running rather than starting a second one, and comes back with deduplicated: true at 0 credits. To run the same prompt again on purpose — which is a normal thing to want here — pass force_new: true. Pass idempotency_key to control the grouping yourself for 24 hours, which is what you want when runs are driven from a schedule.
How many samples should I run?+
Ten is the usual figure for daily tracking. Below about five the rate is too coarse to act on — with four runs every possible answer is a multiple of 25%, which cannot show a real move. Twenty-five is the maximum. Pick a count and keep it fixed across runs you intend to compare, because changing the denominator changes what a difference means.
Can my AI agent call this directly?+
Yes, and the split design is built for it. MCP: add Local SEO Data to your claude_desktop_config.json and the agent calls ai_sample and ai_sample_status from any prompt. REST: any agent that makes HTTPS calls hits api.localseodata.com/v1/ai/sample with a Bearer token, then polls. Because polling is free and never expires, an agent that loses its context between turns can still collect a job it submitted earlier.

Stop reporting anecdotes. Report a rate.

100 free credits on signup — enough for two full 10-sample measurements before you spend anything.

▌ MADE FOR THE NEW LOCAL SEO STACK