Skip to content

SSR & technical GEO

ExpertDuration ~45 min hands-onTools View Source (Ctrl/Cmd+U), curl, Your browser's DevTools

You can write the most citable page on the internet, add perfect sameAs schema, and allow every crawler — and still be invisible to AI, for one technical reason: the content only exists after JavaScript runs, and most AI crawlers don’t run JavaScript. Googlebot has a rendering step; the AI crawlers largely don’t. They fetch your raw HTML, and whatever isn’t in that first response simply doesn’t exist to them. This is the highest-weighted single factor in the whole technical GEO score, and it’s invisible in a normal browser because your browser runs the JS. This lesson teaches you to see the page the way a machine does, and to fix it when your content isn’t there.

When a browser requests a page, the content can arrive one of two ways. With server-side rendering (SSR), the server builds the full HTML — headings, paragraphs, everything — and sends it complete; the content is right there in the raw response. With client-side rendering (CSR), the server sends a near-empty shell and a bundle of JavaScript, and the browser builds the content after the fact. Many modern frameworks (React, Vue, Angular single-page apps) default to CSR unless configured otherwise.

For humans, both look identical. For an AI crawler, they’re worlds apart, because of one hard limit: JavaScript dependency. AI crawlers — GPTBot, ClaudeBot, PerplexityBot, OAI-SearchBot and friends — generally do not execute JavaScript. They read the HTML you hand them and move on. So content that depends on JS to appear is content they never see. Even Google, which does render, pushes JS pages into a slower delayed processing queue, and for schema it now warns that JS-injected JSON-LD may be missed. What lands in the first HTML response — the raw-HTML content — is what counts.

You don’t need special tools. You need to look at the raw HTML the server actually sent, not the DOM your browser assembled.

  • View Source (Ctrl/Cmd+U), not “Inspect.” Inspect shows the live, JS-modified DOM and will lie to you; View Source shows the untouched response.
  • Or curl the URL from a terminal — curl -s https://example.com — which fetches exactly what a crawler gets, no JS at all.

Then read the signals:

  • Empty <div id="root"></div> (or id="app", or __next) with almost no text around it = critical. The content is client-rendered; an AI crawler sees a blank page.
  • A big __NEXT_DATA__ blob (Next.js) or window.__NUXT__ (Nuxt) in the source = SSR (or static generation) is present — the framework serialized the content into the HTML. Good sign.
  • The real test that beats every heuristic: pick a sentence you can see on the rendered page and search for it in View Source. If it’s there, an AI crawler can read it. If it’s missing, it’s JavaScript-dependent and invisible.

If the content isn’t in the raw HTML, the fix is to get it rendered on the server:

  • Turn on your framework’s SSR or static-generation mode (Next.js getServerSideProps/static export, Nuxt SSR, Astro’s default static output, or a prerendering service).
  • Watch for content that loads after the initial render — tabs, accordions, “read more” toggles, infinite-scroll, and anything fetched by an API call in the browser. If the answer an AI should quote is hidden behind a click or a fetch, move it into the server-rendered HTML.
  • Schema counts too. JS-injected JSON-LD is the classic trap — it validates fine in a browser but is invisible to AI crawlers and delayed at Google. Emit your Organization/sameAs schema server-side, in the raw HTML. (This is the loose end from 3.4.)

While you’re in technical territory: when you assess Core Web Vitals as a supporting signal, use the current metrics — INP (Interaction to Next Paint) replaced FID in March 2024. Never cite FID; it no longer exists. It’s a minor GEO factor next to rendering, but citing a retired metric flags dated work.

The whole lesson reduces to one habit: before you trust any on-page GEO work, View Source and confirm your main content is actually there. If a machine can’t read it without running your JavaScript, none of your citability, schema or entity work reaches it.

  1. Take three pages: your own site, a big media site (likely SSR), and a web app or dashboard-style site (likely CSR).
  2. For each, View Source (Ctrl/Cmd+U) — or run curl -s <url> in a terminal.
  3. Copy a visible sentence from the rendered page and search the raw HTML for it. Present = server-rendered and AI-readable. Missing = JavaScript-dependent and invisible.
  4. Look for the tells: empty <div id="root"> (critical), or a __NEXT_DATA__ / __NUXT__ blob (SSR present).
  5. Check your schema: is the "@type":"Organization" JSON-LD in the raw HTML, or only injected later? If injected, log it as a fix.
  6. For any page that fails, write the specific fix — enable SSR/prerender, move content out of a JS tab, or server-render the schema — in the Level 3 workbook.
Level 3 workbook — CSR-vs-SSR detection checklist & raw-HTML content auditlevel-3-workbook.pdf113 KBOriginal course material — free to use

Check yourself

  1. You View Source on a page and the body is basically an empty <div id="root"></div> — all the real content appears only after JavaScript runs. What does this mean for AI visibility?

  2. Which of these is a positive signal that a page is server-side rendered?

  3. What is the fastest way to check whether a page’s main content is in the raw HTML an AI crawler receives?

You can move on when you can… open a page’s raw HTML, tell whether its main content is server-rendered or JavaScript-dependent, spot an empty root div versus a __NEXT_DATA__/__NUXT__ blob, and name the fix when content (or schema) is invisible to AI crawlers.

  • Google Search Central — “Understand the JavaScript SEO basics”: how rendering, the render queue, and delayed processing work.
  • web.dev — “Interaction to Next Paint (INP)”: the metric that replaced FID in March 2024.
  • Next: 3.7 · llms.txt — the honest lesson — write a spec-valid llms.txt and learn why it’s currently low-impact.