syted

syted blog

How to Rank on ChatGPT: What Actually Gets You Cited

Every article about ranking on ChatGPT tells you to build authority, create high quality content and manage your brand reputation. That advice is not wrong, it is just unfalsifiable. You cannot ship it on Tuesday and check it on Wednesday.

This one goes the other way. It starts at the HTTP request that OpenAI's crawler makes to your server and works forward from there, because that request is the first thing that can fail, and when it fails nothing else you do matters. If the page your server returns to OAI-SearchBot is an empty div and a script tag, no amount of digital PR will put you in a ChatGPT answer.

The order below is the order of the pipeline: can the crawler reach you, can it read you, is your page in the index ChatGPT searches, and does your page contain a passage a model can lift without rewriting it. Every step has a command you can run against your own domain today.

What "ranking on ChatGPT" actually means

There is no ranking. There is no position 1. Understanding what replaced it is the difference between working on the right thing and working on a metaphor.

Content reaches a ChatGPT answer through three separate paths, and they have almost nothing in common.

The model's training data. Weights baked in months before the answer. You cannot influence this on any useful timescale, and by the time you could, the model has been replaced. Ignore it as a channel.

Retrieval at answer time. When ChatGPT searches the web to answer, it fetches a small set of pages, reads them, and cites some of them under the answer. This is the path you can actually work on, it is measurable, and it responds to changes in weeks rather than model generations.

A URL the user pasted. Someone drops your link into the chat. ChatGPT-User fetches it on their behalf. Not a discovery channel, but it is a reason your page needs to be readable by a plain HTTP client, because that is exactly what does the fetching.

Almost everything worth doing sits in the second path. So the practical question is not "how do I rank on ChatGPT", it is "when ChatGPT searches for something my product answers, does my page get retrieved, and does it contain a paragraph worth quoting". Those are two different problems with two different fixes, and most guides collapse them into one.

The reason this matters: the first problem is infrastructure and the second is writing. Founders usually assume they have a writing problem when they have a rendering problem. Check the infrastructure first, because it is cheap to check and it is binary.

The OpenAI crawlers, and which one decides whether you get cited

OpenAI documents four separate user agents, each with a different job. Confusing them is the most common technical mistake on this topic, and it has a real cost: blocking the wrong one removes you from ChatGPT search while leaving your content in the training path, which is the opposite of what most people want.

Bot robots.txt token What it does
OAI-SearchBot OAI-SearchBot Surfaces sites in ChatGPT's search features
GPTBot GPTBot Crawls content for foundation model training
ChatGPT-User not applicable Fetches a page because a user asked for it
OAI-AdsBot OAI-AdsBot Checks the safety of submitted ad landing pages

The one that decides whether you appear as a source in ChatGPT search is OAI-SearchBot. OpenAI's own bots documentation describes it as the agent "used to surface websites in search results in ChatGPT's search features". GPTBot is the training crawler. ChatGPT-User handles user-initiated fetches, and OpenAI states that robots.txt does not apply to it because it is not automatic crawling.

That distinction gives you a genuine choice most people do not know they have. If you object to your content training a commercial model but want to be citable in answers, you can disallow GPTBot and allow OAI-SearchBot. If you did the lazy thing and blocked everything with "OpenAI" in the name, you opted out of the citation channel too.

Here is what that looks like in a Next.js 16 app. The file convention is app/robots.ts, and it returns a MetadataRoute.Robots object:

// src/app/robots.ts
import type { MetadataRoute } from 'next'

const SITE = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://example.com'

export default function robots(): MetadataRoute.Robots {
    return {
        rules: [
            {
                userAgent: '*',
                allow: '/',
                disallow: ['/api/', '/dashboard'],
            },
            {
                // Retrieval for ChatGPT answers. Keep this open.
                userAgent: 'OAI-SearchBot',
                allow: '/',
            },
            {
                // Training crawler. Your call, and it is a different call.
                userAgent: 'GPTBot',
                allow: '/blog/',
                disallow: '/',
            },
        ],
        sitemap: `${SITE}/sitemap.xml`,
        host: SITE,
    }
}

Two things to verify rather than assume. First, that the deployed file says what you think it says. Route handlers get cached, and a stale robots.txt is a silent failure:

curl -s https://example.com/robots.txt

Second, that the traffic hitting you is really from OpenAI. The user agent string is a header, and anyone can send it. OpenAI publishes IP ranges for each bot as JSON, one file per agent:

curl -s https://openai.com/searchbot.json | head -20
curl -s https://openai.com/gptbot.json | head -20

If you are rate limiting or firewalling by user agent, verify against those ranges. Blocking a spoofed OAI-SearchBot at your edge is fine. Blocking the real one because a bot protection rule caught it is a problem you will not notice for months, since nothing in your analytics reports "we stopped being cited".

Grepping your access logs is the fastest way to find out whether any of this is theoretical:

grep -c 'OAI-SearchBot' /var/log/nginx/access.log
grep 'OAI-SearchBot' /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c

The second command gives you the distribution of status codes served to that crawler. A wall of 200s is what you want. A meaningful share of 404s or 301s means the crawler is spending its budget on URLs that no longer exist, which brings us to a number worth knowing.

Your page has to be readable without JavaScript

This is the step that quietly disqualifies the most SaaS sites, and it is the one no strategy listicle mentions.

Vercel published a study of AI crawler behaviour on its network in December 2024. Two findings from it are worth carrying around. None of the major AI crawlers rendered JavaScript: they fetch HTML and parse it, and client-rendered content is not visible to them. And the crawl was wasteful in a specific way. ChatGPT's crawler hit 404s on 34.82% of its requests and spent a further 14.36% on redirects, with Claude's crawler showing a similar 34.16% 404 rate.

Independent testing since then has consistently reported the same rendering behaviour for OAI-SearchBot: a single HTTP request, whatever HTML comes back in that first response, no script execution. OpenAI does not document a rendering step in its bots documentation. Until it does, the safe engineering assumption is that anything your JavaScript builds after hydration does not exist for these crawlers.

That assumption is testable in one command. Fetch your page the way a crawler does, strip the tags, and look at what is left:

curl -sL -A "Mozilla/5.0 (compatible; OAI-SearchBot/1.4; +https://openai.com/searchbot)" \
  https://example.com/blog/your-article \
  | sed -e 's/<script[^>]*>.*<\/script>//g' -e 's/<[^>]*>//g' \
  | tr -s '[:space:]' ' ' \
  | wc -w

Compare that word count to what you see in the browser. If your article reads as 2,000 words on screen and this returns 80, the crawler is seeing a shell. Run it on your pricing page and your docs too, because those are the pages that answer commercial questions.

For a Next.js App Router site, most of this is already handled: server components render to HTML by default. The failure modes are specific and worth naming.

Content behind a 'use client' boundary that only appears after an effect runs is not in the initial HTML. A FAQ accordion that fetches its own answers client side is invisible. A comparison table rendered from state populated by a useEffect call is invisible. Tabs whose inactive panels never render are invisible. So is anything gated behind an interaction, including a "read more" that unmounts the rest of the article.

The fix is not clever. Render the content on the server, and let interactivity be a progressive layer over HTML that already contains the text:

// Bad: the answer only exists after hydration.
'use client'
export function Faq({ id }: { id: string }) {
    const [answer, setAnswer] = useState<string | null>(null)
    useEffect(() => {
        fetch(`/api/faq/${id}`).then((r) => r.json()).then((d) => setAnswer(d.answer))
    }, [id])
    return <div>{answer ?? 'Loading...'}</div>
}

// Good: the answer is in the HTML, the toggle is the only client code.
export function Faq({ question, answer }: { question: string; answer: string }) {
    return (
        <details>
            <summary>{question}</summary>
            <p>{answer}</p>
        </details>
    )
}

The details element is worth calling out because it collapses the tradeoff entirely. The answer text is in the document whether the element is open or closed, so a crawler reads it and a human still gets a collapsible FAQ, with no JavaScript involved at all.

While you are in the logs, the 404 number deserves a response. A third of crawl requests landing on dead URLs is not something you can fix at OpenAI's end, but you can stop contributing to it. Keep redirects for renamed articles rather than deleting them, keep your sitemap honest so it never lists a URL that 404s, and make sure lastModified on each entry reflects when the content actually changed rather than when you last deployed. A sitemap that claims every page changed this morning is a sitemap nobody trusts twice.

Where ChatGPT's search results come from

The retrieval layer is the part with the least official documentation and the most confident blog posts. Here is the line between what is documented and what is observed, because the difference changes what you should spend a Saturday on.

Documented: ChatGPT's search capability launched on top of Microsoft's Bing index, and OpenAI has run its own crawler (OAI-SearchBot) alongside that partnership. Observed and reported by independent researchers rather than announced: retrieval now appears to draw on more than Bing alone, including results that look like they came from Google's index, and OpenAI has never confirmed the full picture.

Two practical conclusions follow, and only two.

First, being indexed in Bing is cheap and still worth doing. Bing Webmaster Tools takes about ten minutes: verify the domain, submit the sitemap, and check the index coverage report once a month. Most founders set up Google Search Console on day one and never touch Bing, which is an odd allocation given where ChatGPT's retrieval started.

Second, IndexNow is a real protocol with a real payoff for a site that publishes often. You host a key file at your root, then ping an endpoint whenever a URL changes. Participating engines share submissions with each other. The batch form is a plain JSON POST:

curl -s -X POST https://api.indexnow.org/indexnow \
  -H 'Content-Type: application/json; charset=utf-8' \
  -d '{
    "host": "example.com",
    "key": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
    "keyLocation": "https://example.com/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6.txt",
    "urlList": [
      "https://example.com/blog/your-new-article"
    ]
  }'

The key is a hex string of 8 to 128 characters, hosted as a text file at your root containing exactly that key. You can submit up to 10,000 URLs in one request, which is more than any honest blog needs in a day.

What does not follow from any of this: buying a spot, submitting your site to ChatGPT directly, or paying for a service that promises to insert you into answers. There is no submission form for ChatGPT answers, and anyone selling placement in them is selling something else.

Write the answer where a retriever can lift it

Now the writing half, and it is genuinely different from writing for Google.

A traditional search result rewards a page that is comprehensively about a topic. A model composing an answer does something narrower: it pulls a passage, checks that the passage stands on its own, and either uses it or moves to the next source. Your unit of competition is a paragraph, not a page.

That has consequences you can act on.

Answer the section's question in its first sentence. Not in the third paragraph after context setting. If an H2 asks "how do I verify OAI-SearchBot", the sentence right below it should answer that, with the elaboration following. This is also just better writing, which is a useful property of most advice that survives contact with retrieval systems.

Make paragraphs survive removal from context. Pronoun chains across sections are the enemy. A paragraph that opens with "This means that..." is worthless when lifted, because the antecedent is two screens up. Repeat the noun. It reads slightly heavier and it travels much better.

Put facts in tables and lists. A comparison stated in prose across five sentences is hard to extract accurately. The same comparison in a four-row table is unambiguous, and it is unambiguous in the raw HTML too, which is the version that matters here.

Name versions, dates and exact strings. OAI-SearchBot is a better thing to write than "OpenAI's search crawler". Next.js 16 is better than "recent versions". A model deciding between two sources on a technical question will favour the one that commits to specifics, and so will a reader who is about to paste your code.

Cover the question the searcher actually has, including the parts that are inconvenient for you. The pages that get cited on contested topics tend to be the ones that say what does not work. If your article on this topic never mentions that llms.txt currently has no documented consumer, it reads like marketing, and the next source over will say it for you.

One thing to be careful about: none of this means writing for machines. Passages that stand alone, answers before elaboration and concrete nouns are how good technical documentation has always been written. If your writing gets worse as you apply this, you are applying it wrong.

What Google says about AI features, and why it settles an argument

Google's official guidance on AI features is short, and it contradicts a large amount of what is being sold right now. On appearing in AI Overviews and AI Mode, Google's documentation states that a page must be "indexed and eligible to be shown in Google Search with a snippet" and adds, in plain terms, that "you don't need to create new machine readable files, AI text files, or markup to appear in these features. There's also no special schema.org structured data that you need to add."

That is Google's system, not OpenAI's, and the two do not have to behave alike. But it is the only first-party statement of its kind, and it points the same direction as everything above: the requirements are standard indexability and readable content, not a new file format.

Google does document controls on the other side of the equation. nosnippet, data-nosnippet, max-snippet and noindex limit what can be shown from your pages, and Google-Extended is the separate control for training and grounding in Google's other systems. Those are levers for restricting use, not for increasing visibility. If you want to appear, the lever is that your content is indexable and answers the question.

Structured data is still worth shipping, just not for this reason. BlogPosting and BreadcrumbList JSON-LD earn you rich results in classic search and give any parser an unambiguous read on author, date and headline. Ship it because it is cheap and correct, not because someone told you it is the secret to AI citations.

llms.txt: what it does, and what it does not

We serve an llms.txt at our own root, so this section is written against our own practice rather than about someone else's.

What it is: a Markdown file at your domain root with a short summary and a curated list of links, intended as a table of contents for a model that has landed on your site and needs to know which pages matter.

What it is not, as of this article's publication: a documented input to any major assistant's retrieval pipeline. No major AI vendor, OpenAI, Google, Anthropic, Meta or Perplexity, has publicly stated that its production retrieval systems read or act on third party llms.txt files. Several of them publish their own, which is a fact people cite as if it were an endorsement of consumption. Publishing a file and reading other people's files are different behaviours.

Where it does earn its keep today is agentic retrieval. When a developer points a coding agent at your documentation, that agent can fetch your llms.txt as an index and traverse only the pages it needs instead of guessing at URLs. If you sell to developers, and your product has docs, that is a real use case with a real reader on the other end.

So the honest recommendation is: write one if you have documentation worth navigating, keep it to ten minutes of work, and do not treat it as a visibility strategy. The cost is low enough that the expected value is positive. The claims being made about it are not supported by anything either vendor has published, and building your plan on it means building on an undocumented behaviour that could be true, false, or true this quarter only.

Here is the ten minute version, served from a route so it stays in your codebase rather than drifting in public/:

// src/app/llms.txt/route.ts
const body = `# Example

> One paragraph on what the product does, in plain language.
> Include the price if it is public.

## Docs

- Install guide: https://example.com/docs
- API reference: https://example.com/docs/api

## Blog

- Index: https://example.com/blog
`

export const dynamic = 'force-static'

export function GET() {
    return new Response(body, {
        headers: {
            'content-type': 'text/plain; charset=utf-8',
            'cache-control': 'public, max-age=3600',
        },
    })
}

How to measure this without fooling yourself

Measurement is where most of this work falls apart, because the obvious method is the wrong one and it flatters you.

The obvious method is to open ChatGPT, ask about your category, and see if you appear. Do not build on that. Answers are non-deterministic, so the same prompt can produce different sources on two consecutive runs. Your own account carries memory and history that bias the result toward things you have discussed. And a single check tells you nothing about the distribution, which is the only thing that matters.

A defensible method has four properties.

A fixed prompt panel. Write 20 to 40 prompts a real buyer might type, and freeze the list. Mix intents: category questions ("best tools for X"), problem questions ("how do I do Y"), and direct brand questions ("is Z any good"). Freezing the list is the point. A panel you edit whenever results look bad measures nothing.

Repetition, in a clean session. Run each prompt several times with memory off or in a fresh account. Record which domains are cited, not just whether you are. Your share of citations across the panel is the metric. A single appearance is noise.

Server logs as the leading indicator. Citation share moves slowly. OAI-SearchBot traffic moves first. If you fixed a rendering problem and the crawler starts pulling pages it never fetched before, that is evidence something changed weeks before any answer does.

A baseline recorded before you change anything. Run the panel once before the work starts. Without it you will be comparing today's numbers to your memory of last month, and your memory will agree with whatever you did.

Now the part every honest version of this article has to include. No one can guarantee that a specific page will be cited in a specific answer, by ChatGPT or anyone else. The retrieval systems are undocumented in their details, they change without announcement, and they are probabilistic by construction. Results vary between domains, categories and weeks. What you can control is whether your content is reachable, readable, indexed and worth quoting. Anyone selling you a position in an AI answer is selling a thing they do not have.

That is also why the sequence in this article is worth following in order. The infrastructure steps are binary and verifiable: either OAI-SearchBot gets a 200, or it does not. Either your article's text is in the initial HTML, or it is not. Fix those and you have removed the failure modes you can actually observe. What remains is writing pages that answer the question better than the pages currently being cited, which is slow, uncertain, and the only durable part of the job.

FAQ

How do I get mentioned in ChatGPT?

Be reachable and readable, then be worth quoting. Concretely: allow OAI-SearchBot in robots.txt, confirm your content is present in the HTML your server returns before any JavaScript runs, make sure the page is indexed (Bing included), and structure each section so its first sentence answers the question in its heading. There is no submission form and no way to buy placement.

How long does it take to show up in ChatGPT?

There is no published timeline, and anyone quoting one is guessing. What you can observe is the sequence: crawler requests in your server logs come first, then indexing, then citations. Watching OAI-SearchBot fetch a page is evidence the pipeline is working; it is not evidence you will be cited, and results vary by domain and category.

Should I block GPTBot?

That depends on what you want, and it is a separate decision from ChatGPT search visibility. GPTBot crawls for foundation model training. OAI-SearchBot handles retrieval for ChatGPT's search features. You can disallow the first and allow the second. Blocking everything with "OpenAI" in the name also removes you from the citation channel, which is usually not what people intend.

Does llms.txt help me rank on ChatGPT?

There is no evidence that it does. As of publication, no major AI vendor has publicly stated that its production retrieval systems read third party llms.txt files. It is useful as a curated index for coding agents pointed at your documentation, which is a genuine but narrower use case. Write one if you have docs worth navigating, and do not build a visibility plan on it.

Does ChatGPT use Bing or Google?

ChatGPT's search capability launched on Microsoft's Bing index and OpenAI runs its own OAI-SearchBot crawler alongside it. Independent researchers have reported retrieval that appears to draw on other indexes as well, including Google's, and OpenAI has not confirmed the full picture. The practical takeaway is unchanged: get indexed in Bing as well as Google, since it is a ten minute job and it covers the documented path.

What is the difference between ranking on Google and ranking on ChatGPT?

On Google you compete with a page for a position on a results list. In a ChatGPT answer there is no list and no position: a retriever pulls a handful of passages and the model composes an answer from the ones that stand on their own. The unit of competition is the paragraph rather than the page, which is why self-contained sections, answers before elaboration, and facts in tables matter more here than they do in classic search.

Get cited by ChatGPT. Rank on Google.

You found this article through search. syted writes one like it every day, on your domain.

Start writing

Get cited by ChatGPT. Rank on Google.

You found this article through search. syted writes one like it every day, on your domain.

Start writing