Emerging Digital PartnersGet in touch

How-to guide · technical

How to fix JavaScript-rendered content so AI crawlers can read it

Googlebot renders JavaScript. GPTBot, OAI-SearchBot, ClaudeBot and PerplexityBot do not. A page can rank first on Google and be a blank shell to every other AI engine. Here is how to find the gap on your platform and close it, starting with the pages that matter.

By Richard Daniel4 min read

Vercel and MERJ analysed hundreds of millions of AI crawler requests and found no evidence that any of them executed JavaScript. Follow-up tests through 2026 report the same behaviour: GPTBot and ClaudeBot download script files but never run them. Google renders JavaScript; the AI crawlers fetch HTML and leave.

That is why a site can look perfect in Search Console and be invisible in ChatGPT and Perplexity. The classic case we see in audits is a pricing page built with a JavaScript widget: ChatGPT cannot read the price, so it cites a review site or a competitor that states one in plain text. This guide finds the gap and closes it, platform by platform.

Step 1: Find out which pages are affected

Pick your ten most important pages: home, about, contact, each service or product category, pricing, FAQ. For each, run:

curl -s -A "Mozilla/5.0 (compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" https://yourdomain.com/pricing > raw.html

Open raw.html and search for the facts that should be there. Or in the browser: View Page Source (not Inspect) and search. Or disable JavaScript in DevTools and reload. If the fact is missing from the raw response, that page is affected. Note exactly which sections are missing; it is usually a widget or a data-driven block, not the whole page.

Step 2: Prioritise by what AI engines ask about

Fix in this order: pricing and packages, service and product descriptions, contact details and opening hours, reviews and testimonials, FAQs, team and About content, then everything else. These are the facts that decide whether an engine can recommend you.

Step 3: Apply the fix for your platform

Next.js (App Router): move data fetching for key content into server components or generateStaticParams with static or ISR rendering. Avoid useEffect fetches for anything a crawler needs. Check next build output: pages marked as static or SSR are fine; client-only content inside them is not.

React, Vue or Angular single-page apps: adopt server-side rendering (Next.js, Nuxt, Angular Universal) or pre-render key routes to static HTML at build time. If a full migration is not possible now, pre-render the ten pages from Step 1 and serve those HTML files; the rest can follow.

WordPress: the theme and most page builders render server-side, so the risk is in plugins: AJAX-loaded pricing tables, review carousels that fetch from an API, tabbed content built by scripts, and "load more" post grids. Replace with plugins that output HTML, or paste the key content as ordinary blocks and keep the widget for decoration only.

Shopify: Liquid templates render server-side. The gaps are apps that inject prices, stock, reviews or size guides via script. Check product pages in View Source; if the price appears only inside a script or not at all, switch the app or add the price to the template directly.

Webflow, Squarespace, Wix: core content renders server-side. Embedded widgets, third-party forms with pricing, and any custom code embeds fetching remote data do not. Move the facts into native text elements.

Headless commerce and custom stacks: server-render or pre-render the pages from Step 1. Where a framework offers both, choose static generation for content that changes rarely (services, about) and SSR for content that changes often (stock, prices).

Any platform, quick fix: if a widget cannot be replaced, add a plain-HTML summary of its contents above or below it. A sentence like "Plans start at £49 per month; see the table below" is enough for the engine even if the table itself is scripted.

Step 4: Keep tabs and accordions in the HTML

Hiding content with CSS or with a native details element is fine; the text is in the response. Building the content on click is not. If in doubt, check with View Source.

Step 5: Mind the rest of the response

Crawlers can read non-HTML content that arrives in the initial response, such as JSON embedded in the page or React Server Component payloads, but do not rely on that. Also check that the important text is not inside an iframe from another domain (the crawler sees the iframe tag, not its contents) or inside an image (menus and price lists as JPEGs are a recurring problem).

Step 6: Verify and then watch the engines

Re-run the curl test on each fixed page. Then ask ChatGPT (with search on), Perplexity and Claude to read the URL and state the price, the services and the contact details. Within a couple of weeks, check whether citations for those pages have moved from third parties to you. Our guide on measuring AI visibility explains how to track that.

Common mistakes

  • Checking the homepage and concluding the site is fine. Pricing and product pages are where widgets live.
  • Trusting Search Console. Google renders; the others do not.
  • Testing with Inspect instead of View Source.
  • Adding an llms.txt file instead of fixing the rendering. The file tells a crawler which pages exist; it does not put content into an empty page.

Frequently asked questions

Which AI crawlers execute JavaScript?

+

As of 2026, none of the major ones: GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, PerplexityBot and Meta-ExternalAgent all fetch the raw HTML and stop. The exception is Google's pipeline (which powers Gemini and AI Overviews), and Applebot, which uses a browser-based renderer. Bingbot renders some JavaScript but with limits, and ChatGPT search relies heavily on Bing's index.

Are accordions and tabs a problem?

+

Not if the text is in the HTML and merely hidden with CSS or a details element. They are a problem when the content is fetched or built by JavaScript after the click, which is how many 'load more', tabbed pricing and review widgets work.

Is Next.js safe by default?

+

Mostly. Server components and static generation put content in the HTML. The gap appears when a team fetches key content in a client component with useEffect or a client-side data library, which leaves the initial HTML empty for that section.

Sources

  1. Vercel: The rise of the AI crawler · vercel.com
  2. Lantern: AI crawlers do not render JavaScript · asklantern.com
  3. Google Search Central: JavaScript SEO basics · developers.google.com

Richard Daniel

Automation and Delivery Lead, Emerging Group

Richard leads automation and delivery across the Emerging group, working with EDP on client websites and with ETT on enterprise AI and process automation. He is the person who turns an audit finding into a working fix: crawler access, rendering, tracking, structured data and the plumbing that most marketing teams never see. He writes the technical guides on this site.

Guide15 Sept 2026 · 3 min read

How to get indexed by Bing (because ChatGPT search leans on it)

OpenAI names Bing among the search providers behind ChatGPT search, and independent analyses in 2026 found most of ChatGPT's cited pages also rank in Bing's top results. Copilot is Bing. If your Bing coverage is thin, so is your ChatGPT visibility. Here is the fix.

Richard Daniel
technicalai-searchmeasurement
Guide15 Sept 2026 · 3 min read

How to write an llms.txt file (and what it does and does not do)

Google says you can ignore llms.txt. Ahrefs found 97 percent of the files it studied were never requested. No major AI lab has committed to reading it. It is still a 30-minute job with no downside, as long as you know exactly what you are and are not getting. Here is how to do it properly.

Richard Daniel
technicalai-search

← All guides