How to measure share of voice in Perplexity
Share of voice in Perplexity is the share of your category's answers that belong to you rather than your competitors — and on a search-grounded engine you should measure it twice. Mention share is how often each brand is named in answerText. Citation share is how often each brand's domain appears in sources[]. Run a fixed query set, count both, print them side by side.
The gap between the two numbers is usually more useful than either alone: you can be cited without being named, or named entirely from a competitor's page. This guide covers the by-hand version, the one-call version in curl and Python, the agent version over MCP, and the ways a share-of-voice number quietly becomes meaningless.
To measure share of voice in Perplexity, fix a query set and a competitive set, run every query, and count two things per answer: which brands the text names, and which brands' domains appear in the citation list. Divide each brand's count by the total across the set and you have mention share and citation share. Track both — on a search-grounded engine they routinely disagree, and the disagreement is the finding.
The manual way (and why it stops working)
Do this on paper once; it's worth the afternoon. Pick ten questions a buyer would genuinely type. Run each in Perplexity and, for every brand you track, tick two boxes: named in the text, cited in the sources. Twenty rows of ticks later you can divide and get real percentages — and you'll have learned more about how your category gets described than any dashboard would have told you.
Then try to do it again next month:
- Ten queries is the floor, and by hand it's also the ceiling. Share of voice measured on three answers is noise wearing a percentage sign. Thirty queries a month, transcribed by hand, is a job nobody keeps doing past the second cycle.
- Ticking boxes drifts. Long source lists, similar-looking domains, a brand named twice in one answer — manual counting makes small consistent errors, and consistent errors look exactly like trends.
- No denominator discipline. If one answer fails to load and you quietly skip it, every percentage changes base without anyone noticing. A script can skip it and report that it did.
- You can't recompute. Change your mind about what counts as a mention and the entire afternoon happens again. With the raw answers stored, you re-run the counter in a second.
- No trend. A share-of-voice number with no previous number is a fact, not a metric — and it can't go into a monthly report, a client deck, or an alert.
Do it with one API call
Each query is one POST. The response carries everything both metrics need — the answer prose and the structured citation list — so the counting is a loop, not a scraping project.
curl -X POST https://api.agentgeo.org/v1/fetches \
-H "Authorization: Bearer ag_live_..." \
-H "Content-Type: application/json" \
-d '{"query": "simple CRM with email integration", "surfaces": ["perplexity"]}'Now the measurement. Declare the competitive set explicitly, run the query set, and tally mentions and citations into separate counters:
import requests
from collections import Counter
from urllib.parse import urlparse
KEY = "ag_live_your_key_here"
# Share of voice is always share *within a set you declare*. Declare it.
BRANDS = {
"Acme": "acme.com",
"Globex": "globex.com",
"Initech": "initech.com",
}
QUERIES = [
"best CRM for small business",
"CRM software for a 10-person sales team",
"simple CRM with email integration",
"cheapest CRM for startups",
]
def host(url):
h = urlparse(url).netloc.lower()
return h[4:] if h.startswith("www.") else h
mentions, citations = Counter(), Counter()
delivered = skipped = 0
for query in QUERIES:
resp = requests.post(
"https://api.agentgeo.org/v1/fetches",
json={"query": query, "surfaces": ["perplexity"]},
headers={"Authorization": f"Bearer {KEY}"},
timeout=200, # the API waits up to 180s for live surfaces
)
resp.raise_for_status()
for answer in resp.json()["answers"]:
if answer.get("status") == "failed":
skipped += 1 # costs 0 credits, and must not count as a zero
continue
delivered += 1
text = (answer.get("answerText") or "").lower()
hosts = {host(s["url"]) for s in answer.get("sources", [])}
for brand, domain in BRANDS.items():
if brand.lower() in text:
mentions[brand] += 1
if any(h == domain or h.endswith("." + domain) for h in hosts):
citations[brand] += 1
total_mentions = sum(mentions.values()) or 1
total_citations = sum(citations.values()) or 1
print(f"{delivered} answers counted, {skipped} skipped\n")
print(f"{'brand':<10}{'mention share':>15}{'citation share':>16}")
for brand in BRANDS:
m = mentions[brand] / total_mentions
c = citations[brand] / total_citations
print(f"{brand:<10}{m:>15.0%}{c:>16.0%}")That prints a two-column table: mention share and citation share for every brand you track, plus how many answers were actually counted. Four queries against one surface is four delivered records — four credits — and failed records cost nothing, which is exactly why the script skips them instead of scoring them as zero.
The two shares diverging is the result. Mention share high and citation share low means Perplexity is happy to name you but is assembling its answers out of other people's pages — a content problem: you don't own the reference the engine reads. Citation share high and mention share low means your pages are feeding the answer while somebody else's brand is the subject of the sentence — a positioning problem: your own content doesn't put your product forward as the answer. A single blended "visibility score" would have hidden both, which is why AgentGEO returns the raw records and lets you do the arithmetic.
| Pattern | What it usually means | Where to work |
|---|---|---|
| Mentions high, citations low | The category writes about you; you don't publish the page it quotes | Own the source — publish the comparison, the pricing detail, the spec everyone paraphrases |
| Mentions low, citations high | Your pages are useful but don't name your product as the answer | Write for the passage — make the product the subject of the claim |
| Both low | You're outside the retrieval set for these queries | Coverage — publish something that answers this exact question |
| Both high | You own this query set | Widen it — add the adjacent intents you aren't measuring yet |
Let your agent do it
Share of voice is arithmetic over records, which makes it a natural fit for an agent: it can fetch the query set, do the counting, and write the month's summary in one pass. Connect the server once:
claude mcp add agentgeo -- npx -y agentgeo-mcp --key ag_live_...One tool, fetch_raw_answers, over stdio — zero npm dependencies, Node.js 18+. surfaces takes one to six engine keys per call, so the same instruction extends past Perplexity when you want it to. Then the ask:
- "Run these ten queries through Perplexity and give me mention share and citation share for Acme, Globex and Initech."
- "Compare this month's shares against sov-2026-07.json and tell me which movement is big enough to be real."
- "For every query where Globex is cited and we aren't, list the exact URLs Perplexity used."
AgentGEO computes no share-of-voice number itself — it ranks nothing and scores nothing. The definitions stay in your code or your agent, which is the point: the moment a vendor picks the denominator for you, the metric stops being comparable to anything you'd calculate yourself.
Common problems
Share of voice is easy to compute and easy to compute wrongly. The five that matter:
- Share of what, exactly? These percentages are shares within the brand set you chose. Add a fourth competitor and everyone's number drops. Write the tracked set and the query set into the report, or the number can't be interpreted — least of all six months later.
- Small query sets swing violently. With five queries, one changed answer moves share by twenty points. Aim for twenty to thirty queries per category before treating any movement as signal.
- Failed records are not zeros. A record with
status: "failed"cost nothing and told you nothing. Skip it and report the count you skipped; folding it into the denominator makes every brand look worse for a reason that has nothing to do with the market. - Name collisions inflate mention share. Substring matching on a short brand name catches unrelated words and other companies. Use word boundaries, and spot-check the raw
answerTextbehind any brand whose number suddenly jumps. - One market at a time.
countrydefaults to"US"andlanguageto"en". A German query set is a different market with a different competitive set — keep it as its own table instead of averaging two markets into a number that describes neither.
Summary
Measuring share of voice once, by hand, is a genuinely useful afternoon and you should do it. Measuring it every month, over enough queries to mean something, with both mention and citation counted and last month's numbers to compare against — that's a script or an agent: one call per query, two counters, and a stored history. Keep the definitions in your own code and the number stays yours.
Put a real number on your Perplexity share of voice. [Start free — no credit card](/onboarding) and run your first query set today.
Start for freeFrequently asked questions
- What is share of voice in Perplexity?
- It's the proportion of answers in a defined query set where your brand appears, relative to the competitors you track. On Perplexity it's worth splitting in two: mention share (your brand named in the answer text) and citation share (your domain appearing in the numbered source list). The two often differ, and the difference is diagnostic.
- How do you calculate share of voice for AI answers?
- Fix a query set and a competitive set, run every query, and count per answer whether each brand is named and whether its domain is cited. Divide each brand's count by the total across all tracked brands. The result is only meaningful alongside the two sets you chose, so record them with the number.
- What's the difference between mention share and citation share?
- Mention share counts brand names in the generated prose; citation share counts domains in the sources the engine used. High mentions with low citations means the category talks about you but your pages aren't the reference — a content gap. High citations with low mentions means your pages feed the answer while another brand is the subject of it — a positioning gap.
- How many queries do I need for a reliable share of voice number?
- Twenty to thirty per category is a reasonable working minimum. Below about ten, a single changed answer moves the percentage far enough to look like a trend. Consistency matters as much as size: the same queries, the same locale, and the same tracked brand set every run.
- Can I measure share of voice across ChatGPT and Perplexity together?
- You can measure both, but keep the tables separate before you combine them. The
surfacesarray accepts one to six engine keys per call, so the same query can be sent toperplexity,chatgpt,gemini,google_ai_overview,google_ai_modeandcopilotat once — and each delivered record costs one credit. Because a chatbot only cites when it browses, citation share isn't directly comparable across engines.
Keep reading