ai_match
Determines whether businesses named in AI answers are the business you track by resolving its identifiers and matching on CID, domain, phone, or name; returns confidence, rank, and near misses.
Instructions
Use when deciding whether a business an AI named IS the business you are tracking. Takes the businesses array from ai_scraper, ai_mode or ai_sample plus a target, and returns matched, confidence, matched_on, rank and the near misses.
WHY NOT DO IT YOURSELF: the two obvious rules both fail quietly. Matching on domain misses roughly a third of appearances, because that is how often ChatGPT names a business with an empty website and domain. Matching on name fails on Google AI Mode, which labels cards editorially — the same business came back as "The Classic Staple" in one answer and under its trading name in the next. This matches on cid, then domain, then phone, then name-with-address, then name, and tells you which one it used.
THE TARGET IS RESOLVED FOR YOU: pass business_name and location and the business is looked up in the local graph first, so a name-only target ends up matching on a cid, a domain and a phone rather than on a string. That lookup is what the 5 credits buy. Pass a cid, domain, website or phone yourself and no lookup is made and it costs 1.
ONE ANSWER OR A WHOLE SAMPLE: pass businesses for one answer and get a verdict; pass runs from an ai_sample result and get appearance_rate, best_rank, worst_rank and mean_rank across the sample, with the verdict for each run. Pass one or the other, never both.
READING confidence: 1.0 is a cid, 0.9 a domain or phone, 0.8 a name with a matching address, 0.65 a name alone. matched is true exactly when confidence is 0.5 or above, so a name-only tie between two candidates comes back matched: false — one of them is the client, but nothing in the answer says which. Filter on matched_on when you need identifier-grade certainty.
WHAT IS NOT A SIGNAL: a website on a shared host (Facebook, Instagram, Linktree, business.site, the big directories) is not a domain match. A name matches only when the shorter of the two is wholly contained in the longer, and a one-word name never matches alone. Two addresses agree only when the street number, street line and town all agree. target.place_id needs target.location beside it.
IDENTIFIER COVERAGE — READ THIS BEFORE QUOTING A LOW RATE: identifier_coverage says how much of the answer could be identified AT ALL. identified counts the businesses carrying a cid, a domain or a phone, out of candidates. Two of six means four rows could only ever be matched by name, and a name-only miss is not the same fact as an absence — say so rather than reporting the rate alone. Coverage is a property of what the platform published, not of the client.
WHERE THE CID GOES: pass a cid inside target, where it makes the match exact and skips the lookup. Never filter the businesses you pass in on whether they carry one — the rows without a cid are most of the answer, and dropping them removes the appearances you are trying to count.
SOURCE PROVENANCE, NOT A WARNING: source_graph says which platform's record the AI repeated — google, bing, yelp, aggregator, or unknown. A cid means Google; a Yelp URL means Yelp; a business's own domain means unknown, because it says the AI has the business and not where it read it. entity_variants lists the spellings of the matched business across the runs, each with its source_graph. Two or three variants is the NORMAL state of a business that exists on more than one platform — do not report it as a problem, report it as provenance. It is what lets you say: your Google profile is fine, ChatGPT is reading Bing, and Bing has you in the wrong town.
WHAT IS A PROBLEM: nap_conflicts, and only that. It carries a value that genuinely contradicts the client's own record — a phone number that is not theirs, an address in the wrong town — with the source_graph that supplied it, so the fix has an address. An empty nap_conflicts beside three entity_variants means the client is listed in three places and all three are right.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| runs | No | The runs array from an ai_sample result, to get a rate across the whole sample instead of one verdict. | |
| target | Yes | The business to look for | |
| resolve | No | Force the profile lookup on (true) or off (false). Default: on when there is a location and no identifier was supplied. | |
| businesses | No | One answer's businesses, exactly as ai_scraper, ai_mode or a single ai_sample run returns them. Extra fields are ignored, so pass the array through untouched. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rank | No | ||
| runs | No | ||
| match | No | ||
| target | Yes | ||
| matched | No | ||
| best_rank | No | ||
| mean_rank | No | ||
| candidates | No | ||
| confidence | No | ||
| matched_on | No | ||
| worst_rank | No | ||
| appearances | No | ||
| runs_checked | No | ||
| nap_conflicts | No | ||
| appearance_rate | No | ||
| entity_variants | No | ||
| identifier_coverage | No |