Short answer, as of August 2026: the retrieval agents behind ChatGPT, Claude and Perplexity generally do not execute JavaScript — they read the HTML your server returns. If your pricing table, FAQ block or service description is injected client-side after the page loads, those facts effectively do not exist to an AI engine, even though your site looks perfect in a browser and ranks fine in Google.
This is the second-most common silent failure in generative engine optimization, after crawler access being blocked outright. It's also the one people argue with hardest, because the evidence against it — "look, the page works" — is exactly the wrong test.
Why Google's behaviour misleads everyone
Google built a rendering pipeline over roughly a decade. Googlebot fetches the HTML, queues the page, runs a headless browser, executes the JavaScript, and indexes the resulting DOM. It is slow and expensive, and Google absorbed that cost because it had to.
AI retrieval agents are a different economic proposition. They fetch pages in the seconds between a user's question and an answer, or in bulk to keep a lightweight index warm. Running a full browser per fetch is a cost most of them decline to pay. What they parse is the response body.
So a site can be:
- Indexed and ranking in Google — because Googlebot rendered it, and
- Completely uninformative to ChatGPT or Perplexity — because their agents saw an empty shell with a
<div id="root">and a script tag.
Nothing in your analytics reports this. Rankings look normal. The only symptom is that you're never cited, which is easy to attribute to competition or authority rather than to a missing response body.
The ten-second test
Do not use DevTools' Elements panel — it shows the rendered DOM, which is the thing you're trying to bypass. Fetch the raw response:
curl -sL https://example.com/your-best-page | grep -c "a distinctive phrase from the page"
If that returns 0, the phrase isn't in the HTML. Do it for the facts that matter: a price, a service name, an FAQ answer, your hours, your city. In a browser, the equivalent is View Source (Ctrl+U), not Inspect — different views, and only one of them is what a crawler receives.
A fuller check, worth ten minutes on any site you're unsure about:
curl -sL -A "OAI-SearchBot" https://example.com/your-best-page > raw.html
wc -c raw.html
grep -o "<h[12][^>]*>[^<]*" raw.html
A file under about 10 KB on a content-rich page, or a result with no headings, is an app shell. That's the finding.
What tends to fail, ranked by frequency
| Pattern | Visible to AI agents? | Typical fix |
|---|---|---|
| Static site, server-rendered HTML | Yes | Nothing to do |
| Next.js / Nuxt / SvelteKit with SSR or SSG | Yes | Verify per-route; one client-only route can slip through |
| React or Vue SPA, client-side only | No | Prerender or migrate to SSR |
Content loaded by fetch() after mount | No | Fetch server-side, embed in the response |
| Tabs or accordions where panels load on click | No | Render all panels in HTML, hide with CSS |
| "Load more" pagination with no crawlable links | Partially | Provide real paginated URLs |
| Reviews or prices from a third-party widget | No | Mirror the key facts in your own HTML |
| Content behind a cookie or consent gate | No | Serve content, gate only tracking |
The last three are the ones that surprise experienced teams. A review widget, a booking embed and a consent wall are all fine for users and all invisible to a raw-HTML reader. Your star rating and your prices — precisely the facts an assistant would quote — arrive from someone else's iframe.
The tabs-and-accordions trap
This one deserves its own note because it's so widespread and so easy to fix.
Two implementations look identical to a user:
- All panel content is in the HTML; CSS hides the inactive panels; clicking toggles a class.
- Only the active panel is in the HTML; clicking triggers a fetch that injects the rest.
The first is fully readable by every crawler. The second hides most of your content from all of them. FAQ sections are the usual casualty — and FAQ content is disproportionately what gets quoted in AI answers, because it's already in question-and-answer form. If you build FAQs as lazy-loaded accordions, you've hidden your most quotable asset.
Render everything, hide with CSS. Content hidden by CSS is not cloaking and carries no penalty; it's ordinary progressive disclosure.
Fixes, cheapest first
Server-render the routes that matter. You rarely need to convert an entire application. The pages an AI engine would cite are a small set — service pages, pricing, FAQ, guides, location pages. Moving those to SSR or static generation while the logged-in application stays client-side is a bounded project.
Prerender for crawlers. Services like Prerender.io serve a cached, fully-rendered snapshot to crawler user-agents. Google has long treated this as acceptable when the snapshot matches what users see. It's a pragmatic bridge, not a permanent architecture — you now maintain two paths, and they drift.
Inline the critical facts. Even in a client-rendered app you can put the important content into the initial HTML: a static FAQ block, a server-rendered price table, structured data generated at build time. Ugly, effective, quick.
Mirror third-party widgets. If your reviews come from an external script, also render your own summary in HTML — "4.8 average across 212 reviews, as of August 2026." Now the fact is quotable and it stays accurate as the widget updates.
Whatever you change, verify with the raw fetch, not the browser. That is the entire discipline.
How this interacts with the rest of the stack
Rendering is a gate, not a strategy. Fixing it makes your content readable; it does not make it worth quoting. The two run in sequence:
- Access — can the agent fetch a response at all? See the crawler access audit.
- Rendering — does the response contain the content? This post.
- Structure — are the facts machine-readable? See structured data, llms.txt and AI citation.
- Substance — is the content specific enough to be worth quoting? See how to get cited by ChatGPT and Perplexity.
Skipping straight to step four is the default mistake, and it's expensive: you commission content that lands in a body no agent reads. When you're running the diagnosis in order, the full checklist for a competitor being cited when you aren't walks each layer with the test for each. Engine-by-engine differences in how aggressively each fetches and re-fetches are covered in how the major engines pick their sources.
Keeping it fixed
Rendering regressions are as silent as access regressions and slightly more common, because they arrive with ordinary feature work. A component gets refactored to fetch on mount; a marketing page moves behind a new layout; a consent library upgrade starts gating content. Nothing looks wrong.
DigiRank's site audit pipeline fetches pages the way a crawler does and flags routes whose raw HTML lost its content, so a refactor that quietly emptied a page surfaces as an issue in the same week rather than as an unexplained visibility decline a quarter later. Because the audit and the AI Visibility Tracker live in one tool, the regression and the citation drop appear on the same timeline. Scheduled audits start on the $249/mo Agency plan with a 14-day trial, and Pro at $499/mo adds a comprehensive crawl across every route. It reads Search Console and GA4 alongside, so you can see whether a rendering change moved conventional performance too.
The test costs one curl command. Run it on your five most important pages before you buy anything else.
Frequently asked questions
Do AI crawlers execute JavaScript? Generally no. The retrieval agents behind ChatGPT, Claude and Perplexity parse the HTML your server returns rather than running a full browser, because rendering is expensive at the latency they operate under. Google is the exception — Googlebot renders JavaScript, and Google's AI surfaces inherit that index.
My site ranks fine in Google, so why would AI engines have a problem? Because Googlebot renders JavaScript and most AI retrieval agents don't. A client-rendered site can be fully indexed by Google and still return an empty shell to an agent that reads only the raw response. Ranking is not evidence of readability outside Google.
How do I check whether my content is in the raw HTML?
Use View Source rather than Inspect, or run curl -sL <url> and search for a distinctive phrase from the page. DevTools' Elements panel shows the rendered DOM, which hides exactly the problem you're testing for.
Do I have to rewrite my whole app in Next.js? No. Server-render only the pages an engine would plausibly cite — services, pricing, FAQs, guides, locations. A logged-in application can stay client-rendered because no crawler reaches it anyway. Prerendering for crawler user-agents is a valid bridge if a migration isn't near-term.
Does hiding content with CSS hurt AI visibility? No. Content present in the HTML and hidden with CSS — collapsed accordions, inactive tabs — is readable by crawlers and is not cloaking. The problem is content that isn't in the HTML at all until a click triggers a fetch.
What about reviews, prices or booking widgets from a third party? Anything inside a third-party script or iframe is invisible to raw-HTML readers. Mirror the key facts in your own markup — an aggregate rating, a price range, a summary line with an "as of" date — so the quotable facts live in a body the agent actually receives.
Will fixing rendering produce citations by itself? No. It removes a blocker. The page still has to answer a real question with specifics worth quoting, and your entity information still has to be consistent across the web. Rendering is a prerequisite, not a cause.
