# airanker

> Measure how visible a brand is in AI/search results. Deterministic AI-brand-visibility scoring powered by Bright Data.

Latest version **0.1.5** (published 2026-08-23) · MIT license · 0 weekly downloads

## Install

```sh
npm install airanker
pnpm add airanker
yarn add airanker
bun add airanker
```

Provides the commands `airank`, `airanker`.

## Health

**Score 60/100 (C)** — status: active.

Positive: esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; no types; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.1.5 |
| Published | 2026-08-23 |
| First published | 2026-08-21 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM |
| Node | >=18.18 |
| Dependencies | 7 |
| Unpacked size | 355.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Maintainers | sahilgupta09 |
| Keywords | ai, search, brand, visibility, seo, chatgpt, perplexity, gemini, brightdata, cli |

## Links

- npm: https://www.npmjs.com/package/airanker
- Repository: https://github.com/Sahil-Gupta584/airanker
- Homepage: https://github.com/Sahil-Gupta584/airanker#readme
- Issues: https://github.com/Sahil-Gupta584/airanker/issues
- npm.io page: https://npm.io/package/airanker

## Dependencies (7)

- [ora](https://npm.io/package/ora.md) ^8.1.1
- [zod](https://npm.io/package/zod.md) ^3.24.1
- [chalk](https://npm.io/package/chalk.md) ^5.4.1
- [dotenv](https://npm.io/package/dotenv.md) ^16.4.7
- [undici](https://npm.io/package/undici.md) ^6.21.0
- [commander](https://npm.io/package/commander.md) ^12.1.0
- [@clack/prompts](https://npm.io/package/@clack/prompts.md) ^0.9.1

## Alternatives

- [@expo/fingerprint](https://npm.io/package/@expo/fingerprint.md) — 6.2M weekly downloads
- [@azure/monitor-opentelemetry-exporter](https://npm.io/package/@azure/monitor-opentelemetry-exporter.md) — 850.0K weekly downloads
- [@azure/monitor-opentelemetry](https://npm.io/package/@azure/monitor-opentelemetry.md) — 624.0K weekly downloads
- [@posthog/ai](https://npm.io/package/@posthog/ai.md) — 423.3K weekly downloads
- [fakefilter](https://npm.io/package/fakefilter.md) — 63.9K weekly downloads

## Recent versions

- 0.1.5 (latest) — 2026-08-23
- 0.1.4 — 2026-08-22
- 0.1.3 — 2026-08-22
- 0.1.2 — 2026-08-21
- 0.1.1 — 2026-08-21
- 0.1.0 — 2026-08-21

## README

# AIRanker

Measure how visible a brand is in AI and search results. Run a controlled set
of queries across ChatGPT, Perplexity, Gemini, Google AI Mode and Google SERP,
then get a **deterministic, reproducible AI-visibility score** for that brand —
not a vibe, not one model's opinion: the same input always yields the same
score.

```bash
npx airanker opencmo.site
```

## What it does

1. **Analyzes the brand** — fetches the website, uses an LLM to build a
   grounded `BrandProfile` (products, use-cases, keywords; competitors only if
   the site names them).
2. **Generates prompts** — a configurable number (default 8) of realistic
   user queries covering 9 intent classes (best-of, comparison, alternatives,
   problem/solution, buyer, …). Deduplicated.
3. **Collects raw evidence** — each query is run against every AI engine plus
   Google SERP via **Bright Data**. Raw responses are stored verbatim.
4. **Extracts evidence** — an LLM converts each raw response into structured
   observations (mentioned? recommended? position? competitors?). Position is
   `null` unless the raw response states a real rank. **The LLM never invents
   data** — if extraction fails or the engine failed, the observation says so.
5. **Scores deterministically** — a pure function of the observations. No LLM
   in the scoring path. Formula is documented below.
6. **Explains** — an LLM summarizes weaknesses/opportunities/competitor
   insights **grounded only in the structured observations**.

The three layers stay strictly separated: **raw evidence** (Bright Data) →
**LLM interpretation** (extraction/summarization) → **AIRanker score**
(deterministic arithmetic). Nothing is blurred.

## Install / run

```bash
npm install -g airanker        # or: npm i -D airanker
airanker opencmo.site
```

First run or any command checks your config. If Bright Data/LLM keys are
missing, AIRanker walks you through setup interactively:

```
✓ AIRanker setup
  Bright Data API key (won't be echoed): ••••••••••
  Which LLM provider?  ▸ Gemini API (Google AI Studio)
                        OpenAI API
                        Anthropic API
                        claude CLI (not detected)
```

Values are written to `~/.airanker/.env` (never printed to the terminal).

## Commands

```bash
airanker opencmo.site                # bare scan (equivalent to scan)
airanker scan opencmo.site           # full scan
airanker scan opencmo.site --queries 100
airanker scan opencmo.site --queries 100 --output report.json
airanker scan opencmo.site --no-google
airanker scan opencmo.site --engines chatgpt,perplexity
airanker scan opencmo.site --raw     # embed raw provider responses in JSON report
airanker report report.json          # render a saved report
airanker setup                       # re-run interactive configuration
airanker --help
```

Offline demo (no keys, mock stack — tests/demo only):

```bash
airanker --demo opencmo.site
```

`--mock` uses the mock Bright Data provider only (real LLM still required);
`--demo` uses mock Bright Data + mock LLM.

## Required environment

| Variable | Purpose |
| --- | --- |
| `BRIGHTDATA_API_KEY` | Bright Data API key (required) |
| `AIRANKER_LLM_PROVIDER` | `openai` · `anthropic` · `gemini` · `claude` · `codex` · `opencode` |
| `AIRANKER_OPENCODE_MODEL` | opencode model, default `opencode/deepseek-v4-flash-free` |
| `OPENAI_API_KEY` | used when provider is openai |
| `ANTHROPIC_API_KEY` | used when provider is anthropic |
| `GEMINI_API_KEY` | Google AI Studio key (`AIza...`) |

If `AIRANKER_LLM_PROVIDER` is unset, the first available API key wins. Local CLI
providers (`claude`, `codex`, `opencode`) auto-detected on `PATH`; never
required, never assumed.

Copy `.env.example` to `~/.airanker/.env` (or project `.env`) for the full list,
including dataset-id overrides, concurrency, timeouts and debug flags.

### Bright Data setup

1. Create an account at [brightdata.com](https://brightdata.com).
2. **SERP API** zone (`serp_api1` default) for Google results.
3. The AI-engine scrapers need no zone — they use the Scraper API
   (`POST /datasets/v3/scrape`) with **dataset ids**:
   - ChatGPT `gd_m7aof0k82r803d5bjm`
   - Google AI Mode `gd_mcswdt6z2elth3zqr2`
   - Perplexity / Gemini / Copilot: auto-discovered from your account via
     `GET /datasets/v3/scrapers`, or set
     `BRIGHTDATA_PERPLEXITY_DATASET_ID` / `BRIGHTDATA_GEMINI_DATASET_ID` /
     `BRIGHTDATA_COPILOT_DATASET_ID`.
4. Grab the key at **Settings → Users → API key**
   ([get.brightdata.com/ybqohltzjud2](https://get.brightdata.com/ybqohltzjud2)),
   then set it:

```bash
export BRIGHTDATA_API_KEY=your-key
airanker opencmo.site
```

### LLM setup

Pick any one API provider. Keys are never logged; setup uses hidden prompts.

```bash
export OPENAI_API_KEY=sk-...
export GEMINI_API_KEY=AIza...          # Google AI Studio
export ANTHROPIC_API_KEY=sk-ant-...
airanker scan opencmo.site
```

Or set `AIRANKER_LLM_PROVIDER=gemini` etc. You may also use a locally installed
`claude` / `codex` / `opencode` CLI — set `AIRANKER_LLM_PROVIDER=claude`.

## Scoring methodology

Every observation contributes to four deterministic components. All are pure
functions of the observations array.

```
mentionRate   = mentioned queries      / total queries
recommendRate = recommended queries    / total queries
positionComp  = 1 - clamp((avgPosition - 1) / 9, 0, 1)     (positions known only)
                 → falls back to mentionRate when no positions are known
competitComp  = 1 - competitorShare

competitorShare = competitor mentions / (competitor mentions + brand recommendations)

AI Visibility = round(100 × (0.30·mentionRate + 0.30·recommendRate +
                            0.20·positionComp + 0.20·competitComp))
```

- Position 1 → full position credit; position 10+ → zero; linear between.
- Avg. position uses **only** observations where the raw response stated a
  position. Unknown positions are `null`, never guessed.
- `competitorShare` measures how often competitors are recommended instead of
  the brand. No recommendations at all → competitors effectively "won" (share
  1), which is the honest reading of an unseen brand.
- Formula version is stored in every report (`airanker-v1`), so scores stay
  comparable across releases.

## JSON report

```bash
airanker scan opencmo.site --output report.json
```

Writes a versioned, Zod-validated report:

```jsonc
{
  "schemaVersion": 1,
  "format": "airanker-report",
  "report": {
    "version": 1,
    "generatedAt": "2026-08-17T00:00:00.000Z",
    "brandProfile": { /* BrandProfile */ },
    "queries": [ /* TestQuery */ ],
    "observations": [ /* QueryObservation */ ],
    "rawEvidence": [ /* only with --raw */ ],
    "aggregateMetrics": { /* mentionRate, byEngine, byCategory, ... */ },
    "score": { "overall": 74, "components": { ... }, "formulaVersion": "airanker-v1" },
    "recommendations": { "summary": "...", "strengths": [], "weaknesses": [], ... }
  }
}
```

Render it later: `airanker report report.json`.

## Architecture

```
DOMAIN
  ↓
Fetch/analyze website ──► LLM: BrandProfile (Zod)
  ↓
LLM: generate search queries (dedup)
  ↓
Bright Data: collect AI + SERP evidence        (retries · timeouts · partial failure)
  ↓
LLM: extract structured observations          (positions = null unless stated)
  ↓
Deterministic scoring engine                  (pure function, formula versioned)
  ↓
LLM: recommendations (grounded in observations only)
  ↓
CLI report + optional JSON
```

`src/`

```
cli/            commander CLI, interactive setup, progress, Ctrl+C
providers/
  brightnessdata/  BrightDataClient (Scraper + SERP APIs), mock provider
  llm/             LLMProvider interface, OpenAi/Anthropic/Gemini, local CLIs
brand/          website fetch + BrandProfile
queries/        query generation + semantic-ish dedup
analysis/       evidence extraction (LLM as extractor, never oracle)
scoring/        pure deterministic scoring
recommendations/ grounded summarization
report/         stable versioned JSON + terminal renderer
config/         env loading (~/.airanker/.env + project .env)
```

Providers are interchangeable: `LLMProvider` has one method
(`generateStructured<T>({system, user, schema})`) and `BrightDataProvider` has
`collectAi` / `collectSerp`. Swap in your own in under 20 lines.

## Reliability & security

- Strict Zod validation on every structured LLM output; `null` position rather
  than fabrication.
- Retries with exponential backoff, request timeouts, concurrency limits,
  structured debug logging (`--debug`).
- Partial scans: a failing engine becomes a `failed` `RawEvidence` entry; only
  a total provider outage aborts the scan.
- Domain input sanitized (no URLs, paths or shell metachars reach fetch or
  prompts).
- Scraped content is treated as untrusted text — never executed.
- Subprocess execution restricted to an explicit allow-list
  (`claude`/`codex`/`opencode`) with fixed args, timeouts, and non-shell spawn.
- API keys are never printed or logged; the logger scrubs key-shaped strings.

## Testing

```bash
npm test        # vitest · 38 tests, fixture-driven
```

Covers BrandProfile validation, query dedup, evidence extraction (incl.
invalid/missing LLM JSON), scoring formulas, competitor aggregation, failed
Bright Data requests, missing position, and partial scans.

## Limitations

- **AI/search responses are not deterministic universal rankings.** Every
  engine personalizes answers by account, region, session and model. A scan is
  a *sample* at a point in time, not a ground-truth ranking. Re-run to see
  variance; that variance is itself information.
- **Attempts bounded** — a scan is an approximation over N queries × M engines.
- **No dashboard, no accounts, no database** — single-binary, local JSON only.

## License

MIT. Open source by design — fork it, audit it, trust the score you computed
yourself.

---
_Source: https://npm.io/package/airanker · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
