{"id":4506,"date":"2026-11-09T11:08:54","date_gmt":"2026-11-09T11:08:54","guid":{"rendered":"https:\/\/3way.social\/blog\/?p=4506"},"modified":"2026-11-09T11:08:55","modified_gmt":"2026-11-09T11:08:55","slug":"javascript-seo-in-2026-what-google-and-ai-crawlers-actually-see","status":"publish","type":"post","link":"https:\/\/3way.social\/blog\/javascript-seo-in-2026-what-google-and-ai-crawlers-actually-see\/","title":{"rendered":"JavaScript SEO in 2026: what Google and AI crawlers actually see"},"content":{"rendered":"<p dir=\"ltr\">Open your page, right-click, and choose \u201cview source.\u201d If the content you want to rank for isn\u2019t actually in that HTML, you could have a problem &#8211; And in 2026 it\u2019s a bigger problem than it used to be.<\/p>\n<p dir=\"ltr\">Loads of modern sites build their main content with JavaScript. The browser runs the code, the content appears, everything looks fine to you. The question is whether it looks fine to the things that rank you and cite you&#8230; I&#8217;ve found that often it doesn\u2019t, so here we are introducing Javascript SEO!<\/p>\n<h3 dir=\"ltr\" aria-level=\"5\">Google reads the rendered page, not your source code<\/h3>\n<p dir=\"ltr\">First, the good news &#8211; Google does run JavaScript. It renders the page the way a browser does, then indexes what\u2019s there after the code has run. So the version Google judges is the finished, rendered page.<\/p>\n<p dir=\"ltr\">Martin Splitt, who works on exactly this at Google, <a href=\"https:\/\/www.searchenginejournal.com\/googles-martin-splitt-reveals-3-javascript-seo-mistakes-fixes\/543302\/\" target=\"_blank\" rel=\"noopener\">made the point<\/a> at an SEO event in 2025: \u201cA lot of people are still looking at view source. That is not what we use for indexing. We use the rendered HTML.\u201d<\/p>\n<p dir=\"ltr\">The catch is timing. Google crawls your HTML first, then comes back to render the JavaScript when it has resource to spare. People call this the two waves of indexing. Usually the gap is short. Sometimes it\u2019s days. If your content only exists after rendering, it sits invisible until that second pass lands. For a news page or a time-sensitive launch, that delay costs you.<\/p>\n<p dir=\"ltr\"><a href=\"https:\/\/3way.social\/blog\/javascript-seo-in-2026-what-google-and-ai-crawlers-actually-see\/javascript-seo\/\" rel=\"attachment wp-att-4507\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4507\" src=\"https:\/\/3way.social\/blog\/wp-content\/uploads\/2026\/11\/javascript-seo.jpg\" alt=\"a javascript SEO poster showing a splitscreen of what is shown in browsers\" width=\"800\" height=\"456\" srcset=\"https:\/\/3way.social\/blog\/wp-content\/uploads\/2026\/11\/javascript-seo.jpg 800w, https:\/\/3way.social\/blog\/wp-content\/uploads\/2026\/11\/javascript-seo-300x171.jpg 300w, https:\/\/3way.social\/blog\/wp-content\/uploads\/2026\/11\/javascript-seo-768x438.jpg 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><\/p>\n<h3 dir=\"ltr\" aria-level=\"5\">The newer problem: AI crawlers don\u2019t run your JavaScript at all<\/h3>\n<p dir=\"ltr\">This is the bit that\u2019s changed the stakes. The crawlers behind AI answers are now a serious slice of your traffic, and they behave very differently from Googlebot.<\/p>\n<p dir=\"ltr\">Vercel ran a <a href=\"https:\/\/vercel.com\/blog\/the-rise-of-the-ai-crawler\" target=\"_blank\" rel=\"noopener\">study with MERJ on AI crawler behaviour<\/a> and the headline finding is blunt: \u201cnone of the major AI crawlers currently render JavaScript.\u201d They\u2019ll fetch your JavaScript files (<a href=\"https:\/\/3way.social\/blog\/chatgpt-sent-users-to-a-scam-clone-of-t3-code-could-it-happen-to-your-product\/\">ChatGPT<\/a> pulled them on 11.50% of requests, Claude on 23.84%), but they don\u2019t execute them. So any content that only appears after the code runs is simply not there as far as they\u2019re concerned.<\/p>\n<p dir=\"ltr\">And these bots count for a lot of your traffic! On that same Vercel data, <a href=\"https:\/\/www.searchenginejournal.com\/ai-crawlers-account-for-28-of-googlebots-traffic-study-finds\/\" target=\"_blank\" rel=\"noopener\">AI crawlers already make up around 28% of Googlebot\u2019s volume<\/a>, with GPTBot and Claude pulling close to a billion fetches a month across one network alone. If your key content is client-side rendered, you\u2019re handing all of those crawlers a blank page. That study ran in late 2024, and it\u2019s still the clearest read we have on how these bots work. If anything, the AI crawler share has grown since.<\/p>\n<blockquote>\n<p dir=\"ltr\">\u201cI audit sites where the whole product description loads by JavaScript after the page settles. It looks perfect in Chrome, then you fetch it the way an AI bot does and there\u2019s nothing there but a spinner. You can\u2019t get cited for content a crawler never sees. Put the important words straight in the HTML that ships.\u201d Peter Fox, Head of Dev at 3Way.Social<\/p>\n<\/blockquote>\n<h3 dir=\"ltr\" aria-level=\"5\">How to see what Google and AI actually get<\/h3>\n<p dir=\"ltr\">You don\u2019t have to guess &#8211; Here&#8217;s three quick checks:<\/p>\n<p dir=\"ltr\">Use <a href=\"https:\/\/3way.social\/blog\/crawled-currently-not-indexed\/\">Google Search Console<\/a>\u2019s URL Inspection tool, run a live test, and look at the rendered HTML and screenshot. That\u2019s close to what Googlebot indexes. If your main content is missing there, Google is struggling too.<\/p>\n<p dir=\"ltr\">Disable JavaScript in Chrome (open DevTools, hit the command menu, \u201cDisable JavaScript\u201d), then reload the page. What\u2019s left is roughly what a non-rendering crawler sees, including the AI bots. If the page goes blank or loses its main text, that\u2019s your answer.<\/p>\n<p dir=\"ltr\">Compare view-source against the rendered DOM (right-click, Inspect). If your headings, body copy and links only show up in the rendered version, they depend on JavaScript to exist.<\/p>\n<p dir=\"ltr\">Do this on your top ten pages. It takes about half an hour and it\u2019s the most useful thing you\u2019ll do for technical SEO this month.<\/p>\n<h3 dir=\"ltr\" aria-level=\"5\">What to actually fix<\/h3>\n<p dir=\"ltr\">The fix is mostly about where your content lives.<\/p>\n<p dir=\"ltr\">Server-side rendering is the clean answer. The server sends fully-formed HTML with the real content already in it, then JavaScript takes over for interactivity. Googlebot and the AI crawlers both get the content without running anything. Frameworks like Next.js, Nuxt and Astro make this the default now, so it\u2019s rarely the fight it once was.<\/p>\n<p dir=\"ltr\">If a full rebuild isn\u2019t on, prerendering or static generation for your important pages gets you most of the way. Google used to suggest a workaround where you serve crawlers a pre-rendered version, but it now treats that as a stopgap rather than advice, so I\u2019d put the effort into real server rendering instead.<\/p>\n<p dir=\"ltr\">A few smaller things that catch people out:<\/p>\n<p dir=\"ltr\">Make your internal links proper <code dir=\"ltr\">&lt;a href=\"\"&gt;<\/code> tags. If navigation only fires through an onclick handler, non-rendering crawlers can\u2019t follow it, and your deeper pages go undiscovered.<\/p>\n<p dir=\"ltr\">Don\u2019t hide primary content behind a click or an infinite scroll that only works with JavaScript. If it matters for ranking, it belongs in the initial HTML.<\/p>\n<p dir=\"ltr\">Watch soft 404s. Splitt flagged this one too: a JavaScript route that fails often returns a 200 \u201cOK\u201d status with an error page, so Google thinks a broken page is fine and indexes the mess.<\/p>\n<h3 dir=\"ltr\" aria-level=\"5\">A 30-minute JavaScript SEO audit<\/h3>\n<p dir=\"ltr\">Quick version you can run today.<\/p>\n<p dir=\"ltr\">Pick your five most important pages. For each: view source and search for a sentence of your main content. If it\u2019s not there, flag it. Then disable JavaScript and reload. If the page breaks, flag it. Then run the URL in Search Console\u2019s live test and check the rendered HTML. Then click through your main nav with JavaScript off and see what still works.<\/p>\n<p dir=\"ltr\">Anything that fails two of those checks goes on the fix list, server rendering first. You\u2019ll usually find one or two pages doing real damage and a handful that are fine. That focus is worth more than a 90-page audit that sits in a folder.<\/p>\n<h3 dir=\"ltr\" aria-level=\"5\">Javascript SEO FAQs<\/h3>\n<h4 dir=\"ltr\" aria-level=\"6\">Does Google rank JavaScript sites?<\/h4>\n<p dir=\"ltr\">Yes. Google renders JavaScript and indexes the rendered page. The risk is delay (the two-wave gap) and anything that fails to render, like soft 404s or content behind events it won\u2019t trigger.<\/p>\n<h4 dir=\"ltr\" aria-level=\"6\">Why do AI crawlers matter for JavaScript SEO?<\/h4>\n<p dir=\"ltr\">Because they don\u2019t render JavaScript at all. Tools like ChatGPT and Perplexity read the raw HTML. If your content only appears after the code runs, those tools can\u2019t see it, and they can\u2019t cite a page they never read.<\/p>\n<h4 dir=\"ltr\" aria-level=\"6\">Is server-side rendering always the answer?<\/h4>\n<p dir=\"ltr\">It\u2019s the most reliable one for content that needs to be seen by crawlers. For pages that don\u2019t need to rank or be cited (a logged-in dashboard, say), client-side rendering is perfectly fine. Match the approach to the page\u2019s job.<\/p>\n<h4 dir=\"ltr\" aria-level=\"6\">How do I know if my site has a rendering problem?<\/h4>\n<p dir=\"ltr\">Disable JavaScript in your browser and reload your key pages. If the content disappears, crawlers that don\u2019t render (and that\u2019s all the AI ones) are seeing the same empty page.<\/p>\n<h4 dir=\"ltr\" aria-level=\"6\">What\u2019s the two waves of indexing?<\/h4>\n<p dir=\"ltr\">Google crawls your HTML first, then renders the JavaScript in a second pass later. If your content only exists after rendering, it waits for that second wave, which can take anywhere from minutes to days.<\/p>\n<h4 dir=\"ltr\" aria-level=\"6\">Does structured data need rendering too?<\/h4>\n<p dir=\"ltr\">If your schema is injected by JavaScript, Google can usually pick it up on render, but the first crawl and the AI crawlers won\u2019t. Putting JSON-LD in the server HTML is the safer bet.<\/p>\n<p dir=\"ltr\"><em>By Peter Fox, Head of Dev Team at 3way.social. I spend a lot of time fetching clients\u2019 pages the way a crawler does and explaining why the browser lied to them.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Open your page, right-click, and choose \u201cview source.\u201d If the content you want to rank for isn\u2019t actually in that HTML, you could have a problem\u2026<\/p>\n","protected":false},"author":4,"featured_media":4507,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[3],"tags":[],"class_list":["post-4506","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-seo"],"modified_by":"Becky Halls","_links":{"self":[{"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/posts\/4506","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/comments?post=4506"}],"version-history":[{"count":2,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/posts\/4506\/revisions"}],"predecessor-version":[{"id":4509,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/posts\/4506\/revisions\/4509"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/media\/4507"}],"wp:attachment":[{"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/media?parent=4506"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/categories?post=4506"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/3way.social\/blog\/wp-json\/wp\/v2\/tags?post=4506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}