<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lachezar Dimitrov</title>
    <description>The latest articles on DEV Community by Lachezar Dimitrov (@lachezard).</description>
    <link>https://dev.to/lachezard</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4077206%2F4225cccf-43e8-4dfe-8403-f4e063ef2f41.png</url>
      <title>DEV Community: Lachezar Dimitrov</title>
      <link>https://dev.to/lachezard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lachezard"/>
    <language>en</language>
    <item>
      <title>AI Visibility Tracking: What 23 AI Overviews Showed</title>
      <dc:creator>Lachezar Dimitrov</dc:creator>
      <pubDate>Mon, 24 Aug 2026 11:58:00 +0000</pubDate>
      <link>https://dev.to/lachezard/ai-visibility-tracking-what-23-ai-overviews-showed-593</link>
      <guid>https://dev.to/lachezard/ai-visibility-tracking-what-23-ai-overviews-showed-593</guid>
      <description>&lt;p&gt;&lt;strong&gt;AI visibility tracking means measuring whether AI answer engines mention and cite your brand when buyers ask questions in your category.&lt;/strong&gt; Most tools report a mention count. That number alone is not actionable. In our own measurement of 23 buyer prompts, 91% triggered a Google AI Overview and we were cited in zero of the non-branded ones — and the reason turned out to be something a mention counter would never have shown us.&lt;/p&gt;

&lt;p&gt;This is not a roundup of tools. We built a tracker, pointed it at our own category, and are publishing what came back, including the parts that make us look bad. If you are evaluating AI visibility tracking, the useful question is not which dashboard is prettiest. It is which number tells you what to do next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we measured, and how
&lt;/h2&gt;

&lt;p&gt;On 26 July 2026 we ran 23 prompts through two surfaces, in the US market, in English. The prompt set was built the way a buyer actually searches: four branded prompts about our own company, and 19 non-branded prompts covering the questions our category gets asked — pricing, vendor selection, industry-specific automation, build-versus-buy.&lt;/p&gt;

&lt;p&gt;Two signals, both machine-readable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google AI Overview.&lt;/strong&gt; For each query: does an AI Overview trigger at all, is our domain among its cited references, and which domains are cited instead. We also captured our classic organic position for the same query, which turned out to matter more than we expected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings retrieval.&lt;/strong&gt; Whether our domain surfaces in the vector index layer that many AI applications query before generating an answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we deliberately did &lt;em&gt;not&lt;/em&gt; claim to measure: the answer text inside ChatGPT, Claude, or Perplexity. No API exposes what those systems said about your brand in a real user session. Any tool claiming to track this is running its own prompts through the API and inferring, which is a reasonable proxy but is not the same thing. We think vendors should say so plainly, so we are saying it about our own work first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding one: AI Overviews are not an emerging surface, they are the surface
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;21 of 23 prompts (91%) returned a Google AI Overview.&lt;/strong&gt; Not a handful. Not the informational ones only. Nearly every commercial question our buyers ask now gets answered above the organic results, by a system that cites a handful of sources and moves on.&lt;/p&gt;

&lt;p&gt;That reframes what a ranking is worth. Position 4 on a query where an AI Overview occupies the first screen is not position 4 in any meaningful sense. If you are still reporting average position without segmenting by whether an AI Overview fires, your report is describing a page layout that most of your buyers are no longer seeing first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding two: we scored zero, and the zero was the useful part
&lt;/h2&gt;

&lt;p&gt;Here is the uncomfortable table. Of our four branded prompts, all four triggered an AI Overview and three cited us. Of our 19 non-branded prompts, 17 triggered an AI Overview and &lt;strong&gt;zero&lt;/strong&gt; cited us.&lt;/p&gt;

&lt;p&gt;A mention-counting tool would have reported "3 citations, 13% visibility" and drawn a line on a chart. That framing would have been actively misleading. The three citations were on queries containing our own company name — queries where a buyer already knows who we are. On every question where someone was actually shopping, we did not exist.&lt;/p&gt;

&lt;p&gt;Branded visibility and non-branded visibility are different metrics measuring different business realities, and averaging them together produces a number that flatters you. If your AI visibility report shows a single blended percentage, split it. The branded number tells you whether your entity is understood. The non-branded number tells you whether you are in the consideration set. Only the second one is a growth metric.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding three: citation is mostly downstream of ranking
&lt;/h2&gt;

&lt;p&gt;This is the finding that changed how we plan, and it comes from a second, smaller run rather than the study above. Two days later, on 28 July 2026, we re-tested six of the 19 non-branded queries. Four of them returned an AI Overview. For those four we captured every domain cited, then checked whether those same domains also ranked in the classic organic results for the identical query. So the overlap figures below describe four AI Overviews from 28 July, not the 21 from 26 July.&lt;/p&gt;

&lt;p&gt;Across the 31 citations those four answers issued:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;74% also ranked in the classic organic top 20&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;48% ranked in the top 10&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Only 25% were cited without ranking anywhere in the first two pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sample is small and we would not present it as a universal law. But the direction is clear enough to act on: for most queries, Google is drawing its AI Overview citations from a pool it has already decided to rank. There is no separate side door. The bulk of "AI visibility optimization" is ordinary ranking work, and a tracker that reports citations without reporting your organic position for the same query has hidden the causal variable.&lt;/p&gt;

&lt;p&gt;That 25% residual is real and worth chasing — it is where format, structure, and being the definitive source on a narrow question earn a citation without a ranking. But it is the exception, not the strategy. Anyone selling you an AEO methodology that bypasses ranking should be asked to show the overlap data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding four: one query type ignored websites entirely
&lt;/h2&gt;

&lt;p&gt;One prompt in our set asked for the top AI automation agencies in a specific city. The AI Overview cited exactly four domains, and every one of them was a directory: Clutch, DesignRush, GoodFirms, and The Manifest. No agency websites at all. Not the market leaders, not the best-optimized pages. Directories.&lt;/p&gt;

&lt;p&gt;For location-shaped queries, Google appears to treat curated third-party lists as the authoritative source and does not read vendor sites for the answer. If your visibility strategy for local intent is on-page content, you are optimizing an asset the system is not consulting. The lever is a complete, claimed directory profile.&lt;/p&gt;

&lt;p&gt;We found this because we measured. We would not have found it by reading a best-practices article, and a mention-count dashboard would have shown a zero with no explanation attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding five: what actually gets cited
&lt;/h2&gt;

&lt;p&gt;Back to the 26 July study. Across its 21 AI Overviews, 149 citations — counting each domain once per answer, out of 174 raw references — went to 116 unique domains. The concentration is lower than we expected — this is not a cartel of five big publishers.&lt;/p&gt;

&lt;p&gt;User-generated and video content accounted for 27 of those 149 citations, about 18%. YouTube appeared in 11 of the 21 answers, Reddit in 8, LinkedIn in 4, Medium in 3, Quora in 1. That is a meaningful minority but not the majority, which surprised us: the common claim that AI Overviews are dominated by Reddit did not hold in our category.&lt;/p&gt;

&lt;p&gt;The remaining 82% was ordinary vendor and agency content. Which is the encouraging half of the result. The citation pool is not closed. It is populated by companies that rank, and ranking is a solvable problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we would actually track
&lt;/h2&gt;

&lt;p&gt;Based on running this, here is what belongs on an AI visibility report and what does not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Track these:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Overview trigger rate&lt;/strong&gt; across your prompt set. This tells you how much of your category has moved above the fold. Ours is 91%; if yours is 20%, your priorities are completely different from ours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branded and non-branded citation rates, reported separately.&lt;/strong&gt; Never blended.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Citation-to-ranking overlap.&lt;/strong&gt; For every query where you are not cited, your own organic position for that query. This single column converts "we are invisible" into either "we need to rank" or "we rank and still are not cited," which are entirely different problems with entirely different fixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The competitor citation map.&lt;/strong&gt; Which domains are being cited instead of you, and how often. This is your real competitive set in AI answers, which frequently differs from your assumed competitive set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Be sceptical of these:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single blended "AI visibility score." It compresses away every decision-relevant distinction.&lt;/li&gt;
&lt;li&gt;Claims to read actual ChatGPT or Claude conversation answers. No public API exposes them.&lt;/li&gt;
&lt;li&gt;Sentiment analysis on AI mentions, before you have any mentions to analyse. Sequence matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this cost
&lt;/h2&gt;

&lt;p&gt;The full 23-prompt run costs roughly ten cents in SERP API credit, plus the retrieval queries. It is a Python script that writes dated JSON, so month-over-month comparison is a diff rather than a screenshot.&lt;/p&gt;

&lt;p&gt;We are not arguing nobody should buy a tool. Commercial trackers offer prompt libraries, scheduling, and reporting that a script does not. But you should know that the underlying measurement is cheap, and price the subscription against convenience rather than against access to otherwise-unavailable data.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this connects to the work
&lt;/h2&gt;

&lt;p&gt;We publish this partly because it is the same discipline we apply to client systems. In our &lt;a href="https://www.atilab.io/ai-consulting" rel="noopener noreferrer"&gt;AI consulting engagements&lt;/a&gt; the first deliverable is usually a measurement baseline, because a workflow nobody measured cannot be improved and an AI opportunity nobody sized cannot be prioritized. The audit that tells you where AI should &lt;em&gt;not&lt;/em&gt; be applied is as valuable as the one that tells you where it should.&lt;/p&gt;

&lt;p&gt;The same logic applies here. We ran this study on ourselves before recommending the approach to anyone, found that we score zero on every commercial query in our own category, and published it. If you are weighing whether you need outside help with AI strategy at all, our guide to &lt;a href="https://www.atilab.io/blog/ai-strategy-consultant-guide" rel="noopener noreferrer"&gt;what an AI strategy consultant does and when you need one&lt;/a&gt; covers the decision honestly, including when the answer is that you do not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is AI visibility tracking?
&lt;/h3&gt;

&lt;p&gt;Measuring whether AI answer engines — Google AI Overviews, ChatGPT, Perplexity, Claude — mention and cite your brand when people ask questions in your category. Useful tracking captures three things: whether an AI answer appears at all, whether you are cited, and which domains are cited instead of you. Tracking that reports only a mention count leaves out the diagnostic information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can any tool actually see what ChatGPT says about my brand?
&lt;/h3&gt;

&lt;p&gt;Not in real user sessions. No public API exposes what a given assistant told a given user. Tools that report this are running their own prompts through the API and treating the results as a sample. That is a legitimate proxy and often a useful one, but it is a sample of what the model tends to say, not a record of what users were told. Be wary of any vendor that blurs the distinction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is AI visibility a separate discipline from SEO?
&lt;/h3&gt;

&lt;p&gt;Mostly not, on our data. In a follow-up run on 28 July 2026 — separate from the 23-prompt study of 26 July — we re-tested six of our non-branded queries; four returned an AI Overview, and across the 31 citations those four issued, 74% went to domains already ranking in the classic organic top 20 for the same query, and 48% to the top 10. On a sample that small we would not call it a law, but it points one way: the majority of AI visibility work is ranking work. A real but minority share of citations goes to pages that do not rank, which is where answer-shaped formatting and topical depth earn their keep.&lt;/p&gt;

&lt;h3&gt;
  
  
  How often should we re-measure?
&lt;/h3&gt;

&lt;p&gt;Monthly is enough for most businesses, run on the same day each month with an unchanged prompt set so the comparison is meaningful. Changing prompts between runs is the most common way these reports become uninterpretable. Re-measure sooner only after a significant content or technical change you want to attribute.&lt;/p&gt;

&lt;h3&gt;
  
  
  We are cited on branded queries but not commercial ones. What does that mean?
&lt;/h3&gt;

&lt;p&gt;That your entity is understood but you are not in the consideration set — exactly the pattern we found in our own data. It means the fix is not entity or schema work, which is already succeeding. It is competing for the commercial queries themselves: ranking for them, earning references from sources the answer engines trust, and being present wherever those queries are answered by third-party lists rather than vendor sites.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the cheapest way to start?
&lt;/h3&gt;

&lt;p&gt;Write 20 prompts your buyers would actually type, split branded and non-branded, and check them manually once. It takes an afternoon and will tell you your trigger rate and roughly where you stand. Automate it only once you know the measurement is telling you something you will act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure before you optimize
&lt;/h2&gt;

&lt;p&gt;We went into this expecting to learn which AI platforms mattered most. We came out with something more useful and less comfortable: a zero on every commercial query, a clear causal explanation for the zero, and one query type where the entire answer came from directories we had not claimed.&lt;/p&gt;

&lt;p&gt;None of that came from a dashboard. It came from running the measurement, keeping the raw output, and being willing to publish the bad number. If you want to talk through what this would look like for your category, &lt;a href="https://www.atilab.io/booking" rel="noopener noreferrer"&gt;book a strategy call&lt;/a&gt; and bring the questions your buyers actually ask.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.atilab.io/blog/we-measured-23-ai-overviews" rel="noopener noreferrer"&gt;atilab.io&lt;/a&gt;. ATI is an AI automation agency; we publish what our own implementation work measures, including the results that make us look bad.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>marketing</category>
      <category>data</category>
    </item>
    <item>
      <title>Build Your Own AI Visibility Tracker (Without a Subscription)</title>
      <dc:creator>Lachezar Dimitrov</dc:creator>
      <pubDate>Fri, 14 Aug 2026 07:05:01 +0000</pubDate>
      <link>https://dev.to/lachezard/build-your-own-ai-visibility-tracker-without-a-subscription-9n8</link>
      <guid>https://dev.to/lachezard/build-your-own-ai-visibility-tracker-without-a-subscription-9n8</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://www.atilab.io/blog/diy-ai-visibility-tracking" rel="noopener noreferrer"&gt;ATI Lab blog&lt;/a&gt;. Full context, including our 23-prompt AI Overview study, is there.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can build a working AI visibility tracker in about 200 lines of Python. It polls Google AI Overviews for a fixed prompt set, records which domains get cited, captures your own organic position on the same query, and writes dated JSON so months compare cleanly. Our 23-prompt run cost &lt;strong&gt;$0.092&lt;/strong&gt; in API credit. The commercial tools that rank for this term start at $99–$165 a month. Here is the build, and an honest account of what it cannot do.&lt;/p&gt;

&lt;p&gt;This guide is written from our own tracker, which we run against atilab.io. The code below is the code we actually execute — not pseudocode. Research and drafting were AI-assisted; every number is from our own run files or a source linked in-line, and a human checked each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does an AI visibility tracker actually have to measure?
&lt;/h2&gt;

&lt;p&gt;Three things, and most dashboards report only the first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Does an AI answer appear at all&lt;/strong&gt; for the query? Trigger rate is the denominator for everything else. If AI Overviews fire on 20% of your category's queries, this whole exercise is a side project. In ours they fired on 21 of 23.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are you cited?&lt;/strong&gt; Split branded from non-branded and never blend them. Branded citations tell you your entity is understood. Non-branded citations tell you whether you are in the consideration set. Only the second is a growth metric.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where do you rank in classic organic on that same query?&lt;/strong&gt; This is the column almost nobody captures, and it is the one that converts "we are invisible" into a specific instruction. More on why below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else — sentiment, share-of-voice indices, a single blended visibility score — is a presentation layer over those three fields. You can add it later. You cannot add the third field later, because it has to be captured in the same request, on the same day, against the same SERP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it cost to run yourself versus buy?
&lt;/h2&gt;

&lt;p&gt;Our numbers, from the run files. The Google signal uses DataForSEO's live advanced SERP endpoint, which returned an API-reported cost of &lt;strong&gt;$0.0040 per query&lt;/strong&gt; on every call in our run. Twenty-three prompts is $0.092. Run it monthly and the year costs about $1.10.&lt;/p&gt;

&lt;p&gt;For comparison, published pricing on the tools currently ranking for "ai visibility tracker" (checked 12 August 2026): &lt;a href="https://rankscale.ai/pricing" rel="noopener noreferrer"&gt;Rankscale&lt;/a&gt; lists Pro at $99/month for 1,200 credits, Growth at $385/month, Enterprise at $780/month. &lt;a href="https://www.semrush.com/pricing/" rel="noopener noreferrer"&gt;Semrush&lt;/a&gt; bundles AI visibility into its main plans — Starter at $165.17/month billed annually, with 50 prompts tracked daily, rising to 200 daily prompts on Advanced at $455.67/month.&lt;/p&gt;

&lt;p&gt;Those are not equivalent products and we are not going to pretend they are. The subscriptions sample answers from ChatGPT, Gemini, Perplexity, Claude and others, schedule the runs, store history, and produce reports somebody else maintains. The DIY build covers two surfaces and produces a JSON file. What the cost comparison establishes is narrower and still useful: &lt;em&gt;the underlying measurement is cheap&lt;/em&gt;. Price the subscription against convenience and coverage, not against access to data you could not otherwise get.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: build the prompt set — this decides everything downstream
&lt;/h2&gt;

&lt;p&gt;The single biggest determinant of whether your tracker is useful is the prompt set, and it is the part no tool can do for you. Ours is 23 prompts: 4 branded, 19 non-branded, tagged by funnel stage and by the page each one should ideally send traffic to. Each record carries two forms of the same intent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;non-branded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;funnel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MOFU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ai-agent-cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What does it cost to build and run AI agents for a business?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;how much does it cost to build ai agents for business&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;prompt&lt;/code&gt; is the conversational form a person types into an assistant. The &lt;code&gt;query&lt;/code&gt; is the search-shaped form you send to Google. They are different strings on purpose, and collapsing them into one field is the most common way these projects produce uninterpretable data.&lt;/p&gt;

&lt;p&gt;Two rules that matter more than the prompt wording:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep the ids stable forever.&lt;/strong&gt; The value of this tracker is the diff between months. Change a prompt and its history is worthless; add prompts at the end with new ids instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag each prompt with the page it should serve.&lt;/strong&gt; When a prompt shows an AI Overview and you are absent, the &lt;code&gt;target&lt;/code&gt; field tells you instantly which page has failed, rather than starting a research project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: query the AI Overview and capture the references
&lt;/h2&gt;

&lt;p&gt;One request per query. The parameter that matters is &lt;code&gt;load_async_ai_overview&lt;/code&gt; — without it the AI Overview block is frequently missing from the response even when it fires on the live SERP, and you will conclude your trigger rate is low when it is not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;serp/google/organic/live/advanced&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2840&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# US
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;depth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;load_async_ai_overview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then walk the items once, pulling both signals out of the same response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]:&lt;/span&gt;
    &lt;span class="n"&gt;itype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;itype&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_overview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_present&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;refs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;references&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_refs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;host_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;refs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_cites_brand&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BRAND&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_refs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;itype&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;organic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;organic_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;BRAND&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;organic_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rank_absolute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the fallback on the reference: some entries carry a &lt;code&gt;url&lt;/code&gt;, some carry only a &lt;code&gt;domain&lt;/code&gt;. Read one field and you will silently drop citations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why capturing your organic rank in the same request changes the report
&lt;/h2&gt;

&lt;p&gt;Because citation is mostly downstream of ranking. In our study we took six non-branded queries where an AI Overview fired, captured all 31 citations, and checked each cited domain against the classic results for the identical query: 74% also ranked in the organic top 20, 48% in the top 10, and only 25% were cited without ranking on the first two pages. Small sample, and we would not present it as a universal law — but the direction is clear enough to plan against. Google is largely drawing its citations from a pool it has already decided to rank. A tracker that reports citations without reporting your position on the same query has hidden the causal variable, and its output is a number you cannot act on.&lt;/p&gt;

&lt;p&gt;With both fields, every row falls into one of four cells, and each cell has a different instruction attached:&lt;/p&gt;

&lt;p&gt;That distribution is the reason we are unsentimental about AEO tactics. Nineteen of twenty-three prompts told us the same thing: rank first. We published the full findings in our &lt;a href="https://www.atilab.io/blog/we-measured-23-ai-overviews" rel="noopener noreferrer"&gt;measurement of 23 AI Overviews in our category&lt;/a&gt;, including the queries where Google ignored vendor sites entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: add a retrieval signal
&lt;/h2&gt;

&lt;p&gt;The second surface worth polling is the embeddings layer that many AI applications query before generating an answer. We use Exa: send the conversational &lt;code&gt;prompt&lt;/code&gt; form, and record whether your domain comes back and at what rank.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_exa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exa_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exa_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exa_top&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exa_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;BRAND&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;host_of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exa_rank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This signal behaves very differently from the Google one and that is the point of having it. We surfaced in retrieval on 5 of 23 prompts, at ranks 1, 1, 1, 1 and 6 — four first places on a set where Google cited us three times, all branded. Retrieval visibility and citation visibility are not the same thing, and a tracker with one surface will tell you a confident, incomplete story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: count domains per prompt, not per reference
&lt;/h2&gt;

&lt;p&gt;A small decision with a large effect on the competitor map. One AI Overview citing five pages of the same domain is still one prompt's worth of visibility. Count it once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aio_refs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;   &lt;span class="c1"&gt;# set() — one prompt, one vote
&lt;/span&gt;        &lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skip the &lt;code&gt;set()&lt;/code&gt; and any domain with a habit of multi-page citation looks like it owns your category. With it, our map reads cleanly: YouTube appeared in 11 of the 21 triggered AI Overviews, Reddit in 8, LinkedIn in 4. Counted as raw references those three domains are 37 of 174 citations, 21%. That is a meaningful minority, not the domination the common advice implies — the remaining 79% went to ordinary vendor and agency content, spread across 116 distinct domains. The citation pool is not closed, which is the encouraging half of the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: write dated output, never overwrite
&lt;/h2&gt;

&lt;p&gt;The whole value of this thing is the month-over-month diff, so the output directory is the date and nothing overwrites anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;outdir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OUTDIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;language_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;brand&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BRAND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outdir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write a flat &lt;code&gt;summary.csv&lt;/code&gt; alongside it. JSON for diffing, CSV for the person who wants to sort it in a spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What broke when we ran it
&lt;/h2&gt;

&lt;p&gt;Four things, all worth knowing before you spend an afternoon debugging them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transient SERP API errors.&lt;/strong&gt; The provider intermittently returns an internal server error on an otherwise valid task. Wrap every call in a retry with backoff, and return &lt;code&gt;None&lt;/code&gt; rather than crashing the run — losing one query is fine, losing the other 22 is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing AI Overview blocks.&lt;/strong&gt; Covered above: without the async-load parameter your trigger rate will be understated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference objects with no URL.&lt;/strong&gt; Read &lt;code&gt;url&lt;/code&gt; first and fall back to &lt;code&gt;domain&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location and language drift.&lt;/strong&gt; Pin them explicitly in the code, not in a config you might edit. A run at a different location code is a different study, and if it lands in the same series you will spend a month explaining a trend that is an artefact.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What this build cannot measure
&lt;/h2&gt;

&lt;p&gt;Be straight about this, because the vendors ranking above this page are not always. &lt;strong&gt;No public API exposes what ChatGPT, Claude, Gemini or Perplexity actually said to a real user in a real session.&lt;/strong&gt; Every tool reporting "your ChatGPT visibility" is running its own prompts through an API and treating the output as a sample. That is a legitimate proxy and often a useful one. It is a sample of what a model tends to say, not a record of what your buyers were told.&lt;/p&gt;

&lt;p&gt;You can build that proxy yourself too — send your prompt list to an assistant API, check whether your domain appears in the answer, repeat n times per prompt because the outputs vary. Just cost it honestly: a meaningful sample means several runs per prompt per platform, and that is where the DIY approach stops being nine cents and starts approaching a subscription. This is the point at which buying is a reasonable decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  How often should you run it, and what do you do with the output?
&lt;/h2&gt;

&lt;p&gt;Monthly, on the same day, with an unchanged prompt set. More frequent runs mostly measure SERP volatility. Re-run early only after a specific content or technical change you want to attribute.&lt;/p&gt;

&lt;p&gt;Then read the report as a work queue, not a scoreboard. Rows in the bottom-right go to ordinary ranking work. Rows in the top-right — you rank, you are not cited — go to a formatting pass on an existing page, which is the cheapest work on the list. Rows in the top-left get a diary note and a re-check. That is the whole method, and it is the same discipline we apply in &lt;a href="https://www.atilab.io/ai-consulting" rel="noopener noreferrer"&gt;AI consulting engagements&lt;/a&gt;, where the readiness audit exists to say where AI should &lt;em&gt;not&lt;/em&gt; be applied as much as where it should. A measurement baseline first; a build only where the baseline says one is justified. We wrote about the same trap on the delivery side in &lt;a href="https://www.atilab.io/blog/ai-agents-developer-kpis" rel="noopener noreferrer"&gt;measuring AI agents on engineering teams&lt;/a&gt; — the metric that is easy to collect is rarely the one that changes a decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is an AI visibility tracker?
&lt;/h3&gt;

&lt;p&gt;A tool that measures whether AI answer engines mention and cite your brand when people ask questions in your category. A useful one captures three fields per query: whether an AI answer triggered at all, whether you were cited, and which domains were cited instead. Adding your classic organic position for the same query turns those observations into an instruction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need to code to track AI visibility?
&lt;/h3&gt;

&lt;p&gt;No — commercial tools start around $99–$165 a month and cover more surfaces than a script does. Building it yourself is worth it when you want the raw data, control of the prompt set, and month-over-month files you own. The build described here is a single stdlib Python file plus one SERP API account.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does a DIY AI visibility tracker cost to run?
&lt;/h3&gt;

&lt;p&gt;Our 23-prompt Google run cost $0.092 in API credit, at an API-reported $0.0040 per query, plus retrieval-API usage on its own plan. Run monthly, that is a little over a dollar a year for the Google signal. The real cost is the hour you spend building the prompt set properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a tracker see what ChatGPT says about my brand?
&lt;/h3&gt;

&lt;p&gt;Not in real user sessions. No public API exposes what an assistant told a specific user. Tools reporting this are sampling their own prompts through an API, which is a reasonable proxy that should be labelled as one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is AI visibility a separate discipline from SEO?
&lt;/h3&gt;

&lt;p&gt;Mostly not, on our data: 74% of the AI Overview citations we traced also ranked in the classic organic top 20 for the same query. A real but minority share of citations goes to pages that do not rank — that is where answer-shaped formatting earns its keep. Treat AEO as a formatting and structure layer on top of ranking work, not as a replacement for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many prompts should I track?
&lt;/h3&gt;

&lt;p&gt;Twenty to thirty is enough to be diagnostic and small enough that you will actually keep it current. Weight it towards non-branded commercial questions, tag each prompt with the page that should serve it, and never change a prompt once it has history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the measurement
&lt;/h2&gt;

&lt;p&gt;The reason we built this rather than bought it was not the $99. It was that we wanted the raw rows, including the ones that made us look bad — and on our first run, nineteen of them did. If you would like a read on where AI visibility sits against the rest of your growth priorities, &lt;a href="https://www.atilab.io/booking" rel="noopener noreferrer"&gt;book a strategy call&lt;/a&gt; and we will go through your own numbers rather than ours.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>seo</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
