# AEO (Answer Engine Optimisation) — user guide

The AEO plugin shapes the site for answer engines (Claude, ChatGPT, Perplexity, Google AI Overviews, Bing Copilot). It does three things: emits schema.org JSON-LD from typed graph entities, generates `/llms.txt` and `/llms-full.txt`, and audits any page against eight heuristics.

## When to use it

- A new page is being authored and you want it to be cited when customers ask an answer engine about your service.
- An existing page is not being cited. Audit it to find the structural reasons.
- You're standing up a new site and want the `llms.txt` pair generated so answer engines can index your content directly.

## The tools

### `aeo-emit-jsonld`

Generates a `<script type="application/ld+json">` block for a typed entity. Two modes:

- **From the graph.** Pass `entityId` (Neo4j elementId of an `Organization`, `Person`, `Service`, `Product`, `CreativeWork`, `FAQPage`, `RealEstateListing`, or `Event`). The tool resolves the entity, maps the label to its schema.org type, and emits the block.
- **Inline.** Pass `label` (one of the supported page types) plus a `properties` object. Use this when the page isn't backed by a stored entity (yet) but you want the JSON-LD shape.

Returns the parsed JSON-LD object and a ready-to-inline script block string. Inline the script in your page `<head>`.

### `aeo-write-llms-txt`

Generates the `llms.txt` / `llms-full.txt` pair for the account. Source is every `KnowledgeDocument` for the account that has a `url` property. Returns both files as strings plus a count of pages skipped because they had no URL.

Wire the output to your site host. Convention: `/llms.txt` (index) and `/llms-full.txt` (concatenated content), served as `text/plain`. Format follows the current draft at `https://llmstxt.org/`.

### `aeo-audit-page`

Runs the eight-heuristic audit. Pass either `url` (the tool fetches) or `html` (you supply the rendered content). Returns:

```
{
  "score": 0–100,
  "heuristics": [
    {
      "name": "structured-answer",
      "status": "pass" | "warn" | "fail",
      "detail": "first <p> after <h1> is 142 chars",
      "suggestion": "Add one ≤280-character <p> immediately after the <h1>…"
    },
    …
  ],
  "target": "<url or '(inline html)'>",
  "audit": { "runAt": "<iso>", "elementId": "<set when persisted>" }
}
```

Pass `persist: true` plus `targetKnowledgeDocumentId` to write the result as an `:AEOAudit` node linked to the document.

## The eight heuristics

| Heuristic | What it checks |
|---|---|
| `h1-present` | exactly one `<h1>` |
| `jsonld-present` | at least one parseable JSON-LD block |
| `structured-answer` | first `<p>` after `<h1>` is ≤280 chars |
| `faq-section` | `FAQPage` JSON-LD on the page |
| `meta-description` | 80–160 char `<meta name="description">` |
| `canonical-url` | `<link rel="canonical">` present |
| `og-tags` | `og:title` and `og:description` both set |
| `heading-hierarchy` | no level skips (h1→h3 etc.) |

`structured-answer` is the highest-impact: that one paragraph is what gets lifted into the engine's answer. A page can fail every other heuristic and still be cited if this one passes.

## Observability

Every tool emits a single log line per invocation:

- `[aeo-emit-jsonld] entityId=… schemaType=… source=graph|inline`
- `[aeo-llms-txt] site=… pages=… skippedNoUrl=… indexBytes=… fullBytes=…`
- `[aeo-audit] target=… score=… fails=… warns=…`

Diagnostic path: `grep -E '^\[aeo-' platform-logs/*.log | grep <urlOrEntityId>`.

## What this plugin does not do

- **No citation monitor — out of scope.** Tracking whether your brand is cited by Claude / ChatGPT / Perplexity / Gemini would require multi-engine answer harvesting that doesn't fit maxy-code's no-API-key architecture. Archived without sprinting (Task 363). Check citation manually when needed.
- **No auto-emission on page render.** `aeo-emit-jsonld` is callable on demand. Wiring it into the platform's page-generator render path is per-renderer work, filed as a follow-up.
- **No publish-hook regeneration of `llms.txt`.** The tool runs on demand. Hooking it into the publish event is a follow-up.

## See also

- Plugin manifest: `platform/plugins/aeo/PLUGIN.md`
- Structured-answer template: `platform/plugins/aeo/skills/structured-answer/SKILL.md`
- Schema declaration: `platform/neo4j/schema.cypher` (search `AEOAudit`)
- Spec source: `https://llmstxt.org/`
