# AI Visibility & GEO Report Skill

Generates a **white-label AI Visibility report** for SEO/GEO agencies: how often a
brand is **mentioned** and **cited** inside AI-assistant answers (ChatGPT, Gemini,
Claude, Perplexity), for the topics that matter, versus competitors.

## Output
- `[brand-domain]_ai_visibility_[YYYY-MM].pdf` — client-ready, agency-branded, no DataForSEO branding.
- `[brand-domain]_ai_visibility_[YYYY-MM].json` — data companion.

## Report structure (fixed)
1. **Cover + Scope** — brand, market, models covered, and the generated prompt set shown verbatim.
2. **AI Visibility Summary** — AI Visibility Score (0.6·mention + 0.4·citation), mention share and citation share kept separate, trend vs prior run.
3. **By-LLM Breakdown** — mention/citation rate per model.
4. **By Prompt & Topic** — per prompt: which models mention the brand, prominence, cited? invisible prompts flagged red.
5. **Citation Landscape** — most-cited domains/pages; brand-owned rows highlighted.
6. **Competitor Comparison** — brand vs each competitor, mention & citation share, overall + by model. The report states its measurement basis (dataset vs live prompt set).
7. **AI Search Demand** — estimated LLM query volume per topic.
8. **Opportunities & Next Actions** — GEO-specific moves tied to findings.
9. **Methodology & Glossary**.

## Determinism
All section titles and table column headers are **constants in
`scripts/build_report.py`** (`SECTION_TITLES`, `COLUMNS`, `PROMINENCE_ORDER`,
`PROMPT_TYPES`). The data JSON supplies values only, so the report skeleton is
identical on every run for every brand.

## Data tracks
- **Track A (dataset)** — `ai_opt_llm_ment_*`: aggregated brand/competitor metrics, top cited domains/pages, cross-brand comparison. `platform: chat_gpt | google`.
- **Track B (live)** — `ai_optimization_llm_response` / `ai_optimization_chat_gpt_scraper`: real answers to the generated prompts, all four LLM types. Powers the by-prompt and by-model views.

Competitors default to a **live like-for-like basis** at **zero extra API calls** —
every competitor's mentions/citations are read from the brand's own unbranded live
answers (one answer names every vendor), so the brand's competitor row rests on the
same sample as its headline. A config toggle (`competitor_live_probing`) can instead
use the aggregated dataset (broader population, but ChatGPT-only and often empty for
niche brands). Competitors never multiply the live-call count.

All four LLM types are always covered (not user-selectable); the flagship
web-search model of each is picked dynamically via `ai_optimization_llm_models`.

See `references/endpoints.md` for exact requests and the per-section mapping.

## Requirements
- Python with `reportlab` (`pip install reportlab`).
- DataForSEO MCP connected.
- Bundled DejaVu fonts (Unicode) under `scripts/fonts/`; a custom agency TTF can be supplied via white-label config.

## Pipeline (token-efficient)
The operator does not compute numbers or hand-write the data JSON. During the run it
classifies each live answer into a **compact checkpoint** (`_cells.json`) and writes
only the prose (`_prose.json`); two scripts do the rest deterministically:

```bash
# 1) checkpoint + config + prose -> full data JSON (all numbers computed here)
python scripts/aggregate.py <brand>_config.json <brand>_..._cells.json <brand>_prose.json \
       -o <brand>_ai_visibility_<YYYY-MM>.json
# 2) data JSON -> PDF
python scripts/build_report.py <brand>_ai_visibility_<YYYY-MM>.json
```

This keeps the long model answers and all share/rate/matrix arithmetic off the
operator's token budget, and makes every number reproducible.

## Requirements
- Python with `reportlab` (`pip install reportlab`).
- DataForSEO MCP connected.
- Bundled DejaVu fonts (Unicode) under `scripts/fonts/`; a custom agency TTF can be supplied via white-label config.
