AI Search Visibility & Analytics — Measure how your brand performs inside AI-generated answers (Perplexity, ChatGPT, Gemini, and more).
BestSearch is an AI visibility intelligence platform that answers:
- Are we appearing in AI answers?
- How often are we recommended?
- Do competitors rank higher?
- Is our AI visibility improving over time?
As consumers use Perplexity, ChatGPT, and Gemini instead of Google for research, brands need a new layer beyond SEO. BestSearch provides that.
Search is shifting: Google → AI answers.
Brands today don't know:
- If they're mentioned in AI responses
- Where they rank vs competitors
- Which sources AI cites
- Whether visibility is going up or down
BestSearch solves this with scans, scoring, and a clear dashboard.
| Step | What happens |
|---|---|
| 1. Input | User enters a query (e.g. best veg restaurant in Punjabi Bagh Delhi). |
| 2. Expand | BestSearch generates up to 15 intent-based query variations (commercial, comparison, local, review, list). |
| 3. Scan | Each variation is run across the selected AI engines (Perplexity, OpenAI GPT-4o mini, Gemini). |
| 4. Extract | Entities are parsed from each response (JSON-first, falling back to numbered/bullet lists). |
| 5. Score | We compute per-engine leaderboards plus a Global score and a Consensus score across engines, then store and display them. |
Each entity gets a rank weight (rank 1 = 10 pts, rank 10 = 1 pt).
- Global = Σ rank_weight + per-engine bonus (Perplexity +2, OpenAI/Gemini +1).
- Consensus = mentions × engines_count × avg(rank_weight) — rewards entities that every engine agrees on.
- Volatility = top-3 rank variance across the last 5 scans of the same query →
Stable | Moderate | High volatility.
For a scan, the dashboard shows:
- Global, Per-engine (Perplexity / OpenAI / Gemini), and Consensus leaderboards (rank · score · mentions · engines).
- Trend chart of top scores across the last 7 scans of the same query.
- Engine comparison bar chart of the top 5 entities by engine.
- Volatility chip on the scan header.
- Scan history table — click any past scan to reload its full leaderboards.
- Quota chip showing remaining free scans this month.
- Debug panel with each query → engine → raw AI response.
- Next.js 16 (App Router, Turbopack)
- Supabase (Auth + Postgres + RLS)
- AI engines: Perplexity, OpenAI (
gpt-4o-mini), Gemini (gemini-1.5-flash) - Tailwind CSS v4
- Stripe (subscriptions + webhook)
- Recharts (analytics)
Migrations live in supabase/migrations/. Run them in order in the Supabase SQL editor.
001_scans_table.sql— initial brand/category schema (superseded by 002).002_query_leaderboard_schema.sql— current schema:scans(query-keyed) +scan_results(per-engine leaderboard + raw responses).003_subscriptions.sql—subscriptionstable for Stripe state, RLS read-only for users (webhook writes via service role).
Key tables:
| Table | Columns |
|---|---|
scans |
id, user_id, query, created_at, volatility_index, stability_label |
scan_results |
id, scan_id, engine, leaderboard (jsonb), raw_responses (jsonb), top_score, total_entities |
subscriptions |
user_id, plan, status, stripe_customer_id, stripe_subscription_id, current_period_end |
| Route | Purpose |
|---|---|
POST /api/scan |
Run a scan. Enforces free-tier quota (3 scans / month) for signed-in users when Stripe is configured. |
GET /api/scan/[id] |
Rebuild and return a stored scan's full ScanResponse. |
GET /api/scans |
List the current user's scans (optional ?query= filter, ?limit=). |
GET /api/subscription |
Current user's plan + remaining free quota. |
POST /api/stripe/checkout |
Create a Checkout Session. Body: { plan: "starter" | "pro" }. |
POST /api/stripe/webhook |
Stripe events → upsert subscriptions via service-role client. |
GET /auth/callback |
Supabase OAuth/email-confirm callback. |
- Free — 3 scans / month, single or multi-engine.
- Starter / Pro — unlimited scans, multi-engine. Wired via Stripe Checkout.
- Enterprise — contact sales (mailto link).
Quota enforcement and subscription state degrade gracefully when Stripe / Supabase env vars are missing — the app still runs for local development.
See .env.example. Copy to .env.local and fill in.
# Required
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
# Server-only (webhook bypasses RLS to write subscriptions)
SUPABASE_SERVICE_ROLE_KEY=
# At least one engine
PERPLEXITY_API_KEY=
OPENAI_API_KEY=
GEMINI_API_KEY=
# Optional: Stripe billing
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRICE_STARTER=
STRIPE_PRICE_PRO=
NEXT_PUBLIC_APP_URL=http://localhost:3000npm install
cp .env.example .env.local # fill in values
npm run dev- Create a Supabase project, copy URL + anon key into
.env.local. - Run the SQL files in
supabase/migrations/in order. - In Supabase Auth → URL Configuration, add
http://localhost:3000/auth/callbackto Redirect URLs. - (Optional) Create products in Stripe, set
STRIPE_PRICE_STARTER/STRIPE_PRICE_PRO, and point a webhook athttp://localhost:3000/api/stripe/webhook(stripe listen --forward-to localhost:3000/api/stripe/webhook). - Open http://localhost:3000 → sign up →
/dashboard.
| Area | Status |
|---|---|
| Supabase auth (login, callback, dashboard gating, navbar logout) | ✅ Done |
| Multi-engine scanner (Perplexity, OpenAI, Gemini) | ✅ Done |
| Query expansion + entity extraction | ✅ Done |
| Global + Consensus scoring, volatility | ✅ Done |
| Dashboard (run, leaderboards, trend, engine comparison, history) | ✅ Done |
| Stripe checkout + webhook + quota enforcement | ✅ Done |
| Authority-weighted scoring, sentiment, competitor tracking | 🔜 Roadmap |
| Weekly reports, Slack alerts, CSV export | 🔜 Roadmap |
| Phase | Scope |
|---|---|
| 1 – MVP (current) | Supabase auth, multi-engine scan, scoring, dashboard, Stripe. |
| 2 – Intelligence | Authority-weighted scoring, sentiment, competitor tracking, more engines (Claude). |
| 3 – Advanced | Weekly reports, Slack alerts, CSV export, custom prompts, authority gap analysis. |
BestSearch aims to become the "Ahrefs for AI Search": the default analytics layer for measuring and optimizing brand visibility in AI answers.
BestSearch — AI Influence Intelligence for modern marketers.