JavaScript content not indexed: text that exists in the browser but not in Google
Google runs JavaScript, but only what executes on page load without interaction, and only when the scripts and their data are reachable. Content that appears after a click, a scroll, a consent choice or a failed request is not indexed. Check what Google renders in URL Inspection, then deliver that content in the initial HTML.
A standard WordPress post is not at risk: its text is in the server response. The problem lives in the parts of a page that are filled in later by scripts.
A quick test with a quoted sentence
Pick a distinctive sentence from the part of the page you suspect. Then:
- Search for it. Put the sentence in double quotes in Google together with
site:example.com. If the page is indexed and the sentence returns nothing, Google does not have that text. - Look in the raw HTML.
curl -s https://example.com/page/ | grep -c "part of the sentence". A result of0means the text is not in the server response and depends on JavaScript. - Look in Google's rendered HTML. In Search Console, inspect the URL, run Test live URL, open View tested page and search the HTML tab for the sentence. This is the page after Google's rendering.
The combinations tell you where you stand. In raw HTML: no JavaScript problem. Missing from raw but present in Google's rendered HTML: Google can render it, and indexing should follow, with some delay. Missing from both: Google cannot see it, and you need to find out why.
Why rendering fails for Googlebot
The content needs an interaction. Googlebot does not click, type, hover or scroll like a person. Text fetched when a tab is clicked, reviews loaded by a "show more" button, and products appended on scroll are not requested. Content that is in the DOM but hidden with CSS, as in a normal accordion, is fine; content that is absent until the click is not.
Scripts are delayed until user interaction. Performance plugins offer a "delay JavaScript execution" option that holds scripts back until the first mouse movement, touch or key press. Googlebot produces none of those, so delayed scripts may never run. Anything those scripts would have rendered is missing.
A consent or age gate replaces the page. If content is withheld until a cookie banner is accepted, a crawler that never accepts sees only the banner. Banners should overlay the content, not substitute for it.
The data request is blocked or fails. A script calls /wp-json/… or admin-ajax.php and robots.txt disallows that path, or the API demands a nonce or cookie. Check More info → Page resources in the live test for blocked or failed requests, and JavaScript console messages for errors.
Rendering is too slow or too heavy. Google's renderer does not wait indefinitely. A page that makes a chain of sequential API calls before showing its main content is at risk.
Where this turns up on WordPress sites
- Product filters and search results loaded by AJAX, with no crawlable URL for the filtered view.
- Review, testimonial and social-feed widgets that fetch from a third-party service in the browser. That content was never yours to rank with, and it is usually in an iframe or script Google attributes elsewhere.
- "Load more" archives without paginated links; see links are not crawlable.
- Page-builder elements that render from a JSON payload on the client.
- Headless WordPress front ends built as client-side single-page apps with no server rendering.
Fixes, from most to least robust
- Render it on the server. The dependable fix is for the important text and links to be present in the HTML response. For WordPress content that means printing it in PHP templates or blocks instead of fetching it afterwards. For a headless build, enable server-side rendering or static generation in the front-end framework.
- Load it on page load, not on interaction. If it must be fetched by script, request it immediately, without waiting for a click or scroll, and make sure the endpoint is public and not disallowed in robots.txt.
- Exclude critical scripts from "delay until interaction". Keep the delay for analytics, chat widgets and ads. Scripts that produce content should run on load.
- Give paginated and filtered content real URLs linked with ordinary anchors.
- Do not rely on serving bots a separate prerendered version. Google describes that approach, dynamic rendering, as a workaround and not a long-term solution.
Meta tags deserve the same treatment. Titles, descriptions, canonicals and robots directives should be in the initial HTML, not rewritten by scripts. Hydrogen SEO prints all of its tags and schema server-side, with no front-end JavaScript involved, so what you see in view-source is what crawlers get.
Confirm Google sees it
Repeat the three-step test. The sentence should now appear in the curl output, or at least in the rendered HTML of a live test with no blocked resources. Request indexing for the page, then try the quoted search again after it has been recrawled.
Our free SEO audit reads the raw HTML of the URL you enter without running scripts. If it reports thin content or very few internal links on a page that looks full in your browser, the difference is content your site only produces in JavaScript.
Common questions
Does Google index JavaScript content at all?
Yes. It renders pages with a recent version of Chromium. Rendering happens after the initial crawl and can lag behind it, and anything requiring interaction is not executed.
Are tabs and accordions bad for SEO?
Not when their content is in the HTML and merely hidden until opened. The risk is content fetched from the server only when the tab is clicked.
Do other search engines and AI crawlers run JavaScript?
Many do so less thoroughly than Google, and some not at all. Server-rendered content is readable by all of them.
Is lazy-loading text a good idea?
No. Lazy-load images and embeds. Text is small, and loading it late only risks it being missed.