AnswerLine Start free

, updated , Local SEO · GEO

Local AI answers: measure them by country, state and city

ChatGPT and Gemini answer from inside any US state you name, in all 50 states and DC: send state as a two-letter code, such as TX, and the answer is the one a person in Texas sees. A state does not change the price. Every other engine accepts state and answers for the whole US, the same as without it (states). ChatGPT and Gemini answer from 213 countries, Copilot, Perplexity and Grok from any country, and Google News takes the 71 countries with a Google News edition.

For one prompt in every state, step by step, see how to see ChatGPT answers by US state. The request, the engines and the code in three languages are on ChatGPT state targeting.

To see how AI answers change by location, run the same prompt on the same engine and day across a matrix of markets, with the market set explicitly on every request, then compare the brands, sources and places each market returns. The API is built for three levels: country, state for the US, answered from inside the state on ChatGPT, and a Google canonical location (or uule) for city-level targeting on Google Search and AI Mode. Location is set per request, so the work is in designing the matrix and in reading the results without mistaking noise for geography.

Definitions

Why answers can change by location

Consumer AI assistants ground many answers in web search, and search results depend on location. For local-intent prompts, that plausibly shifts the businesses named, the directories cited and the map results attached. For product and service prompts, market can change availability, pricing sources and regional publications.

Treat all of this as hypotheses to test on your own prompts. A first experiment: run “best family lawyer” on ChatGPT for Colorado and for Florida on the same day, several times each, and check whether the named firms and cited directories differ more between states than between repeat runs in one state. The method below makes that comparison systematic.

One prompt in six markets

On 2026-11-09 we asked ChatGPT “best pizza near me” once without a state and once with each state. Each state’s answer named pizzerias in one city inside that state, most with a street and rating in map[]:

state City in the answer First two places named
none New York L’Industrie Pizzeria, Scarr’s Pizza
TX San Antonio Il Forno, Dough Pizzeria Napoletana
NY Amsterdam Riverside Pizza, Lorenzo’s Southside
FL Opa-locka El cuchillo, El Presidente de las Pizzas Cubanas 3
CA Burbank What Up Dough Pizza, Weirdough’s
IL Carbondale Quatro’s Deep Pan Pizza, Newby’s Pizza

No place appears in two of these answers. Without a state, ChatGPT picked New York City, so a national run says nothing about a pizzeria in Texas. One run per state is a snapshot: the sweep below repeats markets to measure how much one state’s answer moves between runs. The map on the homepage shows the recorded answer for each of the 50 states; our DC answer named places outside DC, so the map leaves DC blank.

Geo parameters by engine

The parameters differ by engine. Every engine accepts state; with a country other than US it is a validation error.

Engine Endpoint Country Sub-country targeting Local result fields
ChatGPT /v1/monitor/chatgpt country (213 countries) or state state, all 50 states and DC map[], entities[]
Perplexity /v1/monitor/perplexity country (any country) or state state accepted; whole US places[]
Gemini /v1/monitor/gemini country (213 countries) or state answers from inside the state none; compare sources[]
Copilot /v1/monitor/copilot country (any country) or state state accepted; whole US none; compare sources[]
Grok /v1/monitor/grok country (any country) or state state accepted; whole US none; compare sources[]
Google AI Mode /v1/monitor/aimode country or gl, plus hl location or uule; state accepted, whole US places[], map[]
Google Search /v1/monitor/google country or gl, plus hl location or uule; state accepted, whole US localResults[]
Google News /v1/monitor/google/news country or gl, plus hl state accepted; whole US none

Notes:

The engine pages for Google local pack and AI Mode places show those fields in detail.

Running a US state sweep

The sweep below runs on ChatGPT, which answers from inside each of the 51 entries. Every other engine answers a state for the whole US. For a first run with one prompt, how to see ChatGPT answers by US state is shorter.

  1. Pick prompts with local intent. Twenty is enough to start; prompt set design covers choosing them.
  2. Fetch the market list from GET /v1/states?country=US rather than hardcoding it.
  3. Build one task per prompt and state, with an idempotency key derived from engine, prompt, state and date.
  4. Submit in batches of up to 500 to POST /v1/async/task/batch, with a webhook.
  5. Store the market on every result row. A completed result’s provenance echoes the prompt and requestedState, but a failed task carries no result, so keep a map from task id or key to prompt and state.
  6. Repeat each market at least a few times on the first sweep to measure normal variance. Add the repeat number to the idempotency key, or same-day repeats are refused as duplicates.
  7. Compare markets only on differences larger than that variance.
import hashlib
import os

import requests

BASE_URL = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
RUN_DATE = "2026-09-16"
PROMPTS = ["best family lawyer", "emergency plumber open now", "best pediatric dentist"]

states = requests.get(f"{BASE_URL}/v1/states", params={"country": "US"}, headers=HEADERS, timeout=30).json()

tasks = []
for prompt in PROMPTS:
    for state in states:
        digest = hashlib.sha256(f"{prompt}|US|{state['code']}".encode()).hexdigest()[:16]
        tasks.append({
            "taskType": "CHATGPT",
            "payload": {"prompt": prompt, "country": "US", "state": state["code"]},
            "idempotencyKey": f"chatgpt-{digest}-{RUN_DATE}",
            "webhook": {"url": "https://example.com/hooks/answers"},
        })

for start in range(0, len(tasks), 500):
    chunk = tasks[start:start + 500]
    res = requests.post(f"{BASE_URL}/v1/async/task/batch", json=chunk, headers=HEADERS, timeout=(10, 660))
    res.raise_for_status()
    for item in res.json().get("results", []):
        if not item["success"] and item.get("error", {}).get("code") != "RESOURCE_ALREADY_EXISTS":
            print(chunk[item["index"]]["payload"], item["error"]["code"])

When results arrive, the webhook body is the finished task. For a COMPLETED task, the engine result is at response.result:

from urllib.parse import urlparse

def local_signals(body: dict) -> dict:
    result = body["response"]["result"]
    return {
        "task_id": body["task"]["id"],
        "domains": sorted({urlparse(s["url"]).hostname for s in result.get("sources", [])}),
        "places": [p.get("name") for p in result.get("map", [])],
    }

Look up the prompt and state for task_id from what you stored at submission. Deliveries can repeat, so dedupe by task.id; see webhook reliability design. Batch patterns for larger matrices are in rank tracking pipelines with batches.

City-level targeting on Google

For city granularity, send location to AI Mode, or to Google Search for the classic local pack. The same prompt can be compared across cities in AI Mode’s places:

import { Client } from "@answerline/sdk";

type Named = { title: string };

const client = new Client({ apiKey: process.env.API_KEY! });
const cities = ["Austin,Texas,United States", "Denver,Colorado,United States"];

for (const location of cities) {
  const aiMode = await client.aiMode({ prompt: "emergency plumber near me", country: "US", location });
  const places = (aiMode.result as { places?: Named[] }).places ?? [];
  console.log(location, { aiModePlaces: places.map((p) => p.title) });
}

These are synchronous calls, fine for a spot check. For a recurring city matrix, submit AIMODE tasks in batches as above; the local rank tracking use case covers the pipeline.

What a sweep costs

Every market is its own request at the same price, so cost grows with the number of markets. A state does not change the price. Starter-tier base prices: ChatGPT $0.0015, Gemini $0.0015, AI Mode $0.00206, Google Search $0.0015, Google News $0.001, Copilot $0.00274, Perplexity $0.0015, Grok $0.00218.

State sweep on ChatGPT:

City check on AI Mode: 20 prompts × 10 cities × $0.00206 = $0.412 per run.

Variance runs: three repeats of one prompt in 5 states on ChatGPT is 3 × 5 × $0.0015 = $0.0225, a cheap way to calibrate before a full sweep.

A new account’s 100 free requests work on both engines, enough to test a few states or cities before sizing a program. Cost planning covers sizing a recurring program.

Reading a sweep: metrics per market

Per-market metrics, computed once results are stored with their market:

Metric Computed from What it shows
Presence rate Share of runs where your brand appears in text (or entities[] on ChatGPT) Where you are named at all
Citation share Share of citationPills[] or sources[] pointing at your domains Where your pages ground the answer
Place inclusion Whether your business is in map[], places[] or localResults[] Local visibility in structured results
Domain overlap Cited domains shared between two markets, divided by all cited domains in either How similar two markets’ source pools are
Competitor set Brands named in a market that are never named nationally Regional competitors you may not track

Compute every metric per engine, because field availability differs: Grok has no citationPills and only ChatGPT returns entities. Keep Google Search’s localResults separate from AI answers: the local pack is a ranked list, while AI answers name a handful of businesses in prose, so positions do not mean the same thing.

Country and language sweeps

Outside the US, the market unit is the country. ChatGPT and Gemini answer from 213 countries and Copilot, Perplexity and Grok from any country; on these the market is country alone. On Google Search, Google News and AI Mode, set hl as well to choose the interface language explicitly. Keep one prompt language per country run and record it, so a difference caused by translation is not reported as a difference in market. Multilingual AI answers covers translation choices.

Separating geography from noise

AI answers vary between identical runs. Before concluding that Florida sees different firms than Colorado:

  1. Hold everything else constant: same prompt text, engine, day, and include flags.
  2. Measure within-market variance from repeat runs in one state.
  3. Compare frequencies, not single answers: “named in 4 of 5 Colorado runs vs 0 of 5 Florida runs” is a finding; one run each is not.
  4. Aggregate carefully: a national average can hide the states where a brand is absent, so report per market first.

AI answer volatility covers variance in more depth.

Pitfalls

Field details for local results are on the Google Search engine page; the quickstart gets a first request running. ChatGPT state targeting sums up the state request on one page.

Questions

Which engines accept US state targeting?

Every engine accepts a two-letter code in state, which implies country US; with another country it is a 400. ChatGPT and Gemini answer from inside the state, in all 50 states and DC. Every other engine answers it for the whole US. See /docs/coverage#states.

Is Washington, DC included?

Yes. DC is one of the 51 entries GET /v1/states?country=US returns, and ChatGPT answers it like a state. Some DC answers name places in nearby Maryland, so check the addresses in map[] before counting them as DC results.

How many countries and states can I target?

GET /v1/countries returns the supported ISO country codes and accepts ?model= to list the countries for a specific engine. Google News takes the 71 countries with a Google News edition; ChatGPT, Gemini, AI Mode and Google Search answer from 213 countries; Copilot, Perplexity and Grok take any country. GET /v1/states?country=US returns the 51 entries state targeting uses.

How much will a 50-state sweep cost?

Each state is a separate request, and a state does not change the price. 20 prompts across the 51 entries from GET /v1/states on ChatGPT is 20 x 51 x $0.0015 = $1.53 per sweep at the Starter tier.

Does the same prompt give different answers in different states?

It can, and that is what a state sweep measures. Hold the prompt, engine and day constant, repeat runs to measure normal variance, and treat only differences larger than that variance as geographic.

How do I target a city on Google?

On Google Search or AI Mode, send location as a Google canonical location name in City,Region,Country form, such as Austin,Texas,United States, together with country. Alternatively send a pre-encoded uule; location and uule are mutually exclusive.

Try it on your own prompts

100 free requests on any engine, no card. One POST returns the answer, sources and citations as JSON.

Keep reading