JavaScript SEO
JavaScript SEO
JavaScript SEO covers every measure that makes sure content is found and indexed by search engines even when it only comes into existence in the browser through JavaScript. The core of the topic: a search engine initially sees only the HTML the server delivers. Everything beyond that requires rendering.
| Core problem | crawling and rendering run separately and at different times |
|---|---|
| renders in a second wave - with a delay of minutes to hours | |
| AI crawlers | GPTBot, ClaudeBot, PerplexityBot as a rule execute no JavaScript at all |
| Most reliable solution | server-side rendering (SSR) or static generation (SSG) |
| Test tool | URL inspection in Google Search Console; Ctrl+U shows the delivered HTML |
JavaScript SEO covers every measure that makes sure the content of a website is found, understood and indexed by search engines even when it only comes into existence in the browser through JavaScript. That affects almost every modern website: single-page applications, product lists loaded on demand, content behind tabs and everything that appears through a "load more" button.
The core of the topic fits into one sentence: a search engine initially sees only the HTML code the server delivers. Everything that comes into existence after that through scripts requires an additional and considerably more expensive step - rendering.
How Google processes JavaScript
Processing runs in two waves. That split is the cause of practically every problem in this area:
- Crawling: Googlebot requests the URL and receives the HTML code from the server. Links it contains are followed, text it contains can go into the index right away.
- Rendering: if the HTML is not enough, the page moves into a queue. There it is opened later by a service with a current Chromium engine, the scripts are executed and the result is evaluated again.
Time passes between the two steps. In many cases it is minutes, but it can become hours or more - rendering is computationally expensive and is prioritised accordingly. For content that has to be in the index quickly (news, offers, dates), that delay is a real problem.
Another important point: the renderer does not behave like a user. It does not click, does not scroll and does not wait indefinitely. Content that only appears after an interaction simply does not exist for search engines.
Not every crawler renders
Google renders JavaScript - which is frequently taken to mean the topic is settled. The rest of the web works differently, though:
- Other search engines render to varying degrees and mostly more cautiously.
- AI crawlers such as GPTBot, ClaudeBot or PerplexityBot as a rule execute no JavaScript. What is not in the HTML does not end up in their sources - see Generative Engine Optimization.
- Preview bots of messengers and social networks read the HTML head only. If Open Graph data is only set through JavaScript, the link preview stays empty.
- Ad and verification systems frequently work without full rendering too.
The rule of thumb is therefore unchanged: everything that counts for findability belongs in the delivered HTML - title, description, headings, body text, links and structured data.
Typical mistakes
- Links without href. A <div onclick="…"> is not a link to a crawler. Only <a href="/target"> is followed. Pages reachable only through click handlers hang in mid-air without internal links.
- Routing through the hash. Addresses in the form example.com/#/product/12 count as a single URL. Whatever stands after the hash is never sent to the server and cannot be indexed as a page of its own.
- Meta data set by script. Title and description that are only set in the browser arrive too late for many systems.
- Content behind interaction. Text that is only loaded after clicking "show more" or on scrolling further is not captured. Text that is already present but hidden via CSS, by contrast, is unproblematic.
- Blocked resources. If script or stylesheet files are blocked in robots.txt, the search engine renders a broken page.
- Errors when fetching data. If an API fails during rendering, the page stays empty - in the user's browser the same page works, because the request succeeds there.
Rendering strategies compared
| Method | What the server delivers | Findability | Suitable for |
|---|---|---|---|
| Client-side rendering (CSR) | an empty shell | worst - everything depends on rendering | applications behind a login |
| Server-side rendering (SSR) | finished HTML, enriched in the browser | most reliable | content that is supposed to rank |
| Static site generation (SSG) | files generated in advance | very good, and fast on top | content that rarely changes |
| Prerendering | pre-rendered HTML from an additional service | good, with one more dependency | retrofitting existing applications |
The formerly widespread dynamic rendering - crawlers get a pre-rendered version, users get the application - now counts as a transitional solution and is no longer recommended. Two separate delivery paths mean two permanent sources of error.
Checking what the search engine really sees
- Look at the page source. Ctrl+U shows the delivered HTML - not what the developer tools display. Whatever is missing here has to be rendered.
- Switch JavaScript off and reload the page. Whatever disappears depends on rendering.
- URL inspection in Google Search Console. It shows the rendered HTML, a screenshot and any loading errors - the most informative tool for this question.
- Search for passages. Paste a verbatim quote from the body text into Google search: if your own page is not found, the text is not in the index.
Why statistics drift apart with JavaScript
The same technology explains a question that comes up with every campaign: why do three systems show three different numbers? Because they count in different places:
- The server log counts every request, including those from bots.
- Analytics tools only count once their JavaScript has been executed - so only visitors who stay long enough, use no blocker and have consented to measurement.
- The campaign statistics count the visits delivered.
All three numbers are correct, they simply measure different things. Anyone comparing website traffic from several sources should keep that in mind: deviations in the double-digit percentage range are normal. When reconciling the numbers of an eBesucher campaign you should therefore first check whether your own counting script loads early enough - a script that only starts after several seconds loses part of the visits by design.
A second point comes on top: eBesucher never transmits a referrer. Visitors from a campaign therefore appear in analytics under "direct". The clean way to separate them is UTM parameters in the destination URL - they sit in the address and work regardless of how much JavaScript is involved.
Checklist
- Is the central text present in the delivered HTML?
- Are all important pages reachable through <a href>?
- Does every view have its own server-addressable URL without a hash?
- Are title, description, canonical and Open Graph data set server-side?
- Are scripts and stylesheets allowed in robots.txt?
- Does the measurement load early enough not to lose visitors?
Summary
- Search engines first see only the HTML from the server; everything else requires rendering.
- Google renders in a second wave with a time gap - many other crawlers do not render at all.
- Links need an href, views need their own URLs without a hash.
- Server-side rendering and static generation are the most reliable routes; dynamic rendering is obsolete.
- URL inspection in Search Console shows what actually arrives.
- Diverging visitor numbers between log, analytics and campaign statistics are a consequence of the same technology.