AI Visibility Report Template for Agencies (Client-Ready)

An AI visibility report template for agencies: the scorecard, intervals, competitor board, source gaps and method notes clients need, with a real example.

BugViso

14 min read

A client-ready AI visibility report has seven parts. A per-engine scorecard, an interval on the headline rate, a leaderboard on a fixed competitor list, the sources that cite rivals instead of the client, accuracy issues with corrections, a short action plan, and method notes: prompts, engines, dates, sample size. Leave any one out and the report invites the wrong conclusion.

AI visibility is new to most clients, and the numbers are easy to misread. This template is built from a real report on our own brand, with every section filled with real data, and a script that generates the scorecard from raw answers.

Example data: BugViso's AI Visibility Tracker report for bugviso.com (website-audit software): 50 prompts, ChatGPT, Gemini, Perplexity and Claude, 2026-10-20, against five anonymised competitors.

The Report Structure

TierSectionWhat it answersMust include
P0HeadlineWhere does the client stand?Index or mention rate with interval, rank on the fixed list
P0Engine scorecardWhich engines see them?Mention rate, prompt coverage, citation coverage, share of voice, accuracy per engine
P0MethodCan we trust it?Prompt set version and size, engines, dates, answers counted, competitor list
P1LeaderboardWho wins instead?Every tracked brand on the same metrics
P1Source gapsWhy do rivals win?Third-party sources citing rivals but not the client
P1Accuracy issuesWhat do engines get wrong?Wrong claims, verbatim, with the correction
P2Action planWhat do we do next?3 actions for this period, each tied to a number above
P2Change since last periodIs it working?Pooled period vs pooled period, prompts won and lost

P0 sections go on page one. A report without method notes isn't client-ready, however good the charts look.

Section 1: The Headline

One line, one number, one range, one rank.

Visibility index 26.5 (rank 5 of 6). Named in 7.9% of unbranded answers (95% interval 4.4–13.5%) across 4 AI engines.

That's the real headline from our report's first run. Everything else in the report explains it. The range is a Wilson score interval, which stays sensible for small rates like this one.

The visibility index combines five parts into a 0–100 score: visibility 35%, share of voice 20%, position 20%, own-site citations 15%, sentiment 10%. For our brand the parts were:

PartWeightScore
Visibility (V)357.9
Share of voice (S)2012.4
Position (P)2072.0
Citations (C)1511.4
Sentiment (T)1051.4

Show the parts. A client who sees "position 72" understands why the index isn't lower: when engines name the brand, they name it early. "Visibility 7.9" shows why it isn't higher.

Section 2: The Engine Scorecard

This is the most important table, because engines behave like separate channels. Here's the scorecard our script generates from the two runs' raw answers (unbranded prompts, competitor names masked):

EngineMention ratePrompt coverageCitation coverageShare of voiceAvg positionIndex
chatgpt8.6%5/358.6%15.8%1.1730
claude0.0%0/354.3%0.0%n/a1
gemini4.3%2/354.3%3.0%1.0025
perplexity17.1%8/3525.7%25.0%1.2538
All engines7.5%11/3510.7%7.4%1.1928

How to explain each column to a client:

  • Mention rate: of the buyer questions that didn't name you, how often each AI named you.
  • Prompt coverage: how many of the 35 questions you appeared on at least once. This is the most intuitive number for clients: "you show up for 11 of 35 buyer questions."
  • Citation coverage: how often your website was linked as a source.
  • Share of voice: of all the recommendations made, how many were you. Explained in our AI share of voice guide.
  • Average position: when you're named, are you named first?

The script's index (28) differs slightly from the tracker's (26.5). The script pools two runs and leaves sentiment out. The tracker scores one run, includes sentiment, and averages the engines. Always say which method a number comes from.

Section 3: Method Notes

Put this box on page one, small but visible:

text
Method
- Prompt set: v1, 50 buyer questions (35 unbranded, 15 naming the brand), drafted from the site
- Engines: ChatGPT, Gemini, Perplexity, Claude (web search on, official APIs)
- Window: 2026-10-20, 2 runs; 400 answers (280 unbranded scored for visibility)
- Competitors: 5, fixed for the period (listed on page 3)
- Scoring: unbranded prompts only; refused/empty answers excluded; 95% Wilson intervals
- Limits: API answers approximate consumer apps (no memory, personalisation or chat history)

Every line prevents a specific misunderstanding:

Method lineThe misunderstanding it prevents
Prompt set version"Why did visibility jump?" (the prompts changed, not the market)
Unbranded only"We're named in 100% of answers!" (on prompts that name you)
Window and answer countTreating one day as a trend
Competitor listComparing shares measured against different rivals
Limits"But when I asked ChatGPT, it said…"

The last line matters more than it looks. Search surfaces themselves change too; Google's notes on AI features and your website are worth linking in the appendix for clients who ask. Clients will check by asking ChatGPT themselves and get a different answer. That's expected: in our repeat test, 40% of shortlists changed on a re-ask 23 minutes later (answer consistency data). Say so before they find out.

Section 4: Diagnosis, Gaps and Accuracy

Our report's diagnosis rated three signals:

SignalValueRatingPlain-English reading
Source coverage8.4WeakNamed in 10 of 119 answers that cite third-party sources
Entity clarity94.4Strong151 accurate vs 9 inaccurate claims about the brand
Authority signals18.2Weak2 of 11 answers naming the brand also cite a review site, publication or directory

This tells the client the problem isn't that engines misunderstand the brand. The problem is that third-party sources don't mention it. Then show:

  • Source gaps: the top third-party pages that cite rivals but not the client, with the engines citing them. The method is in our AI citation gap analysis.
  • Accuracy issues: each wrong claim, verbatim, with the correction. For us, every flagged claim was about pricing or plans (AI brand accuracy audit).

Section 5: The Action Plan

Three actions, each tied to a number in the report, each with a first step. Not a list of twenty best practices.

ActionTied toFirst step
Get into the comparison pages engines citeSource coverage 8.4 (weak)Pitch the top 3 gap sources with corrections and facts
Publish learn-stage guidesNamed on 0 of 10 unbranded learn-stage promptsWrite 2 guides on the questions competitors win
Fix pricing statements at the source9 inaccurate claims this run, all about pricing or plansState the starting price in plain text; generate markup from the pricing data

Then report on those three next period. Clients don't need to know everything about GEO; they need to know what you're doing about the numbers.

The Template

Copy this skeleton into your report tool:

markdown
# AI visibility report: <Client> — <period>

**Visibility index <n>** (rank <r> of <N>). Named in **<v>%** of unbranded answers
(95% interval <lo>–<hi>%) across <k> AI engines. <One sentence: biggest change or finding.>

> Method: prompt set v<x> (<p> prompts, <u> unbranded) · engines: <list> · <dates>, <runs> runs,
> <answers> answers · competitors: <n>, fixed · unbranded prompts only · 95% Wilson intervals.
> API answers approximate consumer apps.

## Scorecard by engine
| Engine | Mention rate | Prompt coverage | Citation coverage | Share of voice | Accuracy |
|---|---:|---:|---:|---:|---:|

## Leaderboard (same prompts, same period)
| Brand | Index | Mention rate | Share of voice |
|---|---:|---:|---:|

## What's holding <Client> back
- Source coverage: <value> (<rating>) — top gap sources: <3 types or pages>
- Accuracy: <n> wrong claims — <most important one, verbatim → correction>

## This period's actions
1. <Action> — because <number> — first step: <step>
2. ...
3. ...

## Change since last period (pooled)
Prompts won <w>, gained <g>, lost <l>. <One sentence on what moved and why.>

Keep it to two pages plus appendix. The appendix holds the full prompt list, the per-topic and per-intent segments (flagged where they rest on fewer than 20 answers), and links to example answers.

Generate the Scorecard from Raw Answers

If you collect answers yourself, this script builds the scorecard table above. It reads the CSV with Python's csv module. It needs a CSV with engine, prompt_id, answer, cited_urls, and optionally branded.

python
#!/usr/bin/env python3
"""Turn raw AI answers into a client-ready AI visibility scorecard (Markdown).

Usage: python3 ai_visibility_report.py answers.csv --brand "Acme" --domain acme.com \
           --competitor "Globex" --competitor "Initech" > report.md
answers.csv columns: engine, prompt_id, answer, cited_urls; optional branded (1/0, branded rows skipped).
Index = 0.35 visibility + 0.20 share of voice + 0.20 position + 0.15 citations, rescaled to 0-100
(sentiment is left out here, so the four weights are divided by 0.90).
"""
import argparse, csv, re
from collections import defaultdict
from urllib.parse import urlparse

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("csv"); ap.add_argument("--brand", required=True); ap.add_argument("--domain", required=True)
    ap.add_argument("--competitor", action="append", default=[])
    a = ap.parse_args()
    names = [a.brand, *a.competitor]
    rx = {n: re.compile(r"(?<![\w-])" + re.escape(n) + r"(?![\w-])", re.I) for n in names}
    own = a.domain.lower().removeprefix("www.")
    E = defaultdict(lambda: {"n": 0, "seen": defaultdict(int), "rank": defaultdict(list), "cite": 0,
                             "prompts": set(), "covered": set()})
    with open(a.csv, newline="", encoding="utf-8") as f:
        for r in csv.DictReader(f):
            if r.get("branded") == "1":
                continue
            hosts = {(urlparse(u).hostname or "").lower().removeprefix("www.") for u in r["cited_urls"].split()}
            hits = {n: m.start() for n in names if (m := rx[n].search(r["answer"]))}
            for key in (r["engine"], "All engines"):
                e = E[key]
                e["n"] += 1
                e["prompts"].add(r["prompt_id"])
                e["cite"] += any(h == own or h.endswith("." + own) for h in hosts)
                for rank, n in enumerate(sorted(hits, key=hits.get), 1):
                    e["seen"][n] += 1
                    e["rank"][n].append(rank)
                if a.brand in hits:
                    e["covered"].add(r["prompt_id"])
    N = len(names)
    print(f"# AI visibility scorecard: {a.brand}\n")
    print("| Engine | Mention rate | Prompt coverage | Citation coverage | Share of voice | Avg position | Index |")
    print("|:---|---:|---:|---:|---:|---:|---:|")
    for key in sorted(E, key=lambda k: (k == "All engines", k)):
        e = E[key]
        V = 100 * e["seen"][a.brand] / e["n"]
        total = sum(e["seen"].values())
        S = 100 * e["seen"][a.brand] / total if total else 0.0
        ranks = e["rank"][a.brand]
        avg = sum(ranks) / len(ranks) if ranks else None
        P = 100 * (1 - (avg - 1) / (N - 1)) if avg else 0.0
        C = 100 * e["cite"] / e["n"]
        index = (0.35 * V + 0.20 * S + 0.20 * P + 0.15 * C) / 0.90
        cov = f"{len(e['covered'])}/{len(e['prompts'])}"
        print(f"| **{key}** | {V:.1f}% | {cov} | {C:.1f}% | {S:.1f}% | {avg:.2f} | {index:.0f} |" if avg else
              f"| **{key}** | {V:.1f}% | {cov} | {C:.1f}% | {S:.1f}% | n/a | {index:.0f} |")
    allE = E["All engines"]
    leader = max(a.competitor, key=lambda n: allE["seen"][n]) if a.competitor else None
    if leader:
        print(f"\nMost-named competitor: **{leader}**, in {100 * allE['seen'][leader] / allE['n']:.1f}% of "
              f"unbranded answers vs {100 * allE['seen'][a.brand] / allE['n']:.1f}% for {a.brand}.")

if __name__ == "__main__":
    main()

It needs Python 3.9+ (removeprefix, the walrus operator). The pooled "All engines" row adds answers across engines; for a headline, average the engine rows instead. The script also printed:

text
Most-named competitor: **Competitor A**, in 25.4% of unbranded answers vs 7.5% for BugViso.

Validation Protocol Before Sending

  1. Re-derive the headline from the scorecard: does the "All engines" row match page one?
  2. Check every rate has a sample size or interval. Delete segment charts resting on fewer than 20 answers, or label them.
  3. Open three answers behind the biggest claim and confirm they say what the report says.
  4. Confirm the competitor list and prompt version match last period, or say they changed.
  5. Read the action plan aloud to someone outside the account. Each action should make sense without the appendix.

For the presentation itself, the same principles as a technical audit apply. Our guide on presenting an SEO audit to a client covers structuring the meeting, and packaging audits as a retainer covers making it a recurring deliverable.

How BugViso Produces the Client Report

BugViso's AI Visibility Tracker builds this report from every run:

  • The full structure above: headline index with rank and interval, the engine scorecard (mention rate, prompt coverage, citation coverage, share of voice, accuracy), the leaderboard, segments by engine, intent and topic with low-confidence flags, source gaps, the three-signal diagnosis, accuracy issues with corrections, and an action plan with up to three "this week" actions.
  • Reports per run, per week, or across all runs. Weekly wrap-ups pool the week's runs and show prompts won, gained and lost.
  • White-label PDF and CSV. The PDF uses your agency's white-label kit: company name, colour, logo and footer, never BugViso's logo. The CSV has one row per prompt × engine.
  • Share links. A report can be shared by a revocable link. Anyone with the link can view it and download the PDF or CSV.
  • A daily report email after each daily run, to the owner and extra recipients you add.

See an example report on the AI visibility tracker page.

High-Risk Oversights

Promising rankings. "We'll get you to #1 in ChatGPT" is a promise nobody can keep: answers vary on every ask. Commit to actions and measurement, not positions.

Reporting branded prompts as visibility. Branded prompts named the brand in 100% of answers in our data. Including them in the headline is the fastest way to lose a client's trust when they find out.

Comparing periods measured differently. A new prompt version or competitor list breaks comparability. Say so, and start a new baseline.

Leaving out the interval. "Visibility rose from 6% to 9%" sounds like growth. If both numbers rest on 70 answers, the intervals overlap and it's noise (how often to track AI visibility).

Burying the action plan. Clients pay for what you do next. Put the three actions on page one or two.

FAQ

What should an AI visibility report include?

A headline rate with an interval and rank, a per-engine scorecard, a leaderboard on a fixed competitor list, source gaps, accuracy issues, a three-item action plan, and method notes with prompt version, engines, dates and sample size.

How do I explain AI visibility to a client?

Use prompt coverage first: "you appear in AI answers for 11 of 35 buyer questions; your top competitor appears for 20." Then show which engines and which sources explain the gap.

How often should agencies send AI visibility reports?

Weekly or monthly, based on pooled runs. Daily runs pooled into a weekly report give stable numbers; single runs are too noisy to report on their own.

Can I white-label an AI visibility report?

Yes. BugViso's tracker renders the PDF with your agency's name, colour, logo and footer, and you can share the report by a revocable link.

What's a good AI visibility score?

There's no universal benchmark. Compare the client with the leader on the same prompts, engines and competitor list, and track the gap over pooled periods.

Conclusion

A client-ready AI visibility report pairs a per-engine scorecard and an honest interval with sources, accuracy issues and three actions, which is the report BugViso's AI visibility tracking builds from every run.

Found this useful? Share it.

See where your site stands

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