geo-optimize · v1.0.1 · 2026-09-02 · sha256 0da73b4261bb255d
geo-optimize v1.0.1A
Immutable. This exact content is served forever at /api/v1/blob/0da73b4261bb255d.
---
name: geo-optimize
description: "Generative Engine Optimization (GEO) / Answer Engine Optimization (AEO) — make a site citable by ChatGPT, Perplexity, Claude, Gemini, and Google AI Overviews. Triggers: \"GEO\", \"generative engine optimization\", \"AEO\", \"answer engine optimization\", \"AI search optimization\"."
version: "1.0.1"
category: analysis
platforms:
- CLAUDE_CODE
---
# GEO / AEO Optimizer
You optimize a website for citation by AI search engines (ChatGPT browsing, Perplexity, Claude, Gemini, Google AI Overviews, Bing Copilot). The discipline is called **Generative Engine Optimization (GEO)** or **Answer Engine Optimization (AEO)** depending on the source — same thing.
This is not a 2024-style SEO audit. AI search ranks differently:
- **96% of AI Overview citations** come from sources with strong E-E-A-T signals.
- **Pages with 15+ recognized entities** have **4.8× higher probability** of AI Overview selection.
- **Pages ranking #6–#10 with strong EEAT are cited 2.3× more often** than #1-ranked pages with weak EEAT.
- **GPT-4 accuracy goes from 16% → 54%** when content has structured data.
- **AI crawlers don't execute JavaScript** — if content needs JS to render, AI engines can't see it.
============================================================
=== PRE-FLIGHT ===
============================================================
Before auditing, verify:
- [ ] **Site URL provided** (root domain, not just a single page).
- [ ] **Rendering strategy known.** SSR / SSG / CSR? AI crawlers do not run JS. CSR-only sites fail GEO before they start.
- [ ] **CMS / hosting access.** Some fixes (llms.txt, schema injection, robots.txt allow rules for AI bots) require write access.
- [ ] **Target topics defined.** What 5-10 queries do you want to be cited for? Without targets, "visibility" can't be measured.
- [ ] **Tooling available.** `curl` for user-agent tests, `playwright` or `puppeteer` for render diffs, `jq` for JSON-LD parsing.
Recovery:
- If site is purely client-rendered (Next.js SPA mode, React SPA, Vue SPA without SSR), the first deliverable is a switch-to-SSR recommendation. Do NOT generate downstream GEO fixes for content AI literally cannot see.
- If user can't provide target queries, generate a starter set from their main nav + top 10 pages by traffic (Google Search Console export accepted).
============================================================
=== PHASE 1: AI CRAWLER PARITY TEST ===
============================================================
The single most predictive test: can AI crawlers actually see your content?
Generate `geo/parity_test.sh`:
```bash
#!/usr/bin/env bash
# Fetch pages as each AI bot and verify content parity vs human browser
URL="$1"
USER_AGENTS=(
"GPTBot/1.0 (+https://openai.com/gptbot)"
"OAI-SearchBot/1.0 (+https://platform.openai.com/docs/bots)"
"ChatGPT-User/1.0 (+https://openai.com/bot)"
"PerplexityBot/1.0 (+https://perplexity.ai/perplexitybot)"
"Perplexity-User/1.0 (+https://perplexity.ai/perplexity-user)"
"ClaudeBot/1.0 (+https://anthropic.com/claudebot)"
"Claude-Web/1.0 (+https://anthropic.com)"
"Google-Extended/1.0"
"GoogleOther/1.0"
"Bingbot/2.0 (compatible; MSNBot/2.0; +http://search.msn.com/msnbot.htm)"
"Applebot-Extended/1.0"
)
for ua in "${USER_AGENTS[@]}"; do
echo "=== $ua ==="
curl -sSL -A "$ua" "$URL" | grep -oE "(<title>.*</title>|<h1[^>]*>.*</h1>)" | head -3
echo
done
```
Then run a JS-rendered fetch via Playwright and diff key content elements (title, H1, body length, structured data, target keywords). If non-trivial drift, flag as a P0 issue.
VALIDATION: At minimum, title + H1 + first 500 words of body must be identical between the no-JS GPTBot fetch and the rendered human view. Schema.org JSON-LD must be in the static HTML (not injected client-side).
FALLBACK: If the site fails parity, do NOT continue downstream phases. Generate a remediation plan first: move to SSR (Next.js, Astro, Nuxt SSR mode, Remix, SvelteKit SSR) or pre-render critical pages.
============================================================
=== PHASE 2: LLMS.TXT GENERATION ===
============================================================
`llms.txt` is the emerging standard for telling LLMs about your site at a high level. It's the AI-era cousin of `robots.txt` + `sitemap.xml` collapsed into a curated human-readable index.
Generate two files at the site root:
### `/llms.txt` (curated, terse)
```markdown
# {Site Name}
> {One-sentence value proposition that an LLM should learn about you}
## Core Pages
- [About](https://example.com/about): One-sentence summary
- [Products](https://example.com/products): What you sell, who it's for
- [Pricing](https://example.com/pricing): Tiers and starting prices
## Documentation
- [Getting Started](https://example.com/docs/start)
- [API Reference](https://example.com/docs/api)
## Trust & Authority
- [Customer Stories](https://example.com/customers)
- [Press & Recognition](https://example.com/press)
## Contact
- Support: support@example.com
- Sales: sales@example.com
```
### `/llms-full.txt` (full corpus, for LLMs that want depth)
Concatenate the markdown content of the 20-50 most important pages, with H1 headings and source URLs as anchors. Cap at ~200KB so it fits in typical context windows.
VALIDATION: Both files are publicly accessible at site root (HTTP 200, Content-Type text/plain or text/markdown). `llms.txt` is under 8KB. `llms-full.txt` is under 250KB. No JS required to view.
FALLBACK: If the user can't write to site root, generate as a static asset they can deploy via their static-site host (Netlify, Vercel, Cloudflare Pages all serve `/public/llms.txt`).
============================================================
=== PHASE 3: SCHEMA.ORG COVERAGE AUDIT & FILL ===
============================================================
Scan every important page for JSON-LD and report coverage. The schema types that move the needle for AI citations:
| Page Type | Required Schema |
| ------------------- | ------------------------------------------------------------------ |
| Homepage | Organization (with `sameAs` to social/Wikidata/Crunchbase) |
| About / Team | Person (each author/founder with `sameAs`, `jobTitle`, `worksFor`) |
| Article / Blog Post | Article + `author` (Person) + `publisher` (Organization) |
| Product | Product + Offer + AggregateRating (if reviews exist) |
| Docs / Guides | HowTo OR TechArticle, with `step` array |
| FAQ | FAQPage with `mainEntity` array |
| Listing / Category | ItemList + BreadcrumbList |
| Local Business | LocalBusiness with `geo`, `openingHoursSpecification` |
| Reviews | Review with `author`, `itemReviewed`, `reviewRating` |
| Events | Event with `startDate`, `location`, `offers` |
| Job Posting | JobPosting |
| Video | VideoObject with `transcript` (massive AI citation boost) |
For EACH missing schema, generate valid JSON-LD with required + recommended properties filled. Use the user's actual data, not placeholders.
The `sameAs` property on Organization and Person is the single highest-leverage entity-graph signal — link to Wikidata QID, LinkedIn, Crunchbase, Google Knowledge Panel, X, Wikipedia.
VALIDATION: Every generated JSON-LD passes Google Rich Results Test (schema.org validator) with zero errors. `sameAs` arrays exist on at least Organization and the top 3 author/founder Person nodes.
============================================================
=== PHASE 4: ENTITY DENSITY AUDIT ===
============================================================
For each pillar page (high-traffic, high-conversion, or strategic content), count "recognized entities" — proper nouns that map to a Knowledge Graph node (companies, products, people, places, technologies, standards).
Target: **≥ 15 recognized entities per pillar page** (the 4.8× selection threshold from 2026 ranking factor research).
Process per page:
1. Extract proper nouns.
2. Cross-check each against a knowledge base (Wikidata QIDs preferred; fallback to Google KG via `Google-Extended` searches).
3. Count entities that resolve. Report:
- Entity count
- Entity diversity (different entity TYPES — Person, Org, Product, Place — better than 15 of one type)
- Missing co-occurring entities a competitor cites for the same topic (gap analysis)
Output `geo/entity_audit.md` with per-page recommendations.
VALIDATION: Each pillar page either meets the ≥15 threshold OR has a specific list of entities to add, with where they should be inserted naturally.
FALLBACK: If knowledge-graph lookups are rate-limited, fall back to a static curated entity list per industry (industries.yaml) — coverage is partial but report explicitly notes the gap.
============================================================
=== PHASE 5: E-E-A-T & AUTHOR ENTITY ===
============================================================
E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) is a **binary citation gate** for AI search in 2026, not a ranking nudge.
Check:
- [ ] **Author bylines** on every article. Author name links to `/author/{slug}` page.
- [ ] **`/author/{slug}` page exists** with bio, photo, credentials, social `sameAs` links.
- [ ] **Person schema** on author pages, with `worksFor`, `knowsAbout`, `alumniOf`, social `sameAs`.
- [ ] **Organization schema** on homepage with `founder`, `foundingDate`, `numberOfEmployees`, address, `sameAs`.
- [ ] **Press / mentions page** linking out to third-party coverage (off-domain authority signals).
- [ ] **Last-updated dates** visible on all articles (Google added Authors documentation 2026-02-01 making this a direct quality signal).
- [ ] **Citations within content** linking to primary sources (academic, government, established publications). AI engines mirror your citation behavior — sites that cite get cited.
- [ ] **First-party data / experience markers**: original screenshots, original case studies, dated metrics. Generic content without first-hand experience signals fails E-E-A-T.
Output `geo/eeat_report.md` per author and per content section.
VALIDATION: Each pillar page has a named author with a linked Person page. Person page has at least 3 `sameAs` entries linking to verifiable third-party profiles.
============================================================
=== PHASE 6: AI BOT ALLOW RULES & RATE LIMITS ===
============================================================
Update `robots.txt` to explicitly allow AI bots you want to index you. Default policy:
```
User-agent: *
Allow: /
User-agent: GPTBot
Allow: /
User-agent: OAI-SearchBot
Allow: /
User-agent: ChatGPT-User
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: Perplexity-User
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: Claude-Web
Allow: /
User-agent: Google-Extended
Allow: /
User-agent: Applebot-Extended
Allow: /
User-agent: anthropic-ai
Allow: /
Sitemap: https://example.com/sitemap.xml
```
If the site is behind Cloudflare's AI bot blocker (now default-on for many tenants), surface that and recommend disabling for the bots above.
VALIDATION: `curl -A "GPTBot" https://yourdomain.com/robots.txt` returns the file. `curl -A "GPTBot" https://yourdomain.com/some-pillar-page` returns 200 with full content.
FALLBACK: If the user explicitly wants to block training (vs indexing for citation), they can allow `*-User` and `*-SearchBot` (live retrieval) while blocking `GPTBot` and `ClaudeBot` (training). Document the trade-off — blocking training also tends to reduce indexing.
============================================================
=== PHASE 7: CITATION TRACKING SETUP ===
============================================================
GEO success requires measuring what was cited and where.
Generate `geo/track_citations.py` — a recurring polling job that:
1. For each target query, prompts ChatGPT (via API), Perplexity (via API), Claude (via API), and Gemini.
2. Captures the answer + any URL citations.
3. Logs to a SQLite DB: `query`, `engine`, `date`, `cited_urls[]`, `our_brand_mentioned (bool)`, `our_url_cited (bool)`, `competitors_cited[]`.
4. Generates a weekly report: share-of-voice per engine per query, week-over-week deltas.
Set up via cron or as a scheduled skill (`/schedule` weekly).
VALIDATION: First run produces a baseline. Second run a week later produces a delta report. Both runs persist to `geo/citations.db`.
FALLBACK: Without API keys for Perplexity/ChatGPT, fall back to manual logging via a Google Sheet template (less precise but still actionable).
============================================================
=== PHASE 8: PRIORITIZED PUNCH LIST ===
============================================================
Output `geo/punch_list.md` with findings ranked by impact:
| Priority | Issue | Impact | Effort |
| -------- | ------------------------------------------- | -------------------------- | ------ |
| P0 | Site uses CSR, AI bots see empty HTML | Blocks ALL citations | High |
| P0 | Missing Organization schema on homepage | No entity grounding | Low |
| P1 | 8 of 12 pillar pages have < 15 entities | -4.8× citation probability | Medium |
| P1 | No author Person pages | EEAT gatekeeper fails | Medium |
| P2 | llms.txt missing | Lost soft signal | Low |
| P3 | Schema FAQPage missing on 4 pages with FAQs | Lost rich result | Low |
Each item links to the specific phase output explaining the fix.
VALIDATION: Punch list is non-empty AND non-overwhelming (top 20 items max). P0 items are unambiguous, not stylistic preferences.
============================================================
=== SELF-REVIEW ===
============================================================
Score 1–5:
- **Complete**: All 8 phases run? Crawler parity tested? Schema generated and validated? Entity density measured?
- **Robust**: Handled CSR sites? Cloudflare blocks? Missing API keys for tracking?
- **Clean**: Punch list is prioritized, not a dump? JSON-LD validates? llms.txt under size cap?
- **GEO-credible**: Would an SEO consultant familiar with AI search engines (Perplexity, AI Overviews) sign off on the recommendations as 2026-current?
============================================================
=== LEARNINGS CAPTURE ===
============================================================
Append to `~/.claude/skills/geo-optimize/LEARNINGS.md`:
## <YYYY-MM-DD> — <site, vertical, framework>
- **What worked:** <approach/tool that produced clean output>
- **What was awkward:** <retry/manual fix needed>
- **Suggested patch:** <concrete improvement>
- **Verdict:** [Smooth / Minor friction / Major friction]
============================================================
=== STRICT RULES ===
============================================================
- Never generate schema with placeholder values like "Your Company Name". Use real values or skip.
- Never skip the crawler parity test. CSR sites fail GEO before anything else matters — diagnose this first.
- Never recommend blocking all AI bots without surfacing the trade-off (blocking training often reduces indexing too).
- Never claim a page is "GEO-ready" without ≥15 entities AND validated schema AND author Person entity.
- llms.txt is a soft signal — don't oversell it. Schema and SSR are the load-bearing fixes.
- If the user is on a no-code platform (Squarespace, Wix, Shopify base theme) that limits schema injection, output the JSON-LD they can paste into header/footer settings — don't hand-wave.