Method
How we measure AI visibility
The visibility score weights mention rate at 50%, citation share at 30% and position among named brands at 20%. Here is the exact arithmetic, the rules that stop a failed API call masquerading as an absence, and what the method cannot see.
Updated 14 October 2026 · 8 minute read
Why we publish the method
We publish this because a score whose method is secret is a marketing graphic. It is also the page a buyer’s diligence asks for, and we would rather it already existed.
Ask
What’s the best invoicing tool for small agencies?
Your question, word for word, sent to the engine we hold a key for.
Engine answers
Perplexity · live
Fernhub is the usual pick 1.
Kalye is a strong alternative 2,
and Tallybook suits freelancers 3.
A failed call is stored as a failure and left out, never as “not named”.
The full answer and every source it cites are stored.
Names and citations found
- ✓Named: KalyeWhole word, links blanked first
- #2nd of 3 brands namedPosition score 0.75
- ↗1 of 3 sources yourskalye.io, counted apart from the name
- ~Tone readShown, not scored
Rivals are found the same way, so you see who was named instead.
Scored
75- Named, 50%50
- Cited, 30%10
- Rank, 20%15
This answer alone scores 75. A run averages every answer it analysed.
Perplexity, and only Perplexity, todaySame questions, same arithmetic, every check.
The three inputs
| Metric | Definition | Weight |
|---|---|---|
| Mention rate | Answers naming the brand ÷ answers analysed | 50% |
| Citation share | Cited sources on the brand’s own domain ÷ all cited sources | 30% |
| Position component | A per-answer position score, averaged over every answer analysed | 20% |
Visibility score = round( (mention rate × 0.5 + citation share × 0.3 + position component × 0.2) × 100 ), clamped to 0–100.
How the position component works
Being the first brand named is worth far more than being the fourth, so position is scored on a scale rather than counted:
| Position in the answer | 1st | 2nd | 3rd | 4th | 5th or later | Not named |
|---|---|---|---|---|---|---|
| Score | 1.0 | 0.75 | 0.5 | 0.25 | 0 | 0 |
The scores are summed and divided by every answer analysed, not only the answers that named you, so one lucky first place cannot carry the score.
Average position is reported separately and is averaged only over answers where you were named. When you were never named it is reported as none, not as zero — an undefined value, honestly labelled.
AnswerPerplexity
What’s the best invoicing tool for small agencies?
For small agencies, Fernhub is the usual pick for recurring retainers 1. Kalye is a strong alternative with simpler pricing 2, and Tallybook suits solo freelancers 3.
- 1fernhub.com
- 2kalye.ioYours
- 3reviewsite.example
This answer alone75(1 × 0.5 + 1/3 × 0.3 + 0.75 × 0.2) × 100
- The question, word for wordAsked the same way every week and stored with the result, so the number keeps its meaning.
- A rival, found the same wayCompetitors are matched as whole words too. That is how you see who was named instead.
- Named, and whereA whole-word match outside any link counts as named. Kalye is the 2nd brand named: 0.75.
- Tone: shown, not scoredThe sentence around the name is read as positive, neutral or negative, and kept out of the score.
- A link is a citationEvery source domain is recorded. kalye.io is the brand’s own, so 1 of these 3 sources is yours.
Worked example one: our own zero
From our September 2026 audit: eight questions, one engine, eight answers analysed.
- Mention rate0 ÷ 8 = 0
- Citation share0 ÷ 90 = 0
- Position component0 ÷ 8 = 0
- Score(0 + 0 + 0) × 100 = 0
All three inputs were zero, so there is nothing to round and nothing to argue about. Zero is the floor, and it is where we started.
Worked example two: how a real score is built
Illustrative numbers, not a client’s, so you can follow the arithmetic. Eight questions; the brand is named in three of them, at positions 2, 1 and 4; four of the 60 cited sources are on its own domain.
| Step | Working | Value |
|---|---|---|
| Mention rate | 3 named ÷ 8 answers | 0.375 |
| Citation share | 4 owned ÷ 60 cited | 0.0667 |
| Position scores | 2nd = 0.75, 1st = 1.0, 4th = 0.25 | sum 2.0 |
| Position component | 2.0 ÷ 8 answers | 0.25 |
| Weighted sum | (0.375 × 0.5) + (0.0667 × 0.3) + (0.25 × 0.2) | 0.2575 |
| Visibility score | 0.2575 × 100, rounded | 26 |
Notice what that says. A brand named in nearly four answers in ten, once in first place, still scores 26 — because it is almost never the cited source. Citation share is where that brand leaves points on the table, and it is the input you control fastest.
Where the brand was named, per answer
Tap an answer to step it: not named, 1st, 2nd, 3rd, 4th, 5th or later.
26Occasionally surfaced
- Named · mention rate
3 ÷ 8 = 0.375 × 5018.75 - Cited · citation share
4 ÷ 60 = 0.0667 × 302 - Rank · position component
2 ÷ 8 = 0.25 × 205
Score = round(25.75) = 26, clamped to 0–100. Position scores: 1st 1.0, 2nd 0.75, 3rd 0.5, 4th 0.25, 5th or later 0, averaged over all eight answers.
What the bands mean
| Score | Band |
|---|---|
| 0–24 | Rarely surfaced |
| 25–49 | Occasionally surfaced |
| 50–74 | Regularly surfaced |
| 75–100 | Consistently surfaced |
The honesty rules built into the run
Enforced in the code that produces the number, not in a policy document. Each one, broken, would quietly flatter us.
- An engine error is never “not named”. Failed and empty answers are counted in their own column and never reach the scoring function. Otherwise the score would measure our own timeouts.
- A run with any failure is marked incomplete and stored under a separate filename, so it can never become the baseline for a trend.
- Records are written atomically and never overwrite an existing file. A published number that can be silently edited is not evidence.
- The question list is stored verbatim in every record. Changing a prompt changes what the number means, so the prompt set travels with the result.
- Nothing resembling an API key can enter a stored record. The records are meant to be publishable.
- Each run has a schema version, so old records stay readable when the shape changes.
- Each question gets a 45-second timeout and one retry before it is recorded as a failure.
Non-determinism, measured
Engines do not return the same answer twice, so we ran our own audit twice, about a minute apart, and kept both records.
| Measure | Run A | Run B |
|---|---|---|
| Visibility score | 0 | 0 |
| Answers naming Bungad | 0 of 8 | 0 of 8 |
| Competitors named | As our code counted them: Profound 2, Peec AI 2, Otterly 2, AthenaHQ 1, Scrunch AI 1. The Scrunch AI count is one too low: a second answer calls it Scrunch, without the AI, and the code missed it. | Identical |
ahrefs.com citations | 3 | 4 |
blog.hubspot.com citations | 5 | 4 |
peec.ai citations | 4 | 2 |
The conclusion we draw, and publish: headline metrics and brand tallies reproduce; per-domain citation counts do not. Treat a single run’s per-domain figures as estimates. Treat a single run of any kind as an anecdote — the signal is the trend across months on a fixed question set.
How to run this yourself
Nothing here is proprietary. If you would rather not pay anyone, this is the method.
The seven steps
- Fix a question set and write it down. The questions a buyer actually asks before choosing someone like you, in their phrasing. At least two where price is the question and two you expect to lose. Store it verbatim — it is the denominator of every number that follows.
- Name your competitors explicitly, with their domains. Without that list you learn whether you were named, but not who beat you, which is the more actionable half.
- Ask every question to every engine you can reach, through an API rather than a chat window, so the run is reproducible and free of personalisation. Set a timeout and allow a small number of retries.
- Record failures separately and never as absences. Count errors and empty responses in their own column, keep them out of the metrics, and mark a run containing one as incomplete so it cannot become a baseline.
- Parse each answer for three things: whether your brand is named, its position among the brands named, and every cited source domain with a flag for whether you own it.
- Compute the three metrics and the weighted score using the arithmetic above.
- Store the whole run and repeat monthly, written atomically and never overwritten, comparing only against your own previous runs on the same question set.
Our own run is a script in our repository rather than a spreadsheet, and the stored records behind our published score are the raw output of it.
What this method does not measure
Stated here so a buyer does not have to find them.
- It is a sample, not a census. It reports what an engine says when asked your questions. It cannot count every time you were cited to somebody.
- Questions are not weighted by real demand. No engine publishes how often a question is actually asked, so every question in the set counts equally, which is a simplification.
- One engine automatically, today. Perplexity is the only engine we hold an API key for. ChatGPT, Claude and Gemini adapters are built and awaiting keys. Google AI Overviews and Copilot have no public consumer API, and we do not track them on any plan. A score from one engine says nothing about the others.
- No personalisation or memory effects. API answers are not the answers a logged-in user with chat history receives. Those may be better or worse for you and we cannot see them.
- Sentiment is recorded but excluded from the score. Being named badly and being named well both count as a mention. We keep sentiment as a separate field rather than smuggling a judgement into a headline number.
- English-language phrasing. The same question in another language can return a different set of brands entirely.
- Scores are not comparable between vendors. Different weights, different questions, different engines. Compare yours only with your own.
Common questions
How is an AI visibility score calculated?
Ours combines three measures: mention rate at 50 percent, citation share at 30 percent, and a position component at 20 percent, multiplied by 100 and rounded. The position component gives an answer 1.0 when you are the first brand named, 0.75 for second, 0.5 for third, 0.25 for fourth and 0 from fifth onwards, then averages that across every answer analysed — not only the ones that named you.
What happens if an engine call fails during a measurement run?
It is recorded as a failure and excluded from the metrics entirely. A failed call is never counted as ‘not mentioned’, because that would make the score a measure of the vendor’s reliability rather than your visibility. A run containing any failure is marked incomplete and stored separately so it can never become the baseline for a trend.
Can two AI visibility scores from different vendors be compared?
No. Weightings differ, question sets differ, and engine coverage differs, so two vendors scoring the same brand are not performing the same measurement. A score is only meaningful against itself, on a fixed question set, over time. Treat any cross-vendor comparison of headline scores as meaningless.
What does this method not measure?
It samples a question set rather than counting every time you were cited to anyone. It does not weight questions by how often they are really asked, because no engine publishes that. It covers one engine automatically today, Perplexity, so it says nothing about ChatGPT or Gemini. It does not account for personalisation or chat memory. And sentiment is recorded but deliberately kept out of the headline score.
See the method applied to your domain
3 questions on Perplexity. Were you named, was your site cited, and can AI crawlers read your homepage? Free, no account.
Or start free with 1 brand and 5 tracked questions. A domain checked in the last week shows its stored run; the daily free allowance resets at midnight UTC.
More guides