Methodology
How we measure AI brand visibility
Every chart in BrandBanta is computed from raw scan responses, persisted as immutable rows, and aggregated transparently. We don't fabricate trendlines, hide algorithms, or average across engines without exposing the per-engine split. This page is the full definition.
How a scan works
Each scan sends a saved prompt (or an ad-hoc one) to four AI providers in parallel — ChatGPT (OpenAI), Claude (Anthropic), Gemini (Google), and Perplexity. We route through OpenRouter for unified billing and platform parity.
Each response is persisted as an immutable row in the response table. We never modify or delete responses after the fact — every chart you see is built from the same raw rows, so re-aggregating with a future algorithm change is always possible.
Citations (URL sources the AI cited) and structured brand mentions are extracted via a regex pre-screen + LLM extraction pass, with hallucination guards on every quoted span. See "Mention detection" below.
Mention rate
Formula: scansWithAtLeastOneMention / totalScans · 100
A scan counts as "mentioning you" if any platform's response contains a verified brand_mention row for your brand. A scan that hits 4 platforms and sees you mentioned in only 1 still counts as a mention — the metric is presence at the scan level, not the response level.
Per-platform mention rate uses the same formula scoped to a single platform: responses-with-mention / total-responses, just for ChatGPT (or Claude, or Gemini, or Perplexity).
Sentiment
Aggregated sentiment is the simple count of each tone over a window. We don't compute a single "sentiment score" because averaging into one number hides the texture — a 50/50 positive/negative split is not the same as 100% neutral, but a score collapses them.
Mention detection
Two passes per response:
- Regex pre-screen. Each brand has a name + aliases + exclusion phrases. We auto-derive a hostname from the brand's website (so "nice.com" matches without the user typing it as an alias). Word boundaries on both sides — "nice job" doesn't match the brand "NICE". Case-sensitivity is configurable per brand.
- LLM extraction pass. Regex hits are passed as candidate spans to a structured-output call. The model is allowed to reject candidates that aren't real mentions (e.g. "nice" the adjective) and add mentions the regex missed. Each accepted mention carries a confidence score (0-100), a sentiment label, and a contextType (primary / comparison / acquisition / incidental).
Sub-brand and product names count. "NICE CXone MPower" is treated as a NICE mention, "Acme's API" as an Acme mention, "nice.com" as a NICE mention. The extractor prompt explicitly biases toward inclusion-with-lower-confidence when ambiguous — better to surface a reviewable mention than silently drop a real one.
Hallucination guard: for every extracted mention, the stored quote must exactly equal response.text.slice(spanStart, spanEnd). Mismatches are dropped silently — no fabricated quotes.
Citation tracking
Top sources cited aggregates by hostname (strippingwww.) and ranks by count. This is the "where AIs get answers in your category" view.
Sources where you're absent is the same aggregation but filtered to responses where your primary brand was NOT mentioned. This is the stronger signal — these are the domains winning answers without you.
Content gap
Surfaced on each own-brand detail page as the "Content gaps" card. Each row lists the query, which competitors got mentioned (with mention counts), and the last time it was scanned.
The companion metric, gap sources, applies the same logic at the citation level: which domains do AIs cite in answers where you're absent.
Discovery (untracked entities)
Discovered entities are stored per response, never deduplicated at write time. Aggregation happens at read time: group by canonical name, count by organization, rank by frequency.
When the "New competitor discovered" alert fires (≥5 observations of the same canonical name in 14 days), the entity becomes a one-click "Track this" candidate. Tracking promotes the entity into the brand table and retroactively links every historical observation as a brand mention.
Cost tracking
Stored in micro-dollars (integer, 1 = $0.000001) on each response row to avoid floating-point drift. The dashboard "Spent" KPI aggregates this across the time window.
When a workspace uses our shared/free-tier OpenRouter key, the cost is recorded on our side and capped via the free-tier policy. When a workspace uses its own (BYOK) key, OpenRouter bills them directly and we still record the cost for visibility — but the customer's account is the authoritative ledger.
Alerts
Three rules in v1, each with a cooldown to prevent spam:
- Mention rate drop:7-day rate drops by >10 points compared to the prior 7-day window (requires ≥5 scans in current). 24h cooldown.
- Competitor surge:a tracked competitor's mention count grew >50% week-over-week with absolute ≥3 mentions. 24h cooldown per competitor.
- New competitor discovered: an untracked brand candidate from the observation table crosses 5+ observations in 14 days. 7-day cooldown per canonical name.
Each alert delivers via the user's enabled channels (in-app, email, webhook, Slack) — opt-out per channel per alert type in your notification settings.
Data depth & cold-start honesty
LLM responses are non-deterministic — the same prompt sent twice can produce different answers. Statistical reliability comes from volume × time.
When a workspace has under 14 days of scan history, every time-series chart shows a Data depth: N days indicator. Trends drawn over short windows are honest about being preliminary.
We don't fabricate trendlines. We don't extrapolate. If you ran 3 scans yesterday and 0 the day before, the chart shows that — not a smoothed best-fit line that creates the illusion of more data than exists.
Per-engine reporting
Every metric is available per platform AND aggregated across platforms. We never average across engines without exposing the per-engine split, because ChatGPT, Claude, Gemini, and Perplexity reason differently and averaging hides that signal.
When you see a single mention-rate number on the dashboard, that's the aggregate. The platform breakdown card shows the per-platform split that the aggregate was built from.