Guides/Technical fixesupdated 2026-08-04 · 5 min

Why JavaScript-Heavy Sites Are Invisible to AI Crawlers

The short answer

Most AI crawlers fetch raw HTML and do not execute JavaScript. If your services, address, and phone number are painted into the page by client-side JavaScript, the crawler sees an empty shell. The check takes thirty seconds: view your page source and search for your phone number.

Here is a failure that is invisible to everyone involved.

Your site looks perfect. It loads fast, it works on mobile, your designer did good work. You can see your services, your address, your phone number, your reviews.

An AI crawler fetches the same URL and gets this:

<!DOCTYPE html>
<html>
  <head><title>Carter Plumbing</title></head>
  <body>
    <div id="root"></div>
    <script src="/static/js/main.a4f2b1.js"></script>
  </body>
</html>

An empty div. No services, no address, no phone number, nothing to read.

Why this happens

Modern web frameworks can build pages in two places.

Server-side. The server assembles the complete HTML and sends it. The browser receives a finished page. So does a crawler.

Client-side. The server sends a nearly-empty shell plus a JavaScript bundle. The browser downloads the bundle, executes it, fetches data, and paints the page. The user sees a complete page a moment later.

Client-side rendering is fine for a browser. It is a problem for anything that reads HTML without running JavaScript — which is most AI crawlers.

Google is the exception: it renders JavaScript in a second pass, though not instantly and not always fully. So the failure mode is specific and modern: your site can rank acceptably in Google Search and still be completely invisible to ChatGPT, Claude, and Perplexity.

That is why this is worth checking even if your search traffic looks healthy.

The thirty-second check

  1. Open your homepage.
  2. Right-click, choose View Page Source. Not "Inspect" — that is the wrong tool for this and will tell you everything is fine when it is not.
  3. Press Ctrl+F / Cmd+F.
  4. Search for your phone number.
  5. Search for one of your service names.
  6. Search for your city.

If all three are there, you pass. Move on.

If you get an empty <div id="root"> or <div id="__next"> and a script tag, your content is client-side only.

Why not Inspect? Inspect shows the DOM after JavaScript has run — the browser's view. View Source shows the raw HTML the server sent, which is the crawler's view. The gap between the two is exactly the problem.

A second check

Use curl, or any "view raw HTML" tool:

curl -s https://yourdomain.com | grep -i "813-555"

If that returns nothing and your phone number is on the page, you have confirmed it.

Who has this problem

It depends on the build, not the platform brand:

  • Custom React, Vue, or Angular sites without server-side rendering — the classic case, and common in agency-built sites from 2019–2023
  • Some Wix and Squarespace templates that hydrate heavily
  • Some page-builder plugins that load sections dynamically
  • Sites with content behind tabs, accordions, or "load more" that fetch on interaction
  • Review widgets, booking widgets, and chat widgets — these are almost always client-side, which is why review text embedded via a widget does not count as content on your page

Standard WordPress themes render server-side and are usually fine. Next.js, Nuxt, Astro, and similar frameworks render server-side by default but can be configured not to.

Partial failures

The whole page being empty is the obvious case. Partial failures are more common and easier to miss:

  • Your service list loads from an API after page load
  • Your location pages are generated client-side from a data file
  • Your reviews come from a third-party widget
  • Your FAQ answers are inside accordions that fetch content on click
  • Your schema is injected by JavaScript rather than present in the HTML

That last one is worth calling out. Schema injected client-side is invisible to crawlers that do not execute JavaScript, which defeats the point of having it.

Check each important page, not only the homepage.

Fixing it

The proper fix

Server-side rendering or static generation for every page that matters. In modern frameworks this is usually a configuration change rather than a rewrite:

  • Next.js — use Server Components or static generation; avoid making the whole page a client component
  • Nuxt — enable SSR or static generation
  • Astro — server-renders by default; keep interactive islands small
  • Gatsby — statically generates by default
  • Plain React SPA — this is the hard case, and usually means migrating to a framework with SSR

Talk to whoever built the site. Ask directly: "Is our content in the server-rendered HTML, or is it client-side only?" A competent developer will answer immediately.

The practical stopgap

If a rebuild is not happening this quarter, get the essential facts into raw HTML by other means:

  • Schema in the head, server-rendered. Your name, address, phone, hours, service area, and services, present in the HTML regardless of what the app does.
  • A plain HTML footer with NAP, service list, and service areas.
  • Static service pages. Even simple server-rendered HTML pages for your top five services, linked from the main site. Not elegant, entirely effective.
  • Noscript content. A <noscript> block containing your core business facts. Modest, but present.

None of this is architecturally satisfying. All of it works, because the goal is that the facts exist in the HTML.

While you are in there

Two adjacent checks:

Speed. Crawlers time out. A page that takes eight seconds to respond may not get read at all. Run PageSpeed Insights and address anything catastrophic.

Blocked resources. If your CSS or JS is blocked in robots.txt, Google's rendering pass fails too. Do not block resources.

What to do this week

  1. View Page Source on your homepage. Search for your phone number.
  2. Do the same for your top three service pages.
  3. Confirm your schema is in the raw HTML, not injected by JavaScript.
  4. If any fail, ask your developer whether pages are server-rendered.
  5. If a fix is not immediate, add server-rendered schema and a plain HTML footer with NAP and services.

Then check whether they can find you at all

Rendering is one of fifteen on-page signals we check. Our free scan runs all of them alongside twenty-five real customer questions across five AI assistants, so you find out both whether they can read you and what they say when they do.

About fifteen seconds, free, no account.

Common questions

Doesn't Google render JavaScript?
Google does, in a second rendering pass, though not instantly and not always completely. AI crawlers largely do not. So a JavaScript-only site can rank acceptably in Google Search and still be invisible to ChatGPT, Claude, and Perplexity, which is a failure mode that did not exist three years ago.
How do I check my site?
Right-click your homepage, choose View Page Source — not Inspect — and search the raw HTML for your phone number and a service name. Inspect shows the rendered DOM after JavaScript runs, which is what a browser sees, not what a crawler sees. View Source shows the truth.
Which site builders have this problem?
It varies by build rather than by platform. Single-page React and Vue apps without server rendering are the classic case. Some Wix and Squarespace templates hydrate heavily. Standard WordPress themes usually render server-side and are fine. Check yours rather than assuming.
What is the fix if my site fails?
Server-side rendering or static generation for the key pages, so content is in the raw HTML. If a rebuild is not feasible, a practical stopgap is adding server-rendered content — schema, a plain HTML footer with NAP and services, and static service pages — so the essential facts exist without JavaScript.
Stop guessing

See exactly what the five AIs say about your business.

Twenty-five real customer questions across Claude, ChatGPT, Gemini, Perplexity, and Google AI Overviews. Free, about fifteen seconds, no account.

Run the free scan

Keep reading