<?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: dbott23</title>
    <description>The latest articles on DEV Community by dbott23 (@dbott23).</description>
    <link>https://dev.to/dbott23</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%2F4042896%2Fa437e052-1cf2-4067-9c0b-0e87ee484948.png</url>
      <title>DEV Community: dbott23</title>
      <link>https://dev.to/dbott23</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dbott23"/>
    <language>en</language>
    <item>
      <title>How Booking.com anti-bot works — and how I built a scraper that gets past it</title>
      <dc:creator>dbott23</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:48:27 +0000</pubDate>
      <link>https://dev.to/dbott23/how-bookingcom-anti-bot-works-and-how-i-built-a-scraper-that-gets-past-it-h9h</link>
      <guid>https://dev.to/dbott23/how-bookingcom-anti-bot-works-and-how-i-built-a-scraper-that-gets-past-it-h9h</guid>
      <description>&lt;p&gt;Booking.com serves over 28 million listings and is one of the most valuable sources of hotel review data on the internet. It's also one of the hardest sites to scrape. I spent a week figuring out why standard approaches fail and how to get the data anyway. Here's everything I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why headless Chromium fails immediately
&lt;/h2&gt;

&lt;p&gt;The first blocker is AWS WAF sitting in front of Booking.com's CDN. It fingerprints incoming browser connections at the TLS handshake level — JA3/JA4 signatures, HTTP/2 header ordering, cipher suite preferences — and Chromium's fingerprint is on the blocklist. You get a 403 before the page even loads.&lt;/p&gt;

&lt;p&gt;The fix is &lt;a href="https://github.com/daijro/camoufox" rel="noopener noreferrer"&gt;camoufox&lt;/a&gt;, a Firefox fork that patches the browser's fingerprinting surface. Firefox's TLS fingerprint passes the WAF check where Chromium's doesn't. But camoufox alone isn't enough — Booking.com's WAF also checks whether the browser is running in a headless environment. The solution is Xvfb (X Virtual Framebuffer): spin up a virtual display, launch Firefox inside it, and the browser believes it's rendering to a real screen.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="n"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Xvfb&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;:99&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;-screen&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;0&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;1280x720x24&lt;/span&gt;&lt;span class="sh"&gt;'&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;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DISPLAY&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:99&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;# now launch camoufox — it sees a real display
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This combination passes the WAF challenge and gets you the page load.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second blocker: the browser context kill switch
&lt;/h2&gt;

&lt;p&gt;You've passed the WAF. The page starts loading. And then, about 18–30 seconds later, the browser context closes. Booking.com's client-side JavaScript runs fingerprinting checks after the page hydrates and closes the connection if it doesn't like what it sees.&lt;/p&gt;

&lt;p&gt;My first approach was to wait for JS hydration and parse the DOM. That doesn't work — the window closes before hydration finishes. My second attempt was to intercept XHR/fetch calls for the review API. Those calls never fire either.&lt;/p&gt;

&lt;p&gt;The key insight came from looking at what actually arrives in the HTTP response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real data is in the initial HTML response
&lt;/h2&gt;

&lt;p&gt;Booking.com uses a micro-frontend architecture called Capla, built on Apollo Client. When the server renders the page, it embeds the full Apollo GraphQL cache as JSON inside &lt;code&gt;&amp;lt;script type="application/json"&amp;gt;&lt;/code&gt; tags in the HTML. This includes hotel metadata, amenities, pricing, photos — &lt;strong&gt;and reviews&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The response body is about 1.7MB. Your browser downloads it in full the moment the server responds, before any JavaScript runs, before any anti-bot checks fire. The data you want is already there.&lt;/p&gt;

&lt;p&gt;The trick is to capture it. Playwright's &lt;code&gt;response.body()&lt;/code&gt; lets you read the raw HTTP response body from inside a network event listener:&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;raw_html_bodies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;booking.com/hotel/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&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="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;body_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20_000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# skip tiny redirect responses
&lt;/span&gt;                &lt;span class="n"&gt;raw_html_bodies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body_str&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="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# don't wait for page load — use the captured body immediately
&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_html_bodies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You register the listener before navigation, collect the bodies as they arrive, then take the largest one. By the time the anti-bot kill switch fires, you already have everything you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parsing the Apollo cache
&lt;/h2&gt;

&lt;p&gt;The Apollo cache is a flat object where keys are GraphQL entity identifiers like &lt;code&gt;FeaturedReview:123456&lt;/code&gt; and values are the actual objects. References between objects use &lt;code&gt;{"__ref": "TypeName:id"}&lt;/code&gt; pointers.&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;_parse_capla_json_scripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&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;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;script&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&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;start&lt;/span&gt; &lt;span class="o"&gt;==&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;break&lt;/span&gt;
        &lt;span class="n"&gt;tag_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tag_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;tag_end&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="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag_end&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tag_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&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;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blob&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="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_build_apollo_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_scripts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cache&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;blob&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed_scripts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="c1"&gt;# Apollo cache keys look like "TypeName:id"
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;v&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;__typename&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find the actual reviews, filter cache entries by &lt;code&gt;__typename&lt;/code&gt;. Booking.com's Capla schema uses &lt;code&gt;FeaturedReview&lt;/code&gt; for the reviews embedded in the SSR response. Each object has &lt;code&gt;positiveText&lt;/code&gt;, &lt;code&gt;negativeText&lt;/code&gt;, &lt;code&gt;score&lt;/code&gt;, &lt;code&gt;roomType&lt;/code&gt; (as a &lt;code&gt;__ref&lt;/code&gt; pointer), &lt;code&gt;completedAt&lt;/code&gt; (Unix timestamp), and traveller info.&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;REVIEW_TYPENAMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;frozenset&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FeaturedReview&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;GuestReview&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;PropertyReview&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;Review&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;reviews&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;apollo_cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&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;v&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;__typename&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;REVIEW_TYPENAMES&lt;/span&gt;
    &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&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;positiveText&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="n"&gt;v&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;negativeText&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;roomType&lt;/code&gt; ref resolves by looking up the key in the same cache:&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;resolve_ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;val&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;cache&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;val&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__ref&lt;/span&gt;&lt;span class="sh"&gt;"&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;val&lt;/span&gt;

&lt;span class="n"&gt;room_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resolve_ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review&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;roomType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;room_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;room_obj&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;name&lt;/span&gt;&lt;span class="sh"&gt;"&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;room_obj&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;p&gt;Each hotel page embeds approximately 10 featured reviews — Booking.com's curated selection of the most recent and highest-quality reviews shown to prospective guests. Getting the full review history (thousands of reviews per hotel) would require hitting Booking.com's internal GraphQL API, which is a different problem.&lt;/p&gt;

&lt;p&gt;For competitive intelligence, sentiment analysis, and reputation monitoring use cases, the featured reviews are the most useful anyway — they're the ones influencing booking decisions.&lt;/p&gt;

&lt;p&gt;The full implementation is available as a ready-to-run actor on Apify: &lt;a href="https://apify.com/dbott23/booking-reviews-scraper" rel="noopener noreferrer"&gt;Booking.com Hotel Reviews Scraper&lt;/a&gt;. Pass one or more hotel URLs, get a clean dataset of reviewer name, score, positive/negative text, room type, trip purpose, and date. Priced at $1 per 1,000 reviews extracted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS WAF blocks Chromium&lt;/td&gt;
&lt;td&gt;Use camoufox (Firefox) + Xvfb virtual display&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anti-bot JS closes browser in 18–30s&lt;/td&gt;
&lt;td&gt;Capture raw HTTP response body before JS runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data isn't in DOM, no API calls fire&lt;/td&gt;
&lt;td&gt;Parse Apollo/Capla SSR JSON cache from &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;roomType&lt;/code&gt; is a &lt;code&gt;__ref&lt;/code&gt; pointer&lt;/td&gt;
&lt;td&gt;Build a flat cache lookup and resolve references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;completedAt&lt;/code&gt; is a Unix timestamp&lt;/td&gt;
&lt;td&gt;&lt;code&gt;datetime.fromtimestamp(ts, tz=timezone.utc).strftime("%Y-%m-%d")&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern — WAF bypass with a fingerprint-clean browser, capture before hydration, parse SSR cache — applies to any site built on Apollo Client with server-side rendering. More and more modern travel and e-commerce sites use this stack, so it's a pattern worth knowing.&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>python</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Export All Google Maps Reviews to a Spreadsheet (2026 Guide)</title>
      <dc:creator>dbott23</dc:creator>
      <pubDate>Mon, 03 Aug 2026 02:18:41 +0000</pubDate>
      <link>https://dev.to/dbott23/google-maps-reviews-scraper-export-to-csv-excel-18j</link>
      <guid>https://dev.to/dbott23/google-maps-reviews-scraper-export-to-csv-excel-18j</guid>
      <description>&lt;h1&gt;
  
  
  How to Export All Google Maps Reviews to a Spreadsheet (2026 Guide)
&lt;/h1&gt;

&lt;p&gt;If you've ever needed &lt;strong&gt;every review for a business on Google Maps&lt;/strong&gt; — your own locations, a competitor's, or a whole list of them — you've probably discovered there's no "Export to CSV" button. Google gives you an infinite-scroll list on the page and nothing else.&lt;/p&gt;

&lt;p&gt;This guide covers three ways to get those reviews into a spreadsheet, from most tedious to most painless, and is honest about the trade-offs of each.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can actually get per review
&lt;/h2&gt;

&lt;p&gt;Before the how, here's the data that's publicly visible on each review and worth capturing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reviewer name and whether they're a &lt;strong&gt;Google Local Guide&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Star rating (1–5)&lt;/li&gt;
&lt;li&gt;Review text and the date&lt;/li&gt;
&lt;li&gt;The business owner's response (if any)&lt;/li&gt;
&lt;li&gt;The place's overall rating and total review count&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's enough for reputation tracking, competitor analysis, or sentiment work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Copy-paste by hand
&lt;/h2&gt;

&lt;p&gt;For a handful of reviews on one business, just scroll and copy. It's free and takes zero setup.&lt;/p&gt;

&lt;p&gt;It also falls apart fast: Google lazy-loads reviews as you scroll, dates are relative ("2 months ago"), owner responses are collapsed, and doing this across 10 locations — or 500 reviews — is a soul-crushing afternoon. Fine for a quick look, useless at any scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: Build your own scraper
&lt;/h2&gt;

&lt;p&gt;If you write code, your instinct is to script it. Here's the honest reality of that path in 2026:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google blocks datacenter IPs.&lt;/strong&gt; A naive &lt;code&gt;requests&lt;/code&gt; or Puppeteer script gets a challenge page or empty results within a page or two. You'll need &lt;strong&gt;residential proxies&lt;/strong&gt;, which cost money and add complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The reviews live behind an infinite-scroll feed&lt;/strong&gt; that only loads as you scroll a specific container — and Google periodically changes the underlying markup, so your selectors break without warning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The UI is localized to the proxy's country&lt;/strong&gt;, so a proxy that exits in France hands you a French page and your English-text selectors silently return nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is insurmountable — it's just a genuine, ongoing maintenance job. If you scrape Google Maps for a living, build it. If you need reviews in a spreadsheet by this afternoon, it's overkill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 3: Use a maintained scraper (no code)
&lt;/h2&gt;

&lt;p&gt;The pragmatic middle ground is a hosted actor that already solves the proxy + anti-bot + maintenance problem, so you just hand it a URL and get structured data back. I built one on the &lt;a href="https://apify.com" rel="noopener noreferrer"&gt;Apify&lt;/a&gt; platform for exactly this: &lt;strong&gt;&lt;a href="https://apify.com/dbott23/google-maps-reviews-scraper" rel="noopener noreferrer"&gt;Google Maps Reviews Scraper&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the full workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Grab the place URL.&lt;/strong&gt; Open &lt;a href="https://www.google.com/maps" rel="noopener noreferrer"&gt;Google Maps&lt;/a&gt;, search the business, click it, and copy the URL from your address bar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paste it into the actor&lt;/strong&gt; (&lt;code&gt;placeUrls&lt;/code&gt;). Add as many businesses as you want — it processes them in one run.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;how many reviews per place&lt;/strong&gt; (up to 500) and a &lt;strong&gt;sort order&lt;/strong&gt; — newest, most relevant, highest, or lowest rating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run it.&lt;/strong&gt; It uses residential proxies to load the real page in English, opens the reviews tab, scrolls the feed, and extracts every review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; the dataset as &lt;strong&gt;CSV, Excel, or JSON&lt;/strong&gt; — one click.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A row of output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"place_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Eiffel Tower"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"place_rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reviewer_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Smith"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"is_local_guide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-07-30"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Absolutely stunning views from the top."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"owner_response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thank you for visiting!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What it costs
&lt;/h3&gt;

&lt;p&gt;It's pay-per-use at &lt;strong&gt;$4 per 1,000 reviews&lt;/strong&gt; — no subscription. So pulling 500 reviews each from 3 locations (1,500 reviews) runs about &lt;strong&gt;$6&lt;/strong&gt;. For a one-off competitive teardown or a monthly reputation export, that's cheaper than the hour you'd spend copy-pasting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which should you pick?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Best option&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10 reviews, one business, once&lt;/td&gt;
&lt;td&gt;Copy-paste&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You scrape Google daily and want full control&lt;/td&gt;
&lt;td&gt;Build your own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A clean spreadsheet across several businesses, today&lt;/td&gt;
&lt;td&gt;Hosted scraper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need a Google API key?&lt;/strong&gt; No — Google's official Places API caps reviews at five per business, which is why scraping the public page is the only way to get them all. No key required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this allowed?&lt;/strong&gt; You're collecting publicly visible data. As always, use scraped data responsibly and in line with applicable terms and privacy law.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I track reviews over time?&lt;/strong&gt; Yes — re-run on a schedule and diff the output to watch ratings and sentiment move week over week.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you try the &lt;a href="https://apify.com/dbott23/google-maps-reviews-scraper" rel="noopener noreferrer"&gt;Google Maps Reviews Scraper&lt;/a&gt;, I'd genuinely value your feedback — it's new, and honest notes on what to add next help a lot.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>datascience</category>
      <category>python</category>
      <category>automation</category>
    </item>
    <item>
      <title>How to Check if ChatGPT Recommends Your Brand (And Track It Weekly)</title>
      <dc:creator>dbott23</dc:creator>
      <pubDate>Thu, 30 Jul 2026 15:10:48 +0000</pubDate>
      <link>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4hh0</link>
      <guid>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4hh0</guid>
      <description>&lt;p&gt;Most SEO tools track your Google rankings. None of them tell you whether ChatGPT, Perplexity, or Gemini recommends you when a potential customer asks "what's the best [your product category]?"&lt;/p&gt;

&lt;p&gt;That's a problem, because an estimated 1 in 3 product searches now start in an AI chat interface — not Google. And the brands getting recommended didn't get there by accident.&lt;/p&gt;

&lt;p&gt;In this post I'll show you exactly how to check where your brand stands with AI engines, and how to track it automatically week over week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why AI Recommendations Are Different From SEO
&lt;/h2&gt;

&lt;p&gt;Traditional SEO is about signals Google understands: backlinks, domain authority, title tags, page speed.&lt;/p&gt;

&lt;p&gt;AI recommendations work differently. Large language models are trained on the public web — Reddit threads, G2 reviews, GitHub repos, comparison articles, Stack Overflow answers, news coverage. &lt;strong&gt;The brands that appear most authoritatively across that content are the ones that get recommended.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This creates a different playbook. You can have a 90 Domain Rating and still be invisible to ChatGPT if your brand isn't discussed where AI training data comes from.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Run a Manual Check First
&lt;/h2&gt;

&lt;p&gt;Before automating anything, get a baseline by hand. Open ChatGPT, Perplexity, and Gemini and ask the kinds of questions your customers actually ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What's the best [your product category] for [use case]?"&lt;/li&gt;
&lt;li&gt;"Compare [your brand] vs [competitor 1] vs [competitor 2]"&lt;/li&gt;
&lt;li&gt;"What tools do people use for [problem you solve]?"&lt;/li&gt;
&lt;li&gt;"What are alternatives to [market leader]?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Were you mentioned at all?&lt;/li&gt;
&lt;li&gt;Were you first, middle, or last?&lt;/li&gt;
&lt;li&gt;What were competitors' names that came up instead?&lt;/li&gt;
&lt;li&gt;Did any specific URLs get cited as sources?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do this across 3–5 queries per engine. It's tedious once, which is why you automate it after.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Automate with the AI Brand Visibility Tracker
&lt;/h2&gt;

&lt;p&gt;Doing this manually every week across 3 engines × multiple queries takes 30–45 minutes and produces inconsistent data (different chat sessions, different results).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;AI Brand Visibility Tracker&lt;/a&gt; runs this automatically. You give it your brands, your competitors, and your queries — it runs them across ChatGPT, Perplexity, Gemini, and Claude and returns structured data you can actually act on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it measures per brand × query × engine:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;brand_mentioned&lt;/code&gt; — was your brand named at all? (true/false)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mention_count&lt;/code&gt; — how many times in the response&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;position_score&lt;/code&gt; — where in the response (10 = first mention, 0 = not mentioned)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;share_of_voice&lt;/code&gt; — your mentions ÷ all brand mentions in that response&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cited_domains&lt;/code&gt; — which URLs the AI pulled as sources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample input:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Acme CRM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Salesforce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HubSpot"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"best CRM for small business"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"affordable alternatives to Salesforce"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"CRM with the best email integration"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perplexity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output (one row):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Acme CRM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"best CRM for small business"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand_mentioned"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mention_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"share_of_voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cited_domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"g2.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"capterra.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reddit.com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it once manually, export to CSV, and you have your baseline. Schedule it weekly and you have a trend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Check Which URLs Are Being Cited
&lt;/h2&gt;

&lt;p&gt;Brand mentions and citation sources are two different things. You can be &lt;em&gt;mentioned&lt;/em&gt; by name without any of your web pages being &lt;em&gt;cited as a source&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Being cited is more valuable — it signals your content is considered authoritative and sends direct referral traffic when AI answers include clickable sources (Perplexity, Bing Chat, etc.).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;AI Citation Auditor&lt;/a&gt; checks exactly this: whether your domain appears in the citation lists that AI engines return for your target queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"yourdomain.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"best project management software"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"jira alternatives for small teams"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why audit competitors too:&lt;/strong&gt;&lt;br&gt;
Multiple domains share the same underlying API call, so auditing 5 domains costs the same as auditing 1. Check your top 3–4 competitors at the same time to see which of their pages are getting cited — those are your content gap targets.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4: Interpret the Results
&lt;/h2&gt;

&lt;p&gt;Here's what to look for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High position score, low citation rate:&lt;/strong&gt;&lt;br&gt;
You're being recommended by name but your content isn't being surfaced as authoritative. Focus on getting more of your pages cited: publish more detailed comparison content, get listed on G2/Capterra, answer questions on Reddit in your niche.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cited but not mentioned:&lt;/strong&gt;&lt;br&gt;
Your content is being used as a source but you're not being named as a brand recommendation. This usually means you're ranking for informational content but not product/brand content. Create more "brand + use case" pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Competitor dominates both:&lt;/strong&gt;&lt;br&gt;
They've built more authoritative coverage across the web. Look at which specific pages of theirs get cited — those are the content types that work for your category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mention rate drops week over week:&lt;/strong&gt;&lt;br&gt;
Something changed. Either a competitor increased their coverage, or you had a public negative event (bad reviews, a controversy). Check what's new in your category.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 5: What Actually Moves AI Recommendations
&lt;/h2&gt;

&lt;p&gt;Based on how LLMs are trained, these are the content investments most likely to improve your position:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Get on G2 and Capterra&lt;/strong&gt; — these are heavily represented in LLM training data. Reviews there get read by millions of users and indexed everywhere.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Answer questions on Reddit in your niche&lt;/strong&gt; — Reddit is a major training source. Being the helpful, authoritative answer in r/SaaS, r/entrepreneur, or your category subreddit builds the coverage LLMs learn from.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Get listed on comparison sites&lt;/strong&gt; — "Acme vs Salesforce", "Best CRM tools" roundups get cited by AI engines constantly. Reach out to sites that publish these.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Publish detailed comparison content on your own site&lt;/strong&gt; — "How Acme compares to [competitor]" pages rank well and get cited.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Get mentioned in newsletters&lt;/strong&gt; — Industry newsletters are often scraped and included in training data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this is new content strategy. The difference is tracking whether it's working for AI visibility specifically — which the manual approach can't do at scale.&lt;/p&gt;


&lt;h2&gt;
  
  
  Running It on a Schedule
&lt;/h2&gt;

&lt;p&gt;The AI Brand Visibility Tracker stores previous run data and automatically calculates week-over-week deltas. So if your &lt;code&gt;mention_rate&lt;/code&gt; went from 0.33 to 0.41 after a content push, you'll see &lt;code&gt;+0.08&lt;/code&gt; in the output.&lt;/p&gt;

&lt;p&gt;To schedule it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the actor on Apify&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Saved tasks&lt;/strong&gt; → &lt;strong&gt;Save current input as task&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click the task → &lt;strong&gt;Schedule&lt;/strong&gt; → set to weekly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll get a fresh dataset every week without touching anything.&lt;/p&gt;


&lt;h2&gt;
  
  
  Putting It Together
&lt;/h2&gt;

&lt;p&gt;The workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Week 1: Run baseline — brands, competitors, 5+ queries, all 3 engines
Week 2+: Scheduled run every Monday morning
         → Compare to previous run automatically
         → Note any drops/gains
         → Identify which competitor pages are getting cited
         → Create content to fill the gaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same thing enterprise GEO agencies charge $2,000/month to do manually in spreadsheets. At $50 per 1,000 checks, a weekly run tracking 3 brands × 5 queries × 3 engines = 45 checks = $2.25/week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;AI Brand Visibility Tracker on Apify&lt;/a&gt; — track brand mentions across ChatGPT, Perplexity, Gemini, Claude&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;AI Citation Auditor on Apify&lt;/a&gt; — check if your domain is cited as a source by AI engines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both run on Apify's free tier for first runs. Pay per check, no subscription.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions or feedback? Drop them in the comments — still early days for GEO tracking and curious what queries others are running.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>seo</category>
      <category>marketing</category>
    </item>
    <item>
      <title>How to Check if ChatGPT Recommends Your Brand — and Track It Weekly</title>
      <dc:creator>dbott23</dc:creator>
      <pubDate>Thu, 23 Jul 2026 02:47:15 +0000</pubDate>
      <link>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4lka</link>
      <guid>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4lka</guid>
      <description>&lt;p&gt;An estimated one in three purchase research sessions now starts with an AI assistant rather than Google. When your potential customer types "what's the best project management tool for startups?" into ChatGPT, your brand either shows up — or it doesn't.&lt;/p&gt;

&lt;p&gt;Traditional SEO dashboards track your Google rankings. None of them track whether AI recommends you.&lt;/p&gt;

&lt;p&gt;This post shows you how to check your AI visibility in under five minutes, and how to set up automatic weekly tracking so you're always in the loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why AI recommendations are different from Google rankings
&lt;/h2&gt;

&lt;p&gt;When someone searches Google, they get a list of ten blue links and decide for themselves. When someone asks ChatGPT or Perplexity, they get a single confident recommendation — and most of them follow it.&lt;/p&gt;

&lt;p&gt;The mechanic is different too. Google ranks pages. AI assistants draw on everything they've been trained on and everything the web-search mode returns in real time. A brand that's well-documented across Reddit, blog posts, GitHub, and review sites gets recommended more often than one with a polished website but thin presence elsewhere.&lt;/p&gt;

&lt;p&gt;There are two distinct things you can measure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Brand mentions&lt;/strong&gt; — Does the AI &lt;em&gt;name&lt;/em&gt; your brand in response to buyer-intent queries?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Citation rank&lt;/strong&gt; — Does the AI &lt;em&gt;cite your website&lt;/em&gt; as a source in its footnotes?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both matter. A brand mentioned but not cited is being recommended but not treated as authoritative. A site cited but not mentioned is being used as evidence for a competitor's recommendation. The goal is both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Run a manual spot check
&lt;/h2&gt;

&lt;p&gt;Start with the simplest possible version: open ChatGPT and Perplexity and ask the questions your customers ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose 3–5 buyer-intent queries.&lt;/strong&gt; Good examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What's the best [category] tool for [use case]?"&lt;/li&gt;
&lt;li&gt;"How do I [problem your product solves]?"&lt;/li&gt;
&lt;li&gt;"What do companies use for [your space]?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a project management tool, you might ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What project management software should a 20-person startup use?"&lt;/li&gt;
&lt;li&gt;"Best free project management tool for remote teams"&lt;/li&gt;
&lt;li&gt;"Alternatives to Jira for small teams"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run each query on ChatGPT (with web search on), Perplexity, and Gemini. Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was your brand mentioned at all?&lt;/li&gt;
&lt;li&gt;How early was it mentioned? First recommendation, third, or buried in a list?&lt;/li&gt;
&lt;li&gt;Was your website listed in the citations/sources?&lt;/li&gt;
&lt;li&gt;Which competitors got mentioned instead?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you a snapshot. The problem with doing it manually is it takes 20+ minutes per check, you can't easily track it over time, and you forget the results by next week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Automate it with an Apify actor
&lt;/h2&gt;

&lt;p&gt;To track this systematically — across multiple queries, multiple engines, and week over week — I built an actor that does the heavy lifting: the &lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;AI Brand Visibility Tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It runs real buyer-intent queries across ChatGPT, Perplexity, Gemini, and Claude, then returns structured data for each check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Asana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"best project management tool for small teams"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand_mentioned"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mention_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"share_of_voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"competitor_mentions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Trello"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Monday.com"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ClickUp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cited_domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"g2.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blog.asana.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"response_snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"For small teams, Asana offers a generous free tier..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;position_score&lt;/code&gt; is 1–10: 10 means your brand was named first, 1 means it was mentioned last, 0 means it wasn't mentioned at all. &lt;code&gt;share_of_voice&lt;/code&gt; is your mentions divided by total brand mentions in the response — a direct measure of how dominant you are in that answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting it up takes about 2 minutes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;actor page on Apify&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt; (no credit card needed for your first runs)&lt;/li&gt;
&lt;li&gt;Enter your brand name and up to 5 competitor names&lt;/li&gt;
&lt;li&gt;Paste in 3–5 queries your customers actually use&lt;/li&gt;
&lt;li&gt;Select which engines to check: ChatGPT, Perplexity, Gemini, Claude&lt;/li&gt;
&lt;li&gt;Click Start&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The run takes a few minutes and outputs a dataset you can download as CSV or connect to Google Sheets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Set up weekly tracking
&lt;/h2&gt;

&lt;p&gt;A one-time check tells you where you stand today. Weekly tracking tells you whether your content and PR efforts are actually moving the needle.&lt;/p&gt;

&lt;p&gt;In the Apify console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Actors → Schedules → New schedule&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Point it at the AI Brand Visibility Tracker with your saved input&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;trackTrends: true&lt;/code&gt; (this is the default)&lt;/li&gt;
&lt;li&gt;Choose a weekly cadence — I run it every Monday morning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every subsequent run automatically compares to the previous one and adds trend deltas to the &lt;code&gt;SUMMARY&lt;/code&gt; output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Asana"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mention_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.17&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"avg_position_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rising &lt;code&gt;mention_rate&lt;/code&gt; means AI is recommending you more often. A rising &lt;code&gt;position_score&lt;/code&gt; means you're being named earlier — more prominently — in the response. A rising &lt;code&gt;share_of_voice&lt;/code&gt; means you're taking ground from competitors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Also check if your site is being cited
&lt;/h2&gt;

&lt;p&gt;Brand mentions and citation links are different signals — and you want both.&lt;/p&gt;

&lt;p&gt;The companion actor is the &lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;AI Citation Auditor&lt;/a&gt;. Instead of tracking brand names, it tracks whether your &lt;em&gt;domain&lt;/em&gt; appears in the structured citation list that engines like Perplexity and ChatGPT return alongside their answers.&lt;/p&gt;

&lt;p&gt;The input is domain names instead of brand names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"yourdomain.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor1.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor2.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"best project management tool for small teams"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perplexity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether your domain was cited at all&lt;/li&gt;
&lt;li&gt;What rank your citation appeared at (rank 1 = first source listed)&lt;/li&gt;
&lt;li&gt;Which specific URL was cited (so you know which content is earning citations)&lt;/li&gt;
&lt;li&gt;How that changes week over week&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One useful property: multiple domains share the same API call. Auditing 5 domains against 3 queries × 3 engines costs the same as auditing 1 domain — the actor checks all domains against each response.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually improves your AI visibility?
&lt;/h2&gt;

&lt;p&gt;Based on what I've seen from running these checks across various brands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Being discussed across multiple sources.&lt;/strong&gt; AI assistants synthesise from many inputs. A brand with Reddit threads, G2 reviews, blog posts, and GitHub repos mentioning it in context gets pulled into more responses than a brand with only a polished website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being cited by authoritative domains.&lt;/strong&gt; G2, Capterra, Trustpilot, and niche industry blogs that get cited by AI are worth being listed on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear, specific positioning.&lt;/strong&gt; Brands that are easy to describe in a sentence ("the Notion alternative built for engineers") get recommended more precisely than brands with vague positioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being named in comparison content.&lt;/strong&gt; "X vs Y" articles, "best tools for Z" lists — AI engines love this format because it's already structured as a recommendation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What doesn't move the needle as much as you'd hope:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having a well-optimised website alone&lt;/li&gt;
&lt;li&gt;Meta descriptions and title tags (these are Google signals, not AI signals)&lt;/li&gt;
&lt;li&gt;Domain authority in the traditional SEO sense&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tracking this for clients
&lt;/h2&gt;

&lt;p&gt;If you're an SEO or GEO agency, this is a straightforward addition to your monthly reporting. Run the actor with a unique &lt;code&gt;trendKey&lt;/code&gt; per client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ClientBrand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"competitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Competitor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Competitor2"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trendKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"client-acme-july-2026"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each client's trend series is stored separately. You get a clean week-over-week delta report you can paste into any client deck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it tracks&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI Brand Visibility Tracker&lt;/td&gt;
&lt;td&gt;Brand mentions, position score, share of voice&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;apify.com/dbott23/ai-brand-visibility-tracker&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Citation Auditor&lt;/td&gt;
&lt;td&gt;Domain citations, citation rank, cited URLs&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;apify.com/dbott23/ai-citation-auditor&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both are pay-per-check — no subscription. First runs are free on Apify's free tier.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions? Drop them in the comments. I'm also tracking which queries and engines tend to surface brands most reliably — happy to share what I've found.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>chatgpt</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Check if ChatGPT Recommends Your Brand — and Track It Weekly</title>
      <dc:creator>dbott23</dc:creator>
      <pubDate>Thu, 23 Jul 2026 02:43:44 +0000</pubDate>
      <link>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4716</link>
      <guid>https://dev.to/dbott23/how-to-check-if-chatgpt-recommends-your-brand-and-track-it-weekly-4716</guid>
      <description>&lt;p&gt;An estimated one in three purchase research sessions now starts with an AI assistant rather than Google. When your potential customer types "what's the best project management tool for startups?" into ChatGPT, your brand either shows up — or it doesn't.&lt;/p&gt;

&lt;p&gt;Traditional SEO dashboards track your Google rankings. None of them track whether AI recommends you.&lt;/p&gt;

&lt;p&gt;This post shows you how to check your AI visibility in under five minutes, and how to set up automatic weekly tracking so you're always in the loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why AI recommendations are different from Google rankings
&lt;/h2&gt;

&lt;p&gt;When someone searches Google, they get a list of ten blue links and decide for themselves. When someone asks ChatGPT or Perplexity, they get a single confident recommendation — and most of them follow it.&lt;/p&gt;

&lt;p&gt;The mechanic is different too. Google ranks pages. AI assistants draw on everything they've been trained on and everything the web-search mode returns in real time. A brand that's well-documented across Reddit, blog posts, GitHub, and review sites gets recommended more often than one with a polished website but thin presence elsewhere.&lt;/p&gt;

&lt;p&gt;There are two distinct things you can measure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Brand mentions&lt;/strong&gt; — Does the AI &lt;em&gt;name&lt;/em&gt; your brand in response to buyer-intent queries?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Citation rank&lt;/strong&gt; — Does the AI &lt;em&gt;cite your website&lt;/em&gt; as a source in its footnotes?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both matter. A brand mentioned but not cited is being recommended but not treated as authoritative. A site cited but not mentioned is being used as evidence for a competitor's recommendation. The goal is both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Run a manual spot check
&lt;/h2&gt;

&lt;p&gt;Start with the simplest possible version: open ChatGPT and Perplexity and ask the questions your customers ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose 3–5 buyer-intent queries.&lt;/strong&gt; Good examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What's the best [category] tool for [use case]?"&lt;/li&gt;
&lt;li&gt;"How do I [problem your product solves]?"&lt;/li&gt;
&lt;li&gt;"What do companies use for [your space]?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a project management tool, you might ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What project management software should a 20-person startup use?"&lt;/li&gt;
&lt;li&gt;"Best free project management tool for remote teams"&lt;/li&gt;
&lt;li&gt;"Alternatives to Jira for small teams"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run each query on ChatGPT (with web search on), Perplexity, and Gemini. Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was your brand mentioned at all?&lt;/li&gt;
&lt;li&gt;How early was it mentioned? First recommendation, third, or buried in a list?&lt;/li&gt;
&lt;li&gt;Was your website listed in the citations/sources?&lt;/li&gt;
&lt;li&gt;Which competitors got mentioned instead?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you a snapshot. The problem with doing it manually is it takes 20+ minutes per check, you can't easily track it over time, and you forget the results by next week.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Automate it with an Apify actor
&lt;/h2&gt;

&lt;p&gt;To track this systematically — across multiple queries, multiple engines, and week over week — I built an actor that does the heavy lifting: the &lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;AI Brand Visibility Tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It runs real buyer-intent queries across ChatGPT, Perplexity, Gemini, and Claude, then returns structured data for each check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Asana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"best project management tool for small teams"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand_mentioned"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mention_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"share_of_voice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"competitor_mentions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Trello"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Monday.com"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ClickUp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cited_domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"g2.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blog.asana.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"response_snippet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"For small teams, Asana offers a generous free tier..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;position_score&lt;/code&gt; is 1–10: 10 means your brand was named first, 1 means it was mentioned last, 0 means it wasn't mentioned at all. &lt;code&gt;share_of_voice&lt;/code&gt; is your mentions divided by total brand mentions in the response — a direct measure of how dominant you are in that answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting it up takes about 2 minutes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;actor page on Apify&lt;/a&gt; and click &lt;strong&gt;Try for free&lt;/strong&gt; (no credit card needed for your first runs)&lt;/li&gt;
&lt;li&gt;Enter your brand name and up to 5 competitor names&lt;/li&gt;
&lt;li&gt;Paste in 3–5 queries your customers actually use&lt;/li&gt;
&lt;li&gt;Select which engines to check: ChatGPT, Perplexity, Gemini, Claude&lt;/li&gt;
&lt;li&gt;Click Start&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The run takes a few minutes and outputs a dataset you can download as CSV or connect to Google Sheets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Set up weekly tracking
&lt;/h2&gt;

&lt;p&gt;A one-time check tells you where you stand today. Weekly tracking tells you whether your content and PR efforts are actually moving the needle.&lt;/p&gt;

&lt;p&gt;In the Apify console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Actors → Schedules → New schedule&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Point it at the AI Brand Visibility Tracker with your saved input&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;trackTrends: true&lt;/code&gt; (this is the default)&lt;/li&gt;
&lt;li&gt;Choose a weekly cadence — I run it every Monday morning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every subsequent run automatically compares to the previous one and adds trend deltas to the &lt;code&gt;SUMMARY&lt;/code&gt; output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Asana"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mention_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.67&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.17&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"avg_position_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"current"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"previous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"delta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rising &lt;code&gt;mention_rate&lt;/code&gt; means AI is recommending you more often. A rising &lt;code&gt;position_score&lt;/code&gt; means you're being named earlier — more prominently — in the response. A rising &lt;code&gt;share_of_voice&lt;/code&gt; means you're taking ground from competitors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Also check if your site is being cited
&lt;/h2&gt;

&lt;p&gt;Brand mentions and citation links are different signals — and you want both.&lt;/p&gt;

&lt;p&gt;The companion actor is the &lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;AI Citation Auditor&lt;/a&gt;. Instead of tracking brand names, it tracks whether your &lt;em&gt;domain&lt;/em&gt; appears in the structured citation list that engines like Perplexity and ChatGPT return alongside their answers.&lt;/p&gt;

&lt;p&gt;The input is domain names instead of brand names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domains"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"yourdomain.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor1.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"competitor2.com"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"best project management tool for small teams"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"chatgpt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perplexity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gemini"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether your domain was cited at all&lt;/li&gt;
&lt;li&gt;What rank your citation appeared at (rank 1 = first source listed)&lt;/li&gt;
&lt;li&gt;Which specific URL was cited (so you know which content is earning citations)&lt;/li&gt;
&lt;li&gt;How that changes week over week&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One useful property: multiple domains share the same API call. Auditing 5 domains against 3 queries × 3 engines costs the same as auditing 1 domain — the actor checks all domains against each response.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually improves your AI visibility?
&lt;/h2&gt;

&lt;p&gt;Based on what I've seen from running these checks across various brands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Being discussed across multiple sources.&lt;/strong&gt; AI assistants synthesise from many inputs. A brand with Reddit threads, G2 reviews, blog posts, and GitHub repos mentioning it in context gets pulled into more responses than a brand with only a polished website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being cited by authoritative domains.&lt;/strong&gt; G2, Capterra, Trustpilot, and niche industry blogs that get cited by AI are worth being listed on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear, specific positioning.&lt;/strong&gt; Brands that are easy to describe in a sentence ("the Notion alternative built for engineers") get recommended more precisely than brands with vague positioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being named in comparison content.&lt;/strong&gt; "X vs Y" articles, "best tools for Z" lists — AI engines love this format because it's already structured as a recommendation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What doesn't move the needle as much as you'd hope:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Having a well-optimised website alone&lt;/li&gt;
&lt;li&gt;Meta descriptions and title tags (these are Google signals, not AI signals)&lt;/li&gt;
&lt;li&gt;Domain authority in the traditional SEO sense&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tracking this for clients
&lt;/h2&gt;

&lt;p&gt;If you're an SEO or GEO agency, this is a straightforward addition to your monthly reporting. Run the actor with a unique &lt;code&gt;trendKey&lt;/code&gt; per client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ClientBrand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"competitors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Competitor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Competitor2"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trendKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"client-acme-july-2026"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each client's trend series is stored separately. You get a clean week-over-week delta report you can paste into any client deck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it tracks&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI Brand Visibility Tracker&lt;/td&gt;
&lt;td&gt;Brand mentions, position score, share of voice&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apify.com/dbott23/ai-brand-visibility-tracker" rel="noopener noreferrer"&gt;apify.com/dbott23/ai-brand-visibility-tracker&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Citation Auditor&lt;/td&gt;
&lt;td&gt;Domain citations, citation rank, cited URLs&lt;/td&gt;
&lt;td&gt;&lt;a href="https://apify.com/dbott23/ai-citation-auditor" rel="noopener noreferrer"&gt;apify.com/dbott23/ai-citation-auditor&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both are pay-per-check — no subscription. First runs are free on Apify's free tier.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions? Drop them in the comments. I'm also tracking which queries and engines tend to surface brands most reliably — happy to share what I've found.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>chatgpt</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
