AI Visibility Setup: Onboard a Client Brand Step by Step

AI visibility setup in six steps: intake, site read, brand brief, competitors, prompt review and first run, plus the setup mistakes our own data exposed.

· BugViso Team

14 min read

AI visibility setup takes six steps: intake, a read of the client's site, a brand brief you correct, at least three competitors, a reviewed prompt set, and the first run. The steps are quick. What isn't quick is undoing a bad setup, because the brief, the competitor list and the prompt set become the measuring instrument for months. Every change after the first run breaks the trend.

Our own brand's setup shows where that bites: a pricing summary that caused a false accuracy alarm, a topic too thin to measure and a single "alternatives" prompt. By the end of this post you'll have the six steps, the check for each, the fixes we'd make to our own setup in hindsight, and a pre-flight script that inspects a client's site before you start.

Data used: BugViso's own brand setup in its AI Visibility Tracker: the site read re-run with the tracker's production crawl code against bugviso.com on 2026-10-29, the 50-prompt set frozen before the runs, and 400 answers from ChatGPT, Gemini, Perplexity and Claude on 2026-10-20 that exposed the setup issues described here.

The Six Steps at a Glance

Each step has one thing to check, and skipping that check costs accuracy later.

StepYou provideCheck before moving onWhat goes wrong if you skip it
1. IntakeWebsite, brand name, market, languageThe market is where buyers are, not where the company is registeredAnswers are localised to the wrong country
2. Site readNothing; the tracker reads the sitePricing and product pages were found and readableThe brief is built without prices
3. Brand briefCorrectionsEvery plan, price and limit is listed exactlyAccuracy checks raise false alarms or miss errors
4. Competitors3+ rivals with domains and aliasesThey're the brands you lose deals toThe benchmark compares you with the wrong market
5. PromptsReview and editsMix, topics and wording match how buyers askMonths of data on questions nobody asks
6. First runA schedule and report recipientsThe run completed on every engineA broken baseline

Step 1: Intake, Four Fields

Intake needs the website, the brand name, the market and the language buyers ask in. The market sets the location the engines search from where their APIs support it; the language sets the language of every prompt.

Pick the market by where the buyers are. A company registered in one country that sells mainly to another should be tracked in the second. If buyers are spread across several markets, start with the one that brings the most revenue, because the same question can return different brands in different countries.

Step 2: The Site Read

The tracker reads the client's key pages to draft the brief; if a fact isn't on a crawlable page, the brief won't have it. We re-ran BugViso's production crawl code against our own site to show what it collects:

Measurebugviso.com, 2026-10-29
robots.txtRead first; nothing blocked
SitemapFound
Requests made16
Pages kept15: home, pricing, about, contact, sales contact, scan, the agency page, the GEO page and 7 feature pages
Time6.4 seconds
Raw page text81,203 characters
Digest sent on to drafting13,672 characters (83% smaller)

Two rules decide what's kept. Pages are scored by what buyers check (pricing highest, then product and feature pages, then about, comparisons and contact), with a bonus for pages linked from the main navigation. Blog posts, legal pages, logins and carts are never read. Then repeated navigation and footer text is dropped from every page, so the digest is mostly facts.

So before you start, check the client's pricing and product pages are public, linked from the navigation and readable without JavaScript. The pre-flight script below does that in about a second. If prices only appear after a quote form, write them into the brief by hand in step 3.

Step 3: Correct the Brand Brief

The brief is the most important five minutes of setup, because it becomes the fact sheet every answer is checked against. BugViso pre-fills it from the site read: category, a one-sentence description, what the brand offers, other names, who it's for, what sets it apart, and facts AI should get right.

Correct three things above all:

  1. List every plan with its exact price and limit. Not a range. Our first brief summarised pricing as "$19 (20 scans) to $149 (300 scans)". When engines correctly described our $49 tier, the checker couldn't confirm it and flagged it. Our pricing page shows 27 distinct dollar amounts (monthly and annual prices, per-scan rates, credit packs), so a summary was always going to lose something.
  2. Add other names. Product names, abbreviations and common misspellings, so mentions aren't missed.
  3. Write the facts buyers check. Refund window, free tier, limits, guarantees, locations served. These feed the accuracy check; anything missing comes back "unverified", as we found when we analysed 369 unverified AI claims.

💡 Rule of thumb: read the brief as if you were a buyer checking an AI answer against it. If the brief can't settle "how much is the middle plan?" or "can I get a refund?", it isn't finished.

Step 4: Choose the Competitors

Track at least three competitors, chosen from the deals the client loses, not from the biggest names in the category. The tracker suggests competitors from the site read; the client's sales team knows better.

For each competitor, enter the domain (it's how the tracker recognises their own pages among citations) and any other names. Then test each name for ambiguity. A rival called "Atlas" or "Signal" can be matched in answers that never mention the company, which inflates its share of voice. Our post on brand name ambiguity in AI answers shows how to test a name in a few minutes.

We tracked five competitors. Five was a good number: enough to see the category's shape, few enough that every name was a real deal-loss rival.

Step 5: Review the Prompt Set

The prompt set is the instrument; review it for mix, topics and wording before anything runs. BugViso drafts 50 prompts from the brief by default and checks them in code. Here's the set we froze for our own brand:

Part of the setPromptsRule
Discovery (no brand named)35About 70% of the set
— learn / consider / purchase10 / 15 / 10About 30 / 40 / 30
Branded10About 20%
Comparison (brand vs a named rival)5About 10%
Topics74–8 topics, at least 3 prompts each

Check four things:

  1. Wording a buyer would type. Plain questions, 6 to 25 words, no insider jargon. Our guide to buyer prompts for AI search has the tests.
  2. Topic size. Our accessibility topic had 3 prompts, the minimum. After two runs it held 24 answers, enough only to say "zero mentions, interval up to 13.8%". Give important topics 5 or more prompts.
  3. Alternatives prompts. We had one "alternatives to a rival" prompt. Its 8 answers couldn't separate a displacement rate of 1 in 8 from 3 in 8. Write one per main rival buyers switch from.
  4. Branded share. Keep branded and comparison prompts near 30% combined, so the unbranded visibility score stays meaningful.

Step 6: Freeze, Run and Schedule

Freeze the set, run once, check the run's health, then set the schedule. The first run is the baseline. Check that every engine returned answers and that no engine failed on many calls; an outage on day one makes every later comparison look like growth.

Then set the cadence by what you report. Daily runs pooled into weekly reports are the practical default for active work; weekly runs suit monthly reporting. Add report recipients if the account team wants the daily email.

After the freeze, resist editing prompts. Every edit creates a new version, and trends restart from it. Collect the edits you want and apply them together at a reporting boundary, as described in prompt set versioning.

Run a Pre-Flight Check on the Client's Site

This script checks the things setup depends on, without any AI calls: text in the raw homepage HTML, whether robots.txt blocks the main AI crawlers, how many URLs the sitemap lists, which key pages exist (pricing, product, about, contact, locations, case studies), and the distinct prices on the pricing page. Standard library only.

python
#!/usr/bin/env python3
"""Pre-flight for AI visibility tracking setup: can AI search crawlers read the client's site,
which pages a brand brief will be built from, and which facts to confirm before prompts are drafted.

Usage: python3 geo_intake_check.py example.com
Standard library only. robotparser is a close approximation of RFC 9309, not an exact match.
"""
import re, sys, urllib.request, urllib.robotparser
from html import unescape
from urllib.parse import urljoin, urlparse

UA = "Mozilla/5.0 (compatible; geo-intake-check/1.0)"
AI_BOTS = ["OAI-SearchBot", "GPTBot", "PerplexityBot", "ClaudeBot", "Claude-SearchBot", "Google-Extended", "Bingbot"]
KEY_PAGES = {"pricing": "pricing|plans|prices", "product/features": "features?|products?|services|solutions",
             "about": "about|company|team", "contact": "contact", "locations": "locations?|stores?|branches",
             "case studies": "case-studies|customers|work|portfolio"}

def get(url, limit=1_500_000):
    try:
        req = urllib.request.Request(url, headers={"User-Agent": UA})
        with urllib.request.urlopen(req, timeout=15) as r:
            return r.status, r.read(limit).decode("utf-8", "replace")
    except Exception as e:
        return getattr(e, "code", None), ""

def visible_text(html):
    html = re.sub(r"(?is)<(script|style|noscript|svg)[^>]*>.*?</\1>", " ", html)
    return re.sub(r"\s+", " ", unescape(re.sub(r"(?s)<[^>]+>", " ", html))).strip()

def main(domain):
    origin = "https://" + domain.removeprefix("https://").removeprefix("http://").strip("/")
    status, home = get(origin + "/")
    print(f"# AI visibility intake: {origin}\n\nhomepage: HTTP {status}, {len(visible_text(home)):,} chars of text in raw HTML"
          + ("  ✗ little text without JavaScript" if len(visible_text(home)) < 500 else ""))
    rp = urllib.robotparser.RobotFileParser(origin + "/robots.txt")
    rs, robots = get(origin + "/robots.txt")
    rp.parse(robots.splitlines() if rs and rs < 400 else [])
    blocked = [b for b in AI_BOTS if not rp.can_fetch(b, origin + "/")]
    print("AI crawlers blocked from the homepage: " + (", ".join(blocked) + "  ✗" if blocked else "none ✓"))
    sitemaps = re.findall(r"(?im)^sitemap:\s*(\S+)", robots) or [origin + "/sitemap.xml"]
    urls = []
    for sm in sitemaps[:3]:
        s, xml = get(sm)
        locs = re.findall(r"<loc>\s*([^<\s]+)\s*</loc>", xml)
        for child in [l for l in locs if l.endswith(".xml")][:5]:   # one level of sitemap index
            locs += re.findall(r"<loc>\s*([^<\s]+)\s*</loc>", get(child)[1])
        urls += [l for l in locs if not l.endswith(".xml")]
    links = [urljoin(origin + "/", h) for h in re.findall(r'href=["\']([^"\'#?]+)', home)]
    pages = {u.rstrip("/") for u in urls + links if urlparse(u).netloc.removeprefix("www.") == urlparse(origin).netloc.removeprefix("www.")}
    print(f"sitemap URLs: {len(urls):,}; same-site pages known: {len(pages):,}\n\n## Pages the brief will lean on")
    found = {}
    for kind, pat in KEY_PAGES.items():
        hits = sorted((p for p in pages if re.match(rf"^/({pat})(/|$)", urlparse(p).path)), key=lambda p: (p.count("/"), len(p)))
        found[kind] = hits
        print(f"- {kind}: {hits[0] if hits else 'not found'}" + (f" (+{len(hits) - 1})" if len(hits) > 1 else ""))
    print("\n## Facts to confirm in the brief")
    if found["pricing"]:
        text = visible_text(get(found["pricing"][0])[1])
        vals = sorted({float(m.replace(",", "")) for m in re.findall(r"[$€£]\s?(\d[\d,]*(?:\.\d+)?)", text)})
        shown = ", ".join(f"{v:g}" for v in vals) or "none in raw HTML ✗"
        print(f"- {len(vals)} distinct amounts on the pricing page: {shown}  -> list every plan with its price and limit")
    else:
        print("- no pricing page: write the price facts into the brief by hand, or engines will guess")
    print("- 3+ competitors the client actually loses deals to, with their domains and any common-word names")
    print("- the market (country) and language buyers ask in")

if __name__ == "__main__":
    main(sys.argv[1] if len(sys.argv) > 1 else sys.exit(__doc__))

On our own site:

text
homepage: HTTP 200, 23,192 chars of text in raw HTML
AI crawlers blocked from the homepage: none ✓
sitemap URLs: 285; same-site pages known: 298

## Pages the brief will lean on
- pricing: https://bugviso.com/pricing
- product/features: https://bugviso.com/features (+8)
- about: https://bugviso.com/about
- contact: https://bugviso.com/contact
- locations: not found
- case studies: not found

Python's urllib.robotparser is close to RFC 9309 but not identical, so treat a "blocked" line as a prompt to check the rules by hand. Crawler names change; OpenAI documents its current ones on its crawler overview.

How BugViso Handles AI Visibility Setup

Setting up a brand in BugViso's AI Visibility Tracker asks for the website, name, market and language. The tracker reads robots.txt, finds the sitemap, fetches the homepage and its key pages politely (15 pages in total), condenses them into a digest, and stops at a pre-filled brand brief for you to correct: category, description, offerings, other names, audience, differentiators, facts AI should get right, and suggested competitors. You confirm at least three competitors before any prompt is drafted.

The prompts are then drafted from the confirmed brief and checked in code for mix, topic sizes, length, duplicates and leading wording. The first set waits on a "Review your prompts" step, where you add, edit, move or delete by topic or as a list, and starting tracking freezes the set and runs the first measurement. Runs are manual by default and can be scheduled daily, weekly or monthly. The setup flow is described on the AI visibility tracker page.

Setup Mistakes We'd Avoid Next Time

A pricing range in the brief. It caused a false accuracy alarm on a correct claim. List every plan.

Minimum-size topics for things that matter. Three prompts per topic is the floor, not the target, for topics you'll report on.

One alternatives prompt. Too few answers to measure displacement. One per main rival.

Choosing competitors by fame. The benchmark is only useful against the rivals buyers actually compare you with.

Editing prompts in week one. Every edit restarts the trend. Batch changes for a reporting boundary.

Frequently Asked Questions

How do I set up AI visibility tracking for a client?

Enter the client's site, name, market and language; let the tracker read the site; correct the brand brief so every plan, price and key fact is exact; confirm at least three competitors the client loses deals to; review the drafted buyer prompts; then freeze the set and run the first measurement.

How many prompts and competitors should I track?

Fifty prompts and three to five competitors is a solid default: about 35 unbranded, 10 branded and 5 comparison prompts across 4 to 8 topics. Give topics you'll report on at least five prompts each.

What information does AI visibility tracking need from the client?

The website, the brand's other names, the market and language buyers use, the competitors they lose deals to, and the exact facts buyers check: plans, prices, limits, refund terms and locations.

Why does the brand brief matter for AI visibility?

It's the fact sheet every AI answer is checked against. A vague brief makes the accuracy check flag true claims or miss wrong ones. Our first brief's price range caused a false alarm on a correct $49-plan claim.

Can I change prompts after AI visibility tracking starts?

Yes, but each change creates a new prompt version, and comparisons restart from it. Collect edits and apply them together at a reporting boundary.

Spend the Setup Time on the Brief

Of the six setup steps, the brief and the competitor list are the ones that quietly decide whether months of data mean anything, so correct them with the client before the first run. BugViso's AI visibility tracking stops at the brief on first setup for exactly that reason.

Written by

· BugViso Team

Kazi writes BugViso’s guides on website audits, Core Web Vitals, technical SEO, accessibility and AI search. The data in them comes from audits BugViso runs in a real Chromium browser, including our 219-site study of website health.

Found this useful? Share it.

Summarise with AI

Open this guide in your assistant.

Follow BugViso

New guides and audit data as we publish them.

See where your site stands

Run a free BugViso audit for SEO, speed, accessibility and AI search readiness — with fixes you can ship today.