---
title: AEO & GEO
description: How the storefront makes itself legible to AI answer engines and generative search, with built-in content negotiation, structured data, and discovery surfaces.
type: guide
---

# AEO & GEO



**Answer Engine Optimization (AEO)** and **Generative Engine Optimization (GEO)** are the practices of making a site legible to the AI surfaces that increasingly mediate commerce — ChatGPT, Claude, Perplexity, Google AI Overviews, and the long tail of agent-driven shopping. Where classical SEO optimizes for crawlers that build a search index, AEO/GEO optimizes for models that read a page once and synthesize an answer. The legibility bar is higher: noisy markup, hydration-only data, and content trapped behind interaction all degrade an LLM's ability to recover the underlying facts.

The template ships with several built-in surfaces that contribute to AEO/GEO. The largest of them is **content negotiation** — serving structured markdown to clients that ask for it — but the supporting cast (JSON-LD schema, sitemaps, OpenGraph metadata) is what makes a page consistently parseable across surfaces.

## How it works

**Content negotiation swaps response format, not routes.** Product, collection, and search pages serve structured markdown when a client sends `Accept: text/markdown`; browsers that don't send it are unaffected and keep getting HTML from the same URL. A `next.config.ts` rewrite intercepts the matching request and routes it to a markdown handler under `app/md/` instead of the page route:

```
GET /products/speaker        (Accept: text/markdown)
GET /collections/speakers    (Accept: text/markdown)
GET /search?q=speaker        (Accept: text/markdown)
    ↓
next.config.ts rewrite
    ↓
/md/products/[handle]
/md/collections/[handle]
/md/search
    ↓
Route handler response: text/markdown
```

Every markdown route lives under this single top-level `app/md/` directory so all content-negotiation handlers are co-located and easy to find, and the `Vary: Accept` header ensures CDNs cache the markdown and HTML responses separately. This is built in and requires no configuration.

**`llms.txt` is a curated index, not a full dump.** `/llms.txt` is a machine-readable index of the storefront — an [emerging convention](https://llmstxt.org) that is to AI agents what `robots.txt` is to crawlers. It links to the search entry point, the collection catalog, and the sitemap/robots discovery surfaces, and tells agents that those pages also serve clean Markdown via the content negotiation above. The route is dynamic: collections are pulled live from Shopify and capped so the file stays a concise index rather than an exhaustive dump — the full URL set lives in the [sitemap](/docs/anatomy/sitemap) instead. Because the links honor content negotiation, the virtual `/collections/all` catalog page is served as Markdown too, not just HTML.

**If you've enabled Shopify Markets, locale routing composes with content negotiation for free.** The content-negotiation rewrite fires before locale routing, so no additional configuration is needed — pass a `?locale=` query parameter to the markdown endpoint for locale-specific pricing and collection/search context.

## Out of the box

| Surface                          | What it does                                                                                           |
| -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| **Content negotiation**          | Serves clean markdown to AI clients via `Accept: text/markdown`                                        |
| **Schema.org JSON-LD**           | Embeds structured `Product`, `BreadcrumbList`, and `Organization` data                                 |
| **Sitemap**                      | [Sitemap index + paged children](/docs/anatomy/sitemap) for products and collections                   |
| **Robots**                       | Declares crawl policy and blocks faceted (sort/filter) collection URLs                                 |
| **`llms.txt`**                   | Curated `/llms.txt` index of collections and discovery links for AI agents                             |
| **OpenGraph & Twitter metadata** | Per-route title/description/image previews, plus `product` OG tags (type, price, availability) on PDPs |

Markdown coverage by page type:

* **Product pages** — handle, brand, category, pricing, options, variants, specs, images, tags, and SEO metadata
* **Collection pages** — collection metadata, description, applied filters, available filters, products, pagination, image, and SEO metadata
* **Search pages** — query metadata, active collection filter, applied filters, available filters, products, and pagination state

Verify it directly:

```bash
# Returns structured markdown
curl -H "Accept: text/markdown" http://localhost:3000/products/speaker

# Returns collection markdown with products, filters, and pagination
curl -H "Accept: text/markdown" http://localhost:3000/collections/speakers

# Returns search markdown with query, filters, and result summaries
curl -H "Accept: text/markdown" "http://localhost:3000/search?q=speaker&sort=price-low-to-high"

# Returns the normal HTML page
curl http://localhost:3000/products/speaker
```

## Common customizations

* **Extending markdown coverage to a new route** — add a handler under `app/md/`, wire the matching `next.config.ts` rewrite for its `Accept: text/markdown` variant, and decide what fields belong in the markdown output for that content type.
* **Tuning the `llms.txt` index** — adjust the collection cap or linked discovery surfaces if your catalog size or navigation structure calls for a different balance between a concise index and a fuller listing.


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)