What it does
Ranking third on Google no longer means you are in the answer. AI Overviews, ChatGPT and Perplexity each pick a handful of sources, and a page that ranks well can be left out of all of them. Search Console cannot tell you, and the AI tools have no report for site owners.
Every Monday the agent takes your top 20 non-branded queries from Search Console, asks DataForSEO for the AI Overview, the ChatGPT answer and the Perplexity answer to each, and checks whether your domain is cited. It sets that against the visits GA4 records from AI assistants, landing page by landing page, so you see which cited pages actually send people.
How it works
1Fix the 20 queries for the month
On the first run each month, call
searchanalytics.querywithdimensions: ["query"]for the last 28 days, drop queries matching your brand regular expression, and keep the top 20 by clicks with their average position and top page. Save them inai-visibility-queries.jsonso every weekly run in the month asks the same 20.2Ask the three AI surfaces
For each query:
POST /v3/serp/google/organic/live/advancedwithkeyword,location_code(2840 for the US),language_code: "en",depth: 10andload_async_ai_overview: true, reading thereferences(domain,url) inside theai_overviewitem;POST /v3/ai_optimization/chat_gpt/llm_scraper/live/advancedwith the same keyword andforce_web_search: true, readingsources[].domain; andPOST /v3/ai_optimization/perplexity/llm_responses/livewithuser_promptandmodel_name: "sonar", readingitems[].sections[].annotations[].url. That is 60 paid requests a run, roughly $0.30 at list prices; sum thecostfields and test onhttps://sandbox.dataforseo.com/v3/first.3Pull visits from AI assistants
Call
runReportfor the last 28 days withdimensions: ["sessionSource", "landingPagePlusQueryString"], metricssessionsandkeyEvents, and adimensionFilteronsessionSourcewithmatchType: "PARTIAL_REGEXP"andchatgpt\.com|perplexity\.ai|gemini\.google\.com|claude\.ai|copilot\.microsoft\.com.- 4
4Join citations, rankings and visits
A query counts as cited when any cited domain, lowercased and without
www., equals your domain or ends with.yourdomain. Anti-join: queries where Search Console has you at position 3 or better and no surface cites you. Then reduce cited URLs and GA4 landing pages to paths (no query string, which strips ChatGPT'sutm_source, no trailing slash) and join: cited pages that get AI visits, and AI-visited pages that none of the 20 answers cite. - 5
5Compare and post
Read last week's card with
GET https://briefkin.dev/v1/cards/insight-dataforseo-ai-answer-visibilityand append this week's count to its history. Post a metric card: cited queries out of 20, the split by surface, AI-assistant sessions, and a table of the cited queries and the top-3 queries nobody cites. Post it to the board
With
BRIEFKIN_TOKENset, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
What you get
- Cited queries out of your top 20 non-branded queries, and the change on last week.
- By surface: AI Overviews, ChatGPT and Perplexity.
- Top-3 queries never cited: where you win on Google and lose in AI answers.
- AI-assistant visits by landing page, with the cited pages that send them.
- The run's cost from the
costfields, and the first page to rework for AI answers.
Install and run it
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
Install the skill
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shell
curl -fsSL https://briefkin.dev/skills/dataforseo-ai-answer-visibility/install | shRun it
Ask Claude Code:
prompt
Run the dataforseo-ai-answer-visibility skillOr paste the prompt instead of installing:
prompt
Check my AI answer visibility. From the Search Console API, take my top 20 non-branded queries by clicks (last 28 days; brand regex: <regex>) with position. For each, use DataForSEO: the Google SERP live advanced endpoint with load_async_ai_overview true (references in the ai_overview item), the ChatGPT LLM Scraper live advanced endpoint with force_web_search true (sources), and Perplexity LLM Responses live with model sonar (annotations). That is 60 requests; tell me the total of the cost fields. Count a query as cited when my domain appears in any surface. From GA4, get sessions by sessionSource and landing page for chatgpt.com, perplexity.ai, gemini.google.com, claude.ai and copilot.microsoft.com. Tell me cited queries out of 20 by surface, top-3 queries never cited, and which cited pages get AI visits. End with the page to rework first.Put it on a schedule
Mondays at 8:00, from cron on any machine where Claude Code is signed in:
crontab
0 8 * * 1 claude -p "Run the dataforseo-ai-answer-visibility skill"Add it with
crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.Send it to your board
Connect Briefkin once with
curl -fsSL https://briefkin.dev/install | shand every run lands on your board as a stat tile. How setup works
View the SKILL.mdRaw file
SKILL.md---
name: dataforseo-ai-answer-visibility
description: "Weekly: of your top 20 non-branded Google queries, how many get an AI answer citing your domain in ChatGPT, Perplexity or AI Overviews, plus AI referral visits. Use when the user asks for this, or when it runs on a schedule."
---
# AI answer visibility: DataForSEO, GA4 and Search Console
Weekly: of your top 20 non-branded Google queries, how many get an AI answer citing your domain in ChatGPT, Perplexity or AI Overviews, plus AI referral visits.
Ranking third on Google no longer means you are in the answer. AI Overviews, ChatGPT and Perplexity each pick a handful of sources, and a page that ranks well can be left out of all of them. Search Console cannot tell you, and the AI tools have no report for site owners.
Every Monday the agent takes your top 20 non-branded queries from Search Console, asks DataForSEO for the AI Overview, the ChatGPT answer and the Perplexity answer to each, and checks whether your domain is cited. It sets that against the visits GA4 records from AI assistants, landing page by landing page, so you see which cited pages actually send people.
## Two ways to get the data
Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.
## Route A: API or MCP server
### What you need
- A DataForSEO API login and password in `DATAFORSEO_LOGIN` and `DATAFORSEO_PASSWORD`, or the DataForSEO MCP server, with a balance (each run spends about $0.30).
- Read access to the Search Console property and Viewer access to the GA4 property, plus your brand terms as a regular expression.
If something is missing, say what and stop; do not invent numbers.
### Steps
1. **Fix the 20 queries for the month** (Google Search Console): On the first run each month, call `searchanalytics.query` with `dimensions: ["query"]` for the last 28 days, drop queries matching your brand regular expression, and keep the top 20 by clicks with their average position and top page. Save them in `ai-visibility-queries.json` so every weekly run in the month asks the same 20.
2. **Ask the three AI surfaces** (DataForSEO): For each query: `POST /v3/serp/google/organic/live/advanced` with `keyword`, `location_code` (2840 for the US), `language_code: "en"`, `depth: 10` and `load_async_ai_overview: true`, reading the `references` (`domain`, `url`) inside the `ai_overview` item; `POST /v3/ai_optimization/chat_gpt/llm_scraper/live/advanced` with the same keyword and `force_web_search: true`, reading `sources[].domain`; and `POST /v3/ai_optimization/perplexity/llm_responses/live` with `user_prompt` and `model_name: "sonar"`, reading `items[].sections[].annotations[].url`. That is 60 paid requests a run, roughly $0.30 at list prices; sum the `cost` fields and test on `https://sandbox.dataforseo.com/v3/` first.
3. **Pull visits from AI assistants** (Google Analytics): Call `runReport` for the last 28 days with `dimensions: ["sessionSource", "landingPagePlusQueryString"]`, metrics `sessions` and `keyEvents`, and a `dimensionFilter` on `sessionSource` with `matchType: "PARTIAL_REGEXP"` and `chatgpt\.com|perplexity\.ai|gemini\.google\.com|claude\.ai|copilot\.microsoft\.com`.
4. **Join citations, rankings and visits**: A query counts as cited when any cited domain, lowercased and without `www.`, equals your domain or ends with `.yourdomain`. Anti-join: queries where Search Console has you at position 3 or better and no surface cites you. Then reduce cited URLs and GA4 landing pages to paths (no query string, which strips ChatGPT's `utm_source`, no trailing slash) and join: cited pages that get AI visits, and AI-visited pages that none of the 20 answers cite.
5. **Compare and post**: Read last week's card with `GET https://briefkin.dev/v1/cards/insight-dataforseo-ai-answer-visibility` and append this week's count to its history. Post a metric card: cited queries out of 20, the split by surface, AI-assistant sessions, and a table of the cited queries and the top-3 queries nobody cites.
## Route B: the browser
### What you need
- Signed in to Search Console and GA4, and to ChatGPT and Perplexity accounts of your own.
If something is missing, say what and stop; do not invent numbers.
### Steps
Start at https://search.google.com/search-console/performance/search-analytics. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.
1. **Take the top 20 queries**: Pick the property, set Date to `Last 28 days`, sort Queries by Clicks, skip branded queries and note the top 20 with their average position.
2. **Ask ChatGPT and Perplexity**: In `https://chatgpt.com/` with search on, and in `https://www.perplexity.ai/`, ask each query in a new chat. Open the sources or citations panel and note whether your domain is listed.
3. **Check Google's AI Overview**: Search each query on `https://www.google.com/`. When an AI Overview appears, expand it and check whether one of its source links points at your domain.
4. **Read AI-assistant visits**: In GA4, open Reports > Acquisition > Traffic acquisition for the last 28 days, set the primary dimension to Session source, and filter for `chatgpt.com`, `perplexity.ai`, `gemini.google.com`, `claude.ai` and `copilot.microsoft.com`. Add Landing page + query string as a secondary dimension and note sessions per page.
5. **Count and compare**: Count queries cited on any surface, list top-3 queries cited nowhere, and match cited pages with the AI-visited landing pages.
Note: Answers in your own signed-in accounts are personalized by your history, memory and location, so they can differ from what DataForSEO's clean sessions return; the browser route costs nothing but takes about an hour for 60 asks. Google shows AI Overviews only for some queries and some signed-in users.
## The report
- **Cited queries** out of your top 20 non-branded queries, and the change on last week.
- **By surface**: AI Overviews, ChatGPT and Perplexity.
- **Top-3 queries never cited**: where you win on Google and lose in AI answers.
- **AI-assistant visits** by landing page, with the cited pages that send them.
- The run's cost from the `cost` fields, and the first page to rework for AI answers.
## Post it to Briefkin
When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.
```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
-H "authorization: Bearer $BRIEFKIN_TOKEN" \
-H "content-type: application/json" \
-d @- <<'JSON'
{
"v": 1,
"event_id": "dataforseo-ai-answer-visibility/<date of this run, e.g. 2026-10-16>",
"item_key": "dataforseo-ai-answer-visibility",
"project": "example.com",
"source": "AI answer visibility: DataForSEO, GA4 and Search Console skill",
"kind": "metric",
"title": "Cited in 4 of 20 top queries; 6 top-3 queries never cited",
"metric": {
"label": "Top 20 queries citing you",
"value": 4,
"period_label": "This week",
"better": "higher",
"period_start": "<start of the period, ISO 8601>",
"period_end": "<end of the period, ISO 8601>"
},
"glance": [
{
"type": "Grid",
"props": {
"columns": 3
},
"children": [
{
"type": "Stat",
"props": {
"label": "AI Overviews",
"value": "2 of 20"
}
},
{
"type": "Stat",
"props": {
"label": "ChatGPT",
"value": "3 of 20"
}
},
{
"type": "Stat",
"props": {
"label": "Perplexity",
"value": "2 of 20"
}
}
]
},
{
"type": "Badges",
"props": {
"items": [
{
"label": "6 top-3 queries never cited",
"tone": "warn"
},
{
"label": "412 AI sessions, 28 days",
"tone": "info"
}
]
}
}
],
"widget": [
{
"type": "Table",
"props": {
"columns": [
"Query",
"Google position",
"AI Overview",
"ChatGPT",
"Perplexity"
],
"align": [
"left",
"right",
"left",
"left",
"left"
],
"rows": [
[
"free invoice template",
2.4,
"Cited",
"Cited",
"No"
],
[
"net 30 payment terms",
3.9,
"Cited",
"No",
"Cited"
],
[
"invoice vs receipt",
6.2,
"No",
"Cited",
"Cited"
],
[
"late payment email template",
8.4,
"No",
"Cited",
"No"
],
[
"invoice number format",
1.4,
"No",
"No",
"No"
],
[
"invoice generator",
1.8,
"No",
"No",
"No"
],
[
"proforma invoice",
2.2,
"No",
"No",
"No"
],
[
"recurring invoice",
2.6,
"No",
"No",
"No"
],
[
"how to invoice as a freelancer",
2.9,
"No",
"No",
"No"
],
[
"invoice due date",
3,
"No",
"No",
"No"
]
]
}
},
{
"type": "Callout",
"props": {
"text": "251 of the 412 AI-assistant sessions landed on /blog/invoice-vs-receipt, cited by ChatGPT and Perplexity. Start with /blog/invoice-number-format: position 1.4, cited nowhere. Run cost: 60 requests, $0.31.",
"tone": "info"
}
}
],
"size": "md"
}
JSON
```
Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.
Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).
## Run it on a schedule
Suggested: Mondays at 8:00 (`0 8 * * 1`). From cron, with the agent signed in on that machine:
```bash
0 8 * * 1 claude -p "Run the dataforseo-ai-answer-visibility skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```
Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/dataforseo-ai-answer-visibility#schedule
Source: https://briefkin.dev/skills/dataforseo-ai-answer-visibility
What your agent needs
A DataForSEO API login and password in
DATAFORSEO_LOGINandDATAFORSEO_PASSWORD, or the DataForSEO MCP server, with a balance (each run spends about $0.30).Read access to the Search Console property and Viewer access to the GA4 property, plus your brand terms as a regular expression.
Connecting DataForSEO
- DataForSEO MCP server, DataForSEO's own. Run it locally with
npx dataforseo-mcp-serverand setDATAFORSEO_USERNAMEandDATAFORSEO_PASSWORDto your API login and API password (Dashboard > API Access); addhttpto the command for clients that want a local HTTP server. A hosted server runs athttps://mcp.dataforseo.com/mcpfor clients that can send a Basic authorization header. You can turn off the modules a skill doesn't use to keep the tool list short (setup guide). - REST API with Basic auth. Store the same pair in
DATAFORSEO_LOGINandDATAFORSEO_PASSWORDand call the endpoints withcurl -u "$DATAFORSEO_LOGIN:$DATAFORSEO_PASSWORD". The free sandbox athttps://sandbox.dataforseo.com/v3/returns sample data at no cost, which is the place to test a skill before it spends money.
The API password can spend your balance but cannot sign in to the dashboard or change billing. Set a low balance alert in the dashboard, and give each skill a fixed keyword list and depth so a run costs the same every time.
Connecting Google Analytics
- Google Analytics MCP server, Google's own open-source server (
analytics-mcpon PyPI, source). It runs locally withpipx run analytics-mcp, offersrun_report,run_realtime_reportandget_account_summaries, and Google labels it experimental. - Data API with a service account. Enable the Google Analytics Data API in a Google Cloud project, create a service account, add its email as a Viewer on the GA4 property, and point
GOOGLE_APPLICATION_CREDENTIALSat its JSON key. The skill also readsGA4_PROPERTY_ID. - Your own Google login.
gcloud auth application-default login --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform --client-id-file=client.jsongives the MCP server or a script your user's access without a key file.
Request only analytics.readonly and keep the service account at Viewer: none of these reports needs Editor.
Connecting Google Search Console
- MCP server. Google doesn't publish one for Search Console. Community MCP servers exist; check which scopes one asks for before you sign in.
- API with a service account. Enable the Google Search Console API in a Google Cloud project, create a service account, and add its email under Settings > Users and permissions on the property. Point
GOOGLE_APPLICATION_CREDENTIALSat the key and setGSC_SITE_URLtosc-domain:example.comorhttps://www.example.com/. - OAuth as yourself. When you can't add users to the property, a desktop OAuth client with the
webmasters.readonlyscope and a stored refresh token works for scheduled runs.
Ask for webmasters.readonly and add the service account as a Restricted user; the reports only read.
Questions
What does a run cost, and can it be cheaper?
Twenty queries on three surfaces is 60 paid requests, about $0.30 at current list prices: a few tenths of a cent per SERP, $0.004 per live ChatGPT scrape, and Perplexity at DataForSEO's fee plus the model's tokens. The Standard queue for the SERP and ChatGPT calls costs less if you can wait for results. Each response carries a cost field, so the card reports the real figure.
Why do AI visits in GA4 not match the citations?
AI answers change from one ask to the next, and the 20 queries are a sample of what people type into ChatGPT, so pages cited for other prompts still get visits. Some AI apps also open links without a referrer, which GA4 files as Direct. Read the GA4 side as a floor and the citation count as a weekly sample.
Do I need Briefkin to use the AI answer visibility: DataForSEO, GA4 and Search Console skill?
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.
Which agents can run it?
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Can it work without an API or MCP server, from my browser?
Yes. Switch the data source to "Your browser" and the steps change to the DataForSEO, Google Analytics and Google Search Console pages themselves: the agent opens search.google.com/search-console/performance/search-analytics in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.