Insights and narratives
The Executive Summary on /insights is the most-read surface in BrandBanta. It's also the most carefully engineered — because an AI narrative that drifts becomes noise instantly.
What you see on /insights
The page is organized top-down by how often you'd actually look at each panel:
- Executive summary — 3-bullet AI narrative + "Regenerate" button + freshness indicator
- KPI strip — current vs previous window: scans, mentions, mention rate, sentiment mix
- Visibility trend — sparkline of mention rate across the last 10 snapshots
- Share of voice — your brand vs each competitor with percentage and absolute count
- Per-platform mention rate — how each LLM treats you separately
- Top cited sources — domains LLMs trust in your category
- Gap sources + Tier 1 source recommender — where competitors get cited but you don't (publish-here suggestions)
- Topic momentum — which of your topics moved most this window (workspace scope only)
- Snapshot history — full time-series of past snapshots
Below that: AI-written findings (3–5), each with evidence, interpretation, confidence, and a specific recommended action.
How the AI narrative is generated
When you visit /insights, the server reads (or materializes) an analytics snapshot — a pre-aggregated row in the analytics_snapshot table containing every KPI plus a content hash of the source data.
The narrative is content-addressed by snapshot hash:
- Identical hash → identical narrative. If your data hasn't moved since the last narrative, we reuse the existing one. Page loads in under 100ms.
- New hash → new narrative. When a scan completes that changes the underlying counts enough to shift the hash, the next visit to
/insightstriggers a Sonnet call (typically 20–40s) that writes a new narrative back to the snapshot row.
The hash is computed over the snapshot's data fields only — your KPIs, leaderboard, sentiment mix, citations — not the timestamp. That way, refreshing the page without new data doesn't burn LLM tokens.
The model
Default narrative model: Claude Sonnet 4.5 via OpenRouter. It's the right tradeoff for this kind of structured-output task — fast enough to feel responsive, smart enough to write recommendations that aren't generic.
For Pro+ tiers we also run an async lane through Anthropic's Batches API (Opus-quality at 50% off). That powers the weekly digest narrative, delivered overnight. See Pricing tiers for which tier gets which lane.
The structured output
The narrative isn't free text. It's validated against a Zod schema with these fields:
{
"summary": ["...", "...", "..."],
"findings": [
{
"finding": "Mention rate dropped 12% week-over-week",
"evidence": "Snapshot shows 23 mentions across 96 scans this week vs 27/93 last week",
"interpretation": "Likely tied to a Perplexity model update reducing your citation frequency",
"confidence": "medium",
"recommendedAction": "Compare top cited sources to confirm Perplexity-specific drift; consider adding HIPAA-compliance content"
}
]
}If the LLM produces malformed output (off-schema, hallucinated fields), we retry with a more conservative prompt before falling back to a "narrative unavailable" banner. We never ship malformed JSON to the UI.
The Regenerate button
On the Executive Summary card you'll see a Regenerate button next to a "Generated 12m ago" label.
- Default page load — returns the cached narrative instantly. No wait.
- Click Regenerate — forces a new snapshot materialization + fresh LLM call. Wait ~30s. Updated narrative swaps in.
Use Regenerate when:
- You just ran a big bulk scan and want the narrative to reflect it
- The current narrative feels stale relative to the dashboard data
- You changed competitors or aliases and want the narrative to acknowledge the new context
When narratives are "insufficient_data"
If a workspace has fewer than a minimum threshold of scans in the window (currently 3), no narrative is generated. The card shows "Need more scans for a meaningful narrative" with a link to run a scan. We won't hallucinate insights from too little data.
When narratives "skipped"
If the workspace has no OpenRouter key (no BYOK + free-tier shared key unavailable in this lane), the narrative card shows "Add an OpenRouter key in Settings → API keys for AI narratives." The dashboard data itself still works — only the narrative skips.
Data retention
Snapshots accumulate over time — every scan completion can trigger a new one. We run a daily cron that prunes the long tail using a value-preserving policy:
- Always keep rows with narratives (LLM tokens were spent; useful as history)
- Always keep rows from the last 90 days (powers the Visibility trend chart)
- Always keep the latest row per scope (active state)
- Delete old + narrative-less + non-latest rows (pure cache leftovers)
So your historical narratives stay accessible forever; only the intermediate cache rows get pruned.
See also
- How it works — full pipeline overview
- Alerts — when narrative shifts become notifications
- Scheduled scans — keeping the narrative fresh on autopilot