JavaScript SEO Tips: How to Audit a JavaScript Website

A JavaScript SEO audit should tell you whether important pages can be found, whether their content loads, and whether their indexing instructions make sense. A page looking right in your browser is a useful starting point, but it doesn't answer all three questions.

Google can execute JavaScript. Its processing includes crawling, rendering, and indexing, and it can extract links from rendered HTML. Those stages are distinct: successfully downloading a page doesn't establish that its content rendered or was indexed. Google's JavaScript SEO guide describes the process.

The tips below follow the order of an audit: choose a few representative URLs, inspect what they return, test the parts that depend on JavaScript, and turn failures into specific fixes. You'll need a browser with developer tools, access to Search Console for a site you manage, and a crawler when you're ready to check more pages.

1. Choose a small set of representative pages

Choose one URL from each important template: a product, a category, an article, and a landing page. Include a page with pagination or a “load more” control if the site uses them.

For each URL, write down the main heading, a distinctive sentence, two important destination links, and the expected title. This makes your test specific. “The page looks fine” is harder to verify than “the category description and both product links are present.”

Test the URL directly in a fresh browser session. Record whether you interacted with a consent banner or navigated from another page first. Those actions can change the conditions you're testing.

If you don't have a reliable URL list, start by combining your sitemap, crawl results, and CMS export. Include pages beyond the homepage; a working homepage can hide problems in product, article, or category templates.

2. Check what the server sends before JavaScript runs

The initial HTML is the document returned by the server. The browser parses it into a document object model, or DOM, which scripts can then modify. Chrome's Elements panel shows that current DOM. It can contain headings, links, and other elements that were absent from the original response. Chrome's DOM documentation explains the distinction.

Open Chrome DevTools, select Network, and reload the page. Select the main document request, then inspect its Response and Headers. Search the response for your chosen heading, sentence, and link destinations. Record the HTTP status and any redirect. Chrome documents these views in its Network panel reference.

Look at how the content is represented. A product name inside a JSON data block is different from a product heading in the document. A URL inside a script is different from an anchor pointing to that URL. A text search is a starting point; inspect the surrounding markup.

3. Compare the rendered page with the initial response

After the page loads, use Elements to search for the same items. Inspect the heading and destination links, then check the document's <head> for its title, canonical, and robots tags. Note whether the page remains incomplete or changes after an interaction.

Example: the product grid depends on JavaScript

Imagine a category page whose server returns this simplified document:

<!doctype html>
<html lang="en">
<head>
  <title>Store</title>
  <script src="/category.js" defer></script>
</head>
<body>
  <main id="catalog">Loading…</main>
</body>
</html>

Suppose category.js successfully loads the catalog and updates the page. The relevant parts of the DOM might then look like this:

<title>Trail Shoes | Example Store</title>

<main id="catalog">
  <h1>Trail shoes</h1>
  <p>Footwear for muddy paths and rocky terrain.</p>
  <a href="/products/ridge-runner">Ridge Runner</a>
  <a href="/products/forest-walker">Forest Walker</a>
</main>

In this example, the title, category copy, and product links all depend on JavaScript running successfully.

Compare the initial HTML with the rendered result. If the product API fails and the page stays at “Loading…”, investigate that failure. If the intended content appears reliably, its absence from the initial HTML alone doesn't prove an indexing problem.

The distinction matters when assigning the fix. An empty response, a failed API call, and a missing link can produce similar-looking crawl reports, but each points to different work.

Record what changed between the response and the rendered page: headings, descriptive copy, destination links, and metadata. A screenshot gives visual context, but an HTML excerpt shows the exact missing element. Note whether an interaction was needed before it appeared.

4. Make sure important navigation uses crawlable links

A clickable card may use a script without exposing a link destination in its HTML. For navigation to another page, use an anchor with a real URL:

<a href="/products/ridge-runner">View Ridge Runner</a>

JavaScript can enhance the interaction while preserving that link. Google recommends <a> elements with href attributes and says JavaScript-inserted links can be crawlable when they use that markup. Google's link guidance includes examples.

Ask the developer to check the shared card or navigation component. One correction there may repair the same issue across many pages.

5. Test pagination and content behind “load more”

Google Search doesn't interact with pages by clicking or scrolling. Important content should load without requiring those actions. For infinite-scroll collections, provide persistent paginated URLs and links between them so later items have a discovery path. Google's lazy-loading guidance covers this approach.

During the audit, compare the first visible batch with a later batch. Open the later page directly. If there is no URL that reproduces it, record that as a concrete discovery problem for the development team.

6. Open deep URLs directly and check their status codes

Paste an important deep URL into a fresh session. If it fails while navigation from the homepage works, investigate routing and state dependencies. The page may require data that a previous screen loaded, or the server may not know how to handle that route.

Also test a deliberately nonexistent URL. A polished “page not found” screen returned with HTTP 200 can be treated as a soft 404. Fix the response behavior as well as the visual message. Google's HTTP status guidance explains why a successful response is not proof of usable content.

7. Check robots instructions and canonical URLs

Inspect both HTML tags and response headers. A page-level noindex can appear in a robots meta tag or an X-Robots-Tag header; checking only the visible page misses both. Google's robots-tag specification covers these controls.

Don't ship an initial noindex and expect JavaScript to remove it for a page you want indexed. Google may skip rendering after seeing the original instruction. Also avoid setting one canonical in the response and changing it to another during rendering. Both behaviors are addressed in Google's JavaScript SEO guidance.

Check that canonical declarations match your intended page grouping. Google treats canonicalization signals as inputs to its selection, so the declared canonical and Google's selected canonical can differ. See Google's canonicalization documentation.

8. Compare your findings with Google’s rendering evidence

For a site you manage, inspect the URL in Search Console. Distinguish the indexed-page information from a live test. Where available, review the tested page's HTML, screenshot, and loading information. Search for the same distinctive content you checked locally. A passing live test does not guarantee indexing. Google's URL Inspection documentation explains what each view covers.

If your browser and Google's test disagree, compare failed resources and JavaScript errors. Google's rendering environment also doesn't retain cookies or local storage between page loads, so a flow that requires a previous visit deserves particular attention. See Google's JavaScript troubleshooting guide.

9. Check how far each problem extends

Once you understand the issue on one page, identify the templates that share it. A missing title on one product may point to a product-template problem; a missing category link may originate in a shared navigation component.

Use a crawler with JavaScript rendering to check the affected sections and export the discovered URLs. If a category's products are missing from the results, go back to that category page and inspect the links and rendering behavior.

An unexpectedly short crawl is a clue. Check whether it reached a limit, encountered failures, or never discovered the missing section. Increasing the page limit won't fix a link that never appears. A third-party crawl also reflects its own environment; use Google's inspection tools for Google-specific evidence.

When is changing the rendering approach worth considering?

Server-side rendering creates page HTML on the server; static generation creates it ahead of requests. Either can put important content and links in the initial response. Client-side rendering relies on browser execution to build some or all of that content.

Choose based on the dependency your audit uncovered. If a product description repeatedly disappears because a browser-side data request fails, delivering that description in the initial HTML is a concrete option to evaluate. If the description already arrives in the response and a decorative widget is broken, rebuilding the site's rendering architecture is unlikely to be your first useful fix.

A server-rendered site can still have missing links, incorrect canonicals, or failing routes. Retest the same URLs after any implementation change.

Finish the audit with fixes someone can verify

“JavaScript is hurting our SEO” leaves the next person with most of the investigation still to do. A useful issue describes a particular failure. For the category example above, a ticket might say:

Example issue: product links missing on direct category visits

Open /trail-shoes in a fresh session without visiting the homepage first. The page returns HTTP 200, but the main content remains at “Loading…” and no product anchors appear. Navigating to the category from the homepage produces the expected product grid.

Expected: the category heading, description, and product links should appear on a direct visit. Investigate the category's initial data loading and any state supplied by the homepage.

This is a hypothetical ticket, but the level of detail is the point. Attach the document response, rendered HTML excerpt, and any relevant failed request from your actual test. List another affected URL if you suspect a shared template.

After the fix, repeat the same direct visit in a fresh session, check the affected section with a crawler, and inspect a representative URL in Google. Keep the before-and-after evidence. That gives you a much clearer answer than whether the site uses React, whether its homepage looks fine, or whether one crawler returned a reassuring page count.