How to Optimize a Site for AI Search: GEO and SEO
A practical GEO and SEO guide: test AI crawler access with curl, build connected schema markup, and measure what actually gets cited.
Some people no longer reach the website at all: they ask ChatGPT, Perplexity, or another AI agent and get the answer right in the chat. Hence the term GEO: generative engine optimization. Below we break down what actually works here, what gets sold under the guise of work, and how to hand the mechanical part off to an assistant while keeping the decisions for yourself. Everything described here we did on our own site, so the numbers and the pitfalls are real.
TL;DR: GEO isn't a separate discipline from SEO: a model can't cite a page it hasn't found, and it finds pages the same way regular search does. Test with curl using each AI bot's User-Agent, since robots.txt can allow a crawler while hosting still returns a 403. Build your schema markup as one connected graph linked through @id instead of scattered blocks, and only move the update date when the text itself changes. What gets cited is specifics: numbers, commands, terms, not reasoning. Hand an assistant the mechanics and the checks; keep query selection and content decisions for yourself.
Before You Start
What follows involves a lot of technical terms: crawlers, schema.org, JSON-LD. It looks scarier than it is.
This guide is written not just for you but for your assistant too. Most of what's described here doesn't need to be done by hand: open Claude Code or another assistant with access to your site's files, give it a link to this page, and ask it to work through the steps. What's left for you is the decisions and checking the results, not typing commands into a terminal.
How GEO Differs from SEO, and How It Doesn't
GEO stands for generative engine optimization: optimization for systems that answer with text instead of a list of links, like AI Overviews in Google and answers from ChatGPT and Perplexity with links to sources.
GEO has no separate mechanics of its own. For a model to cite your page, it first has to find and fetch it. It finds it through the same index and the same crawl as regular search. GEO therefore builds on top of SEO rather than replacing it.
Insight: A model can't cite a page it hasn't found. And it looks in the same place regular search does.
The difference is what you're fighting for. In regular search you're fighting for a position and a click. In a generative answer there's no position, only making it into the answer and a source link next to it. The model pulls a specific chunk from the page that can be paraphrased. From there it all comes down to three things:
- Access. The crawler has to actually be able to get your page, not a 403.
- Clarity. The machine has to understand, without guessing, what kind of page this is, who the author is, and when it was updated.
- Citability. The text has to contain something worth quoting: numbers, commands, terms, comparisons.
Here are the steps, in the order it makes sense to do them.
Step 1. Let AI Crawlers In, and Check They Actually Get Through
The first thing everyone does is open robots.txt and allow the AI bots. That's the right move, but it's not enough, and here's why.
There are several bot families now, and they do different things. Some crawl for training data, others fetch material to answer a query right now, and others follow a direct link from a user. Block the wrong one and you drop out of answers but not training, or the other way around.
# search: search results, ai-input: ChatGPT and Perplexity answers, ai-train: model training
User-agent: *
Content-Signal: search=yes, ai-input=yes, ai-train=yes
Allow: /
# ChatGPT answers and OpenAI search
User-agent: GPTBot
Allow: /
User-agent: OAI-SearchBot
Allow: /
User-agent: ChatGPT-User
Allow: /
# Claude
User-agent: ClaudeBot
Allow: /
User-agent: Claude-User
Allow: /
# Perplexity and Google for AI answers
User-agent: PerplexityBot
Allow: /
User-agent: Perplexity-User
Allow: /
User-agent: Google-Extended
Allow: /
Sitemap: https://example.com/sitemap.xml
Different bots handle different jobs: some gather material for an answer right now, others collect training data.
Now for the gotcha that made this worth writing. robots.txt is a request, not a pass. Your host can cut bots off before they ever reach robots.txt: at the web server, firewall, or anti-bot protection level. You allow them, but the server returns a 403, and you don't know it because everything opens fine in a browser.
That's exactly what happened to us. Our robots.txt allowed everything, but GPTBot and ClaudeBot were getting rejected at the hosting level. One command uncovered it:
$ curl -A "GPTBot" -sI https://example.com/ | head -1
HTTP/2 403
$ curl -A "ClaudeBot" -sI https://example.com/ | head -1
HTTP/2 403
# meanwhile the page opens fine in a regular browser, which is what throws you off
You need to test as the bot itself: robots.txt can allow it while the server still refuses.
It got fixed by contacting hosting support: they lifted the block, and after that both bots started getting 200s. Until that happened, the rest of the GEO work was pointless, since there's nothing to cite if the page can't be downloaded.
Important: Run curl with the User-Agent of every bot in your robots.txt and confirm you get a 200. It's one minute of work, and it either invalidates or confirms everything else.
Step 2. Markup: A Connected Graph Instead of Scattered Tags
Schema.org is a way to tell the machine outright what it would otherwise have to guess from the layout: page type, author, date, breadcrumbs, questions answered.
A common mistake is throwing together several independent chunks of JSON-LD where the Article knows nothing about the author, and the author isn't linked to the organization. The machine just sees a pile of disconnected statements. It's better to build one graph and connect the nodes through @id: that way "this article was written by this person, who works at this organization" becomes an explicit fact instead of a coincidence of names.
{
"@context":"https://schema.org",
"@graph": [
{"@type":"TechArticle",
"headline":"Article title",
"datePublished":"2026-08-02",
"dateModified":"2026-08-02",
// links to the author node instead of duplicating the name as a string
"author":{"@id":"https://example.com/#author"},
"mainEntityOfPage":"https://example.com/article/"},
{"@type":"Person","@id":"https://example.com/#author",
"name":"First Last",
"jobTitle":"Who you are and why you should be trusted",
// sameAs links the page to real profiles
"sameAs":["https://t.me/channel","https://youtube.com/@channel"],
"knowsAbout":["topics you know well"]},
{"@type":"BreadcrumbList", "itemListElement":[ ... ]},
{"@type":"FAQPage", "mainEntity":[ ... ]}
]}
One graph linked through @id instead of several independent blocks.
What's worth marking up first:
- Article or TechArticle on every piece, with dates, author, and
mainEntityOfPage. - Person with a
sameAsfield pointing to your real profiles. This is what connects the nameless "article author" to an actual person with a channel, talks, and a track record. - BreadcrumbList, a cheap way to show the section's structure.
- FAQPage, if the page genuinely has questions and answers. Don't mark up a made-up FAQ just for the sake of markup.
A nice detail: when we looked at what the big education platforms do for our queries, it turned out many of them have no structured markup at all. A rich snippet is the one place a small site can beat a big one without a budget.
Tip: Check the result in Rich Results Test and the Schema.org validator after every edit. Invalid JSON-LD gets ignored entirely, not partially, and there's no way to spot that just by looking at the page.
Step 3. Dates: Freshness You Can't Fake
For queries like "how to use X in 2026," freshness is a strong signal. Tools change every month, and search engines naturally prefer fresh material over old.
Hence the temptation to stamp today's date on every page at once. Don't do that. Search engines compare the stated date against what actually changed in the document between crawls, and a mismatch works against you. Plus it's simply misleading the reader who opened a page marked "updated yesterday."
The approach that works is simple:
datePublishedgets set once and is never touched again.dateModifiedmoves only when the text itself changes, not the layout or meta tags.- The date is duplicated in the page's visible text, not just in the markup.
If you pull the date from git history, you get an honest source of truth: you can see when the file was created and when its paragraphs, not just its indentation, last changed.
Step 4. Write So There's Something to Quote
Write content built around concrete specifics, not general reasoning, because that's what actually gets quoted. This is the most underrated part of GEO, and it's where the gap between sites is widest.
Insight: A model doesn't paraphrase reasoning. It paraphrases facts.
If the text says "the service offers flexible plans for different needs," there's nothing to take from it. If it says "free tier, then $8, $20, $100, and $200 a month," there's something to quote, and a link to you will show up in the answer.
What raises your odds of making it into the answer:
- Numbers and terms. Prices, limits, versions, deadlines, system requirements.
- Full commands and code. Not "the install command is in the docs," but the command itself. Send someone to the primary source and you hand the quote to that source.
- Comparison tables. A table makes it easy to extract an "option, what it's for" pair.
- Self-contained paragraphs. A chunk of text should read fine if pulled out of context, because that's exactly how it'll be taken.
- Direct answers in the first sentence. Answer first, explanation after, not the other way around.
A separate note on length. It's not about character count, it's about intent coverage: someone searching "how to use X" also wants to know along the way what it costs, whether it works from Russia, and what to do if it won't install. A piece that covers the whole path beats three short notes on the same topic.
What to Hand to an Agent, and What to Do by Hand
The crawler access, markup, date, and text-quality work from the four steps above is mostly mechanical across dozens of pages: identical markup, consistent meta tags, checking response codes, cross-referencing dates against file history. This is exactly the kind of task where an assistant like Claude Code beats a human: it doesn't get tired, doesn't skip page eight of eight, and keeps the format consistent.
What works in practice:
Put the Rules in a Project File
Set up a file in the repo root with your SEO conventions that the assistant reads at the start of every session: heading format, where the canonical URL lives, which schema types you use, where dates come from, what counts as a content change versus cosmetic. A rule written down once stops being something you negotiate every session.
Ask for a Plan Before Edits
Bulk changes across ten files are exactly where a mistake multiplies instantly. Plan and file list first, execution second.
Demand Verification, Not a Report
"I set the dates on all the pages" is a claim. "I ran all nine JSON-LD blocks through the parser, all valid, here's the output" is verification. The difference matters: markup breaks silently, and the page still looks normal from the outside.
Tip: Ask the assistant to confirm results with a command, not with words: parse the JSON, hit it with curl, show the output. The phrase "check it and show me the output" saves hours of debugging.
What to Keep for Yourself
Query selection, decisions on dates and wording, judging intent. The agent doesn't know which query you actually need, and it'll happily stamp a nice update date on a page where the text never changed. The agent is responsible for doing the thing right. You're responsible for it being the right thing.
What Doesn't Work
There's a lot of hype around GEO, so here's a separate note on what's not worth your time.
- llms.txt. A manifest file "for language models." Google has publicly stated it doesn't use it, and other major systems haven't officially confirmed they do either. Fine to keep, not worth expecting results from.
- Markup as a multiplier. Schema.org doesn't lift rankings on its own. It removes ambiguity and earns a rich snippet, which affects CTR and citability, not ranking position.
- Scattered keywords. Keyword density stopped being a lever long before generative search existed. A query is better served by the structure of the material than by repetition.
- Mass page generation. A hundred thin pages for a hundred queries bloat the index and drag down the whole site's quality score.
What works is the boring stuff: crawler accessibility, honest structure, specifics in the text, clear authorship, and a regular publishing cadence.
How to Measure What Any of This Got You
The problem with measuring GEO is that generative systems don't hand back statistics. What you can actually look at:
- Search Console: impressions, positions, whether pages made it into the index. The baseline, without which nothing else matters.
- Request logs from AI bots. You can see whether GPTBot, ClaudeBot, and PerplexityBot are showing up, and on which pages.
- Manual citability checks. Once a month, ask ChatGPT and Perplexity your target query and see whether you show up among the sources.
And a rough timeline. One of our guide pages generated 803 impressions and 23 clicks in its first month, a 2.9% CTR, higher than the site average. That's not explosive growth; it's normal dynamics for an informational page on a young domain. Don't expect results any sooner than a few weeks after indexing.
Daily citation tracking across ChatGPT, Gemini, Perplexity, and Google AI Mode, plus a Tech Review audit covering the same ground as this guide, is what turns this into an action plan instead of a stale snapshot. Any single AI answer fluctuates a lot day to day, but the daily volume of data is what makes that possible. That's what SupaIntent does, a low-lift way to see where you actually stand.
Frequently Asked Questions
How is GEO different from SEO?
GEO is optimization for answers from generative systems: AI Overviews in Google, ChatGPT, Perplexity. It has no separate mechanics of its own: for a model to cite a page, it first has to find and fetch it, and that's regular search and regular crawling. GEO isn't a replacement for SEO, it's a layer on top: the same technical foundation plus factual density in the text and clear authorship.
Do I need an llms.txt file?
As a ranking lever, no. Google publicly says it doesn't use llms.txt, and other major systems haven't officially confirmed using it either. The file doesn't break anything, and you can keep it as a site map for people and agents, but don't count on it boosting citability. Your time is better spent on robots.txt, markup, and text quality.
Does Schema.org markup improve rankings?
Not directly. Markup isn't a ranking multiplier, it's a way to take the guesswork out for the machine: who the author is, when it was updated, what type of page it is, which questions it answers. The practical benefit is rich snippets and making it easier for a language model to extract facts and attribution from the page. That affects CTR and citability, not ranking position itself.
Can I hand all of SEO to an agent and skip checking?
No. An agent handles the mechanical part well: markup, meta tags, sitemap, checking response codes, consistency across dozens of pages. But it doesn't know which query you actually need, and it'll happily stamp a nice update date on a page where the text never changed. Decisions about keywords, dates, and wording stay with the human.
Reveal where AI sends your clients

Track prompt-level visibility across ChatGPT, Gemini, Perplexity, and Google AI search. See which competitors win the answer, which sources shape the response, and where your brand is missing.