AI answer tracking as an agency deliverable
AI answer tracking as an agency deliverable means running a fixed set of client-relevant prompts through ChatGPT, Gemini and similar engines on a schedule, storing every answer, and reporting how often the client is named, cited, or replaced by a competitor. The client question usually arrives informally (“our CEO asked whether we show up in ChatGPT, can you check?”). An agency that answers with a screenshot has answered once. An agency that answers with a trend line per engine and market has a retainer.
Metrics
The report rests on three definitions:
- Mention rate: the share of monitored prompts whose answer names the client brand at least once.
- Citation share: the share of all cited source URLs in those answers that point to the client’s domains.
- Displacement: a prompt where a competitor is named and the client is not.
The mentions vs citations post explains why these two numbers move independently, and the share-of-voice framework covers weighting across engines.
Report inputs by engine
Response fields differ by engine, and a report template that assumes one shape for all of them will silently produce zeros.
| Report input | ChatGPT | Perplexity | Gemini | Copilot | Grok | AI Mode |
|---|---|---|---|---|---|---|
| Verbatim answer | text, markdown |
text, markdown |
text, markdown |
text, markdown |
text, markdown |
text, markdown |
| Cited pages | sources[] |
sources[] |
sources[] |
sources[] |
sources[] |
sources[] |
| Named brands as structured data | entities[] (type, name) |
none, match in text | none, match in text | none, match in text | none, match in text | none, match in text |
| Searches behind the answer | searchQueries[] (free with include.searchQueries; empty on answers served today) |
none | none | coming | searchQueries[] |
none |
ChatGPT, Gemini, Google Search and AI Mode answer from 213 countries, which is how a multi-region client gets per-market splits from one integration; Copilot, Perplexity and Grok take any country, and Google News the 71 countries with a Google News edition. Gemini also takes a US state. See local answers at state level. markdown is returned when you request it with include.markdown.
Brand detection is your code on every engine except ChatGPT, whose entities[] lists the brands and products an answer names. Keep a per-client alias list (brand name, product names, common misspellings, the domain) and match it case-insensitively against result.text.
Setting up one client
- Agree the prompt set with the client. 30 to 60 prompts is a workable range for a first scope: category prompts (“best payroll software for restaurants”), problem prompts, comparison prompts, and a few brand prompts (“is
reliable?”). Write them the way a buyer would type them. Prompt set design goes deeper. - Pick engines and markets. Start with the engines the client’s buyers use. Each additional engine or market multiplies cost linearly, so add them deliberately.
- Choose the cadence. Weekly is enough for most clients; answers vary run to run, so a trend needs repeated samples rather than daily noise. See monitoring cadence and answer volatility.
- Submit each run as an async batch. One
POST /v1/async/task/batchcall accepts 1 to 500 tasks. Give every task anidempotencyKeyderived from client, prompt, engine, market and run date, so a retried submission never creates duplicates. - Receive results by webhook. Each finished task is POSTed to your
webhook.url; the completed engine result is atresponse.result. Verify the signature before trusting the body. - Store raw JSON, then compute metrics. Keep the full response per task; metrics are derived, and you will recompute them whenever the alias list changes.
- Render the monthly report. The report template post has a structure non-specialists can follow.
Submitting a weekly run
curl -X POST https://api.answerline.dev/v1/async/task/batch \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"taskType": "CHATGPT",
"idempotencyKey": "acme:p014:chatgpt:US:2026-09-21",
"webhook": { "url": "https://reports.example-agency.com/hooks/answers" },
"payload": { "prompt": "best payroll software for restaurants", "country": "US" }
},
{
"taskType": "GEMINI",
"idempotencyKey": "acme:p014:gemini:US:2026-09-21",
"webhook": { "url": "https://reports.example-agency.com/hooks/answers" },
"payload": { "prompt": "best payroll software for restaurants", "country": "US" }
}
]'
The response lists one result per task by index. A task that failed validation or reused a key comes back with its own error (VALIDATION_ERROR, RESOURCE_ALREADY_EXISTS, INSUFFICIENT_CREDITS) while the rest are queued, so check each item rather than the HTTP status alone.
Building the batch from a client config in Python
import os
import requests
API = "https://api.answerline.dev"
HEADERS = {
"Authorization": f"Bearer {os.environ['API_KEY']}",
"Content-Type": "application/json",
}
def weekly_batch(client_id, prompts, engines, markets, run_date, hook_url):
tasks = []
for i, prompt in enumerate(prompts):
for engine in engines:
for country in markets:
tasks.append({
"taskType": engine,
"idempotencyKey": f"{client_id}:p{i:03d}:{engine.lower()}:{country}:{run_date}",
"webhook": {"url": hook_url},
"payload": {"prompt": prompt, "country": country},
})
# 500 tasks per batch request at most
for start in range(0, len(tasks), 500):
r = requests.post(f"{API}/v1/async/task/batch", json=tasks[start:start + 500], headers=HEADERS, timeout=60)
r.raise_for_status()
for item in r.json().get("results", []):
if not item.get("success"):
err = item.get("error", {})
print("task", start + item["index"], err.get("code"), err.get("message"))
Detecting the client in a finished task
import re
def mentioned(result, aliases):
text = result.get("text") or ""
return any(re.search(rf"\b{re.escape(a)}\b", text, re.IGNORECASE) for a in aliases)
def cited(result, domains):
return [s["url"] for s in result.get("sources", []) if any(d in s.get("url", "") for d in domains)]
def handle_webhook(body):
task = body["task"]
if task["status"] != "COMPLETED":
return None
result = body["response"]["result"]
return {
"key": task.get("idempotencyKey"),
"mentioned": mentioned(result, ["Acme Payroll", "Acme"]),
"cited_urls": cited(result, ["acmepayroll.com"]),
}
Deliveries can arrive more than once and out of order, so upsert by task.id rather than appending.
Budgeting per client
Costs are per task, from the published prices per 1,000 requests at the Starter tier: ChatGPT $0.60, Gemini $0.60, Google AI Mode $2.06, Google Search $1.03, Google News $0.20. ChatGPT’s include flags are free. Failed tasks are not charged. Larger tiers, reached by 30-day spend, cost less per request. Full rules are on the pricing docs.
Worked example: a standard client scope
50 prompts, weekly, one market, ChatGPT + Gemini, async:
- Cost per prompt per run: $0.0006 + $0.0006 = $0.0012
- Runs per month: 4 (weekly)
- Monthly: 50 x 4 x $0.0012 = $0.24
Variations, same arithmetic:
| Change | Calculation | Cost per month |
|---|---|---|
| Baseline above | 50 x 4 x $0.0012 | $0.24 |
| Month with 5 weekly runs | 50 x 5 x $0.0012 | $0.30 |
Add ChatGPT searchQueries (free) |
50 x 4 x $0.0012 | $0.24 |
| Second market (e.g. US and GB) | 50 x 4 x $0.0012 x 2 | $0.48 |
| Add a Google News query per prompt | 50 x 4 x ($0.0012 + $0.0002) | $0.28 |
What a portfolio of clients costs
There is no plan to pick: you top up a USD balance from the dashboard and each request is charged from it. The more you spend over 30 days, the less ChatGPT, Gemini, Perplexity and Google News requests cost (see pricing). Using the $0.24 baseline client at Starter prices:
| Clients | Monthly cost at Starter prices |
|---|---|
| 5 | $1.20 |
| 20 | $4.80 |
| 50 | $12.00 |
The Growth tier starts at $95.00 of 30-day spend, about 395 baseline clients; once a tier is reached its lower prices apply. Two things matter in practice. Leave headroom in the balance for re-runs and pitch audits, or turn on auto top-up. When the balance runs out, new requests get 403 INSUFFICIENT_CREDITS, so a scheduler should read GET /v1/credits (its remaining is the balance in dollars) before submitting a run. Cost planning covers forecasting across a portfolio.
Pricing the service to the client
Price on scope rather than per-request costs. Prompts, engines, markets and cadence are levers the client understands, and they map one-to-one to the cost formula above. Typical packaging is a monitoring retainer, or a line inside an existing SEO scope with a quarterly review of the prompt set.
Prospect audits
The strongest sales use of this data is a pre-meeting audit: run the prospect’s 10 category prompts on the engines their buyers use, and bring the answers. “When a buyer asks for the best tool in your category, these three competitors are named and you are not” is a finding a prospect can check themselves.
Cost for 10 prompts on ChatGPT and Gemini: 10 x $0.0012 = $0.012, and a new account’s 100 free requests cover 5 such audits. Run each prompt more than once if the result will be quoted, since a single answer can differ on the next run.
For the platform version of this, where the data sits behind your own branded dashboard, see white-label AI visibility.
Mistakes that erode client trust
- Treating one run as the result. Answers vary between runs, so report rates over several runs.
- Relying on
entities[]alone. Only ChatGPT returns it, so a template that reads it reports the client as never mentioned on every other engine. Match aliases intextthere. - Loose alias matching. Short or generic brand names (“Nova”, “Bolt”) produce false positives. Use word boundaries and review a sample of matches each month.
- Editing prompts mid-trend. An edit breaks the prompt’s history; retire it and add a new one with a new ID.
- Mixing markets in one number. A client strong in the US and absent in Germany averages to a misleading middle. Report per market first.
- Random idempotency keys. A key generated fresh on each attempt does not prevent duplicates. Derive it from client, prompt, engine, market and date, as above; see idempotency keys explained.
- Parsing webhooks before verifying them. Verify the
Webhook-Signatureover the raw body, then parse.
What to hand the client each month
- Mention rate and citation share per engine and market, with the previous three months for context
- Prompts where the client entered or left the answer
- The competitors named most often on prompts where the client is absent
- The most-cited third-party pages in the category, which become the content and outreach list
- For key answers, the answer text next to its cited sources in order, so the client sees what a buyer sees
Start with the quickstart, then the AI visibility tracking use case.
Questions
What does an AI answer tracking service for agency clients consist of?
A fixed prompt set per client, run on a schedule across the AI engines and markets the client cares about, with every response stored and summarized in a monthly report. The core metrics are mention rate, citation share and which competitors were named instead.
What does one agency client cost per month?
It depends on prompts, engines, markets and cadence. For example, 50 prompts run weekly (4 runs) on ChatGPT and Gemini costs 50 x 4 x $0.0012 = $0.24 a month.
Does every engine return a list of brands named in the answer?
No. Only ChatGPT returns an entities array, the brands and products named in the answer as type and name pairs. Gemini has none, so there you detect brand mentions by matching names and aliases in the text or markdown of the answer.
Should agencies use synchronous calls or async tasks for client monitoring?
Async tasks. Synchronous calls keep a connection open for the whole run, while async batches queue up to 500 tasks per request and can deliver results to a webhook.
Can I run a prospect audit with the free requests?
Yes. A new account gets 100 free requests, granted once, and they work on every live engine. 10 prompts on ChatGPT and Gemini are 20 requests, so the free requests cover 5 such audits; after that one costs $0.012.