How to Audit JavaScript SEO Without Guessing
By Seth Black · Published
Most JavaScript SEO arguments I get pulled into end with someone saying “but Google renders JavaScript now.” Google renders a lot of it. The real question is whether it rendered your page, with your canonical tag, before the API call behind it timed out. You can answer that with evidence instead of a hunch.
My first production disaster came from exactly this. Firefox had just dropped, I switched to it, and I stopped testing in IE, which still owned nearly the whole browser market. One quick patch later, an e-commerce site went offline on launch weekend. Googlebot is basically IE: a user with unusual habits and a very short attention span.
Get two copies of every page
A JavaScript audit compares the raw HTML your server returns with the rendered DOM after JavaScript runs. You can grab both for one URL in about ten seconds:
## Raw HTML, what a non-rendering crawler sees
curl -s https://example.com/pricing > raw.html
## Rendered DOM, after JavaScript runs
google-chrome --headless --dump-dom https://example.com/pricing > rendered.html
diff <(grep -o '<title>.*</title>' raw.html) <(grep -o '<title>.*</title>' rendered.html)
If the raw file is mostly an empty <div id="root"></div> and a pile of script tags, you’ve already learned something. This raw-versus-rendered gap is the core of why JavaScript crawls break silently — the page looks fine in a browser while Google sees almost nothing.
What to compare
Check these between the raw and rendered versions:
- Title and meta description. Shells often ship placeholder text that gets swapped out later.
- Canonical and robots meta. A canonical that only exists after hydration is a gamble. A
noindexin the shell that JavaScript later removes is worse, because Google may act on the first one it sees. - H1 and body copy. If the main content is missing from the raw HTML, you depend on rendering working every time.
- Structured data. JSON-LD injected by a tag manager sometimes never fires during a crawl.
- Internal links. These get their own section.
Links that only show up after JavaScript
Google follows <a href> elements. It does not click buttons. I regularly find navigation built from <div onClick={...}> or router components that render an anchor with no href. Those links look perfect in a browser and do nothing for a crawler.
Count the links in each version. If the rendered DOM has 140 internal links and the raw HTML has 6, you have a crawl path problem. If the rendered DOM also has 6 because the rest sit behind a “Load more” button, rendering won’t save you. The same principle applies to AI crawlers reading your JavaScript content — most of them never execute it at all.
How rendering fails in React, Vue, and Angular
These are the three I see most often:
- React: hydration errors that blank out a section, or a client-side fetch that comes back after the renderer has already taken its snapshot.
- Vue: content wrapped in
v-ifthat waits on API data, so the rendered DOM shows a spinner forever. - Angular: an empty
<app-root>on every route because server-side rendering was set up for the homepage and nowhere else.
If you’re procuring outside help for a framework-specific audit, the questions worth asking vendors are covered in buying a technical SEO audit for React and Angular apps.
Doing this on 40,000 URLs
Hand-running curl and headless Chrome works until the site has more than a handful of routes you actually care about. bseoa runs an HTTP crawler and a headless Chrome crawler against the same URLs and diffs them per page:
black-seo-analyzer --url-to-begin-crawl https://example.com --spa --output-type html-folder --output-file ./audit
Crawl output streams in real time, so a broken route shows up while the crawl is still running. Every issue links to the exact URLs it affects, so you can give programmers a URL list grouped by failure type instead of a PDF that says “JavaScript issues found” and nothing else. If you prefer running audits from the command line rather than a browser tab, the SEO audit CLI workflow for developers covers how to wire this into staging and CI pipelines.
Start a free trial and run it on the section of your site you trust the most.
bseoa renders JavaScript the way Googlebot does, so React and Angular sites audit correctly. See how or start a free trial.
-Sethers