Irmu
Guides14 minIrmu Engineering

ChatGPT Brand Monitoring: Track What AI Tells Your Customers (2026)

Build your own LLM visibility tracker: run a fixed set of buyer questions through ChatGPT on a schedule, record whether your brand is mentioned, where, and which sources are cited — with Python, Node and SQL.

Why ChatGPT answers are now a sales channel

A growing share of buyers ask ChatGPT "what's the best X for Y" before they ever open a search engine. The answer they get is a short list, a few sentences of reasoning and a handful of cited sources. If your product isn't in that list, you don't get a second chance on page two — there is no page two.

The problem is that nobody sees those answers except the person who asked. Your web analytics won't show a lost mention, and the answer can change between Monday and Friday, or between Germany and the US, without anything on your side changing. The only way to know what ChatGPT says about you is to ask it, the same way, repeatedly, and keep the results.

  • Visibility: is your brand mentioned at all for the questions buyers ask?
  • Position: are you the first recommendation or the fifth?
  • Framing: what does ChatGPT say you are good or bad at — and is it true?
  • Sources: which pages does it cite, and are any of them yours?
  • Competitors: who shows up instead of you, and where?

What an LLM visibility tracker actually does

Strip away the dashboards and every "AI visibility" or "ChatGPT rank tracker" product does the same four things: keep a list of prompts, ask them on a schedule, parse the answer for brand names and citations, and chart the result over time. You can build that in an afternoon if you have a reliable way to ask ChatGPT and get a structured answer back.

That last part is the hard bit. The OpenAI API is not the same as the ChatGPT app: the app browses the web, shows citations, renders product lists and is personalised by location. Answers from the raw model API often differ from what a real user sees in chatgpt.com. If you want to know what customers see, you have to ask through the website.

Measure the surface your customers use. A model API answer is a proxy; a chatgpt.com answer asked from the customer's country is the real thing.

Asking ChatGPT through Irmu

Irmu's `GET /chatgpt` endpoint opens ChatGPT in a real browser, types your prompt, waits for the full streamed answer and returns it as JSON nodes — paragraphs, headings, lists, tables and product lists — each with the sources ChatGPT showed beside it. No OpenAI key is involved. It costs a flat 30 credits per prompt, and `country` (plus optional `city`) changes where the question is asked from without changing the price.

The prompt can be up to 1,000 characters. Keep buyer questions short and natural — the way a person would actually type them.

ask.sh
curl -G https://app.irmu.com/api/chatgpt \
  -H "Authorization: Bearer $IRMU_API_KEY" \
  --data-urlencode "prompt=best web scraping API for a small startup" \
  --data-urlencode "country=us"
response.json
{
  "prompt": "best web scraping API for a small startup",
  "conversation": [
    { "role": "user", "message": "best web scraping API for a small startup" },
    {
      "role": "assistant",
      "response": [
        { "type": "paragraph", "text": "Here are some good options…",
          "sources": [{ "attribution": "example.com", "url": "https://example.com/review" }] },
        { "type": "ordered_list", "items": [{ "text": "…" }, { "text": "…" }] }
      ]
    }
  ],
  "credits_charged": 30,
  "credits_remaining": 970,
  "job_id": "0198a9b6-…",
  "status": "done",
  "position": null,
  "error": null
}

Step 1 — Write the prompt set

Your prompt set is your keyword list. Get it wrong and the chart is meaningless. Start from what buyers ask, not from your brand name: "best X for Y", "X alternatives", "X vs Y", "how do I do Z". Include a few prompts that name you directly ("is Acme good for…") to track framing, but keep most of them unbranded — that's where you win or lose new customers.

Twenty to fifty prompts is plenty to start. Freeze the wording: changing a prompt resets its history.

  • Category: "best project management tool for agencies"
  • Alternative: "alternatives to Competitor for small teams"
  • Comparison: "Acme vs Competitor"
  • Problem: "how to track client hours across projects"
  • Branded: "what are the downsides of Acme"

Step 2 — Ask on a schedule and keep everything

Store the full raw answer, not just a score. You'll want to re-parse old answers when you add a competitor to the list or change how you detect mentions. A weekly run is a good default; answers drift, but not hourly.

Answers can take a while. If the endpoint returns `202`, the prompt is paid for and still running: collect it for free from `GET /crawl/{job}`, where the answer arrives under `data.conversation`. A `500` means ChatGPT didn't answer in time — those are refunded (`credits_charged: 0`), so just retry later.

ask_chatgpt.py
import os, time, requests

API = "https://app.irmu.com/api"
HEADERS = {"Authorization": f"Bearer {os.environ['IRMU_API_KEY']}"}

def ask(prompt: str, country: str = "us") -> dict | None:
    res = requests.get(f"{API}/chatgpt", headers=HEADERS,
                       params={"prompt": prompt, "country": country}, timeout=200)
    body = res.json()
    if res.status_code == 500:
        return None                      # not answered, refunded — retry later
    while res.status_code == 202:        # paid, still running: collect for free
        time.sleep(5)
        res = requests.get(f"{API}/crawl/{body['job_id']}", headers=HEADERS, timeout=60)
        body = res.json()
        if res.status_code != 202:
            body["conversation"] = (body.get("data") or {}).get("conversation", [])
    return body

Step 3 — Detect mentions, position and citations

Flatten the assistant's nodes into an ordered list of text chunks, then look for each brand. Position is the index of the first chunk that mentions it — in a list answer, that's effectively its rank. Collect every `sources[].url` as well: citations tell you which pages ChatGPT trusts for this topic, which is your content roadmap.

Use aliases. People and models write "Hub Spot", "HubSpot CRM" and "hubspot.com". Match case-insensitively on word boundaries, and keep the alias list next to the prompt set.

score.js
const BRANDS = {
  acme: ["acme", "acme.io"],
  rival: ["rival", "rival app", "rival.com"],
};

function chunks(nodes) {
  const out = [];
  for (const n of nodes) {
    if (n.text) out.push({ text: n.text, sources: n.sources ?? [] });
    for (const item of n.items ?? []) out.push({ text: item.text ?? JSON.stringify(item), sources: item.sources ?? n.sources ?? [] });
    for (const row of n.rows ?? []) out.push({ text: [].concat(row).join(" "), sources: n.sources ?? [] });
  }
  return out;
}

export function score(answer) {
  const nodes = answer.conversation.find((t) => t.role === "assistant")?.response ?? [];
  const list = chunks(nodes);
  const result = {};
  for (const [brand, aliases] of Object.entries(BRANDS)) {
    const re = new RegExp(`\\b(${aliases.join("|")})\\b`, "i");
    const idx = list.findIndex((c) => re.test(c.text));
    result[brand] = { mentioned: idx >= 0, position: idx >= 0 ? idx + 1 : null };
  }
  result.citations = [...new Set(list.flatMap((c) => c.sources.map((s) => s.url)))];
  return result;
}

Step 4 — Store it so you can chart it

One row per prompt per run, with the raw answer kept alongside. Share of voice is then a simple query: for each week, the percentage of prompts where you were mentioned, and your average position when you were.

schema.sql
create table llm_answers (
  id          bigserial primary key,
  prompt      text not null,
  country     text not null,
  asked_at    timestamptz not null default now(),
  raw         jsonb not null,
  citations   text[] not null default '{}'
);

create table llm_mentions (
  answer_id   bigint references llm_answers(id),
  brand       text not null,
  mentioned   boolean not null,
  position    int
);

-- weekly share of voice
select date_trunc('week', a.asked_at) as week, m.brand,
       round(100.0 * avg(m.mentioned::int), 1) as share_pct,
       round(avg(m.position) filter (where m.mentioned), 1) as avg_position
from llm_mentions m join llm_answers a on a.id = m.answer_id
group by 1, 2 order by 1, 2;

Country matters more than you think

ChatGPT answers depend on where the question comes from. A "best accounting software" question asked from Germany and from the US will often recommend different products, cite different sources and quote different currencies. If you sell in several markets, track each one separately with `country` — it's free on top of the 30 credits.

Don't average countries together. A brand that's first in the US and absent in France doesn't have a 50% share of voice; it has a France problem.

What it costs

Each prompt is 30 credits, whether it's asked from one country or another. So 40 prompts × 2 countries × 4 weekly runs is 320 questions a month, or 9,600 credits. That fits comfortably in the Lite plan's 200,000 monthly credits with plenty left for other work. Prompts that ChatGPT doesn't answer are refunded.

40 prompts × 2 countries × weekly = 9,600 credits a month. Check the pricing page for current plan volumes.

Can you track ads in ChatGPT?

A lot of people searching for "ChatGPT ads" want to know whether competitors are paying to appear in answers. The honest answer for this guide: `/chatgpt` returns the answer nodes and citations exactly as the page showed them. We haven't documented a separate field for sponsored placements, so we don't promise that ads are captured or labelled.

What you can do today is keep the raw answers. If sponsored content appears in the answer and is rendered as part of it, it will be in your stored nodes, and you can re-parse history once you know what it looks like. We'll update this guide if we add explicit ad detection.

Turning the data into action

The citation list is the most useful output. If ChatGPT keeps citing three review sites and a Reddit thread for your category, those are the pages to be on. If it describes your product with an outdated limitation, fix the public pages that say so. Then watch whether the next runs change.

Start small: ten prompts, one country, one week. If the numbers surprise you — and they usually do — expand from there.

Start building with Irmu today

200 free credits every month, no card required. Every API, every integration, one key.