A JavaScript SEO audit checks whether Google can read your content, links, and metadata without waiting on script execution. Combined with a mobile SEO review and crawl budget optimization, it fixes the three most common reasons large sites lose organic visibility: invisible content, broken mobile parity, and Googlebot wasting time on low-value URLs.

Key takeaways

  • Google indexes JavaScript in two waves. Content missing from the raw HTML can wait hours to weeks for rendering.
  • Mobile-first indexing means the mobile DOM is what gets indexed. Navigation links or content hidden behind JS clicks effectively disappear from Google's view.
  • Crawl budget problems usually show up as a large gap between "Discovered" and "Crawled" pages in Search Console. This is typically caused by faceted navigation, redirect chains, or thin pagination.
  • Serving critical content, meta tags, and links in the initial HTML through server-side rendering or static generation cuts both rendering cost and crawl waste.
  • The crawl-budget tactics in this guide reflect the strategy used on Not Another Sunday, a Next.js and Supabase directory with 137,000 listings that keeps thin pages out of Google's index.

Updated 15 August 2026: sources added, experience claims checked against our project record, summary added.

This playbook covers JavaScript SEO auditing from the renderer's perspective, mobile-first indexing pitfalls that quietly kill rankings, and crawl budget optimization strategies for large sites.

JavaScript SEO Audit, Mobile SEO & Crawl Budget Optimization

How Google Actually Processes JavaScript

Before you audit anything, you need to understand the two-wave indexing pipeline Google uses. This process decides whether your content gets indexed in hours or in weeks.

Wave 1: Raw HTML Crawl

Googlebot fetches your URL and looks at the initial HTML response. No JavaScript runs at this stage. Whatever sits in the raw HTML gets processed right away. That includes your <title> tag, meta description, canonical tag, internal links, structured data, and body content.

If your page serves a mostly-empty <div id="root"></div> with a fat JS bundle, Google sees almost nothing. The URL gets tossed into a rendering queue.

Wave 2: The Rendering Queue

Google's Web Rendering Service (WRS) picks up queued URLs and runs JavaScript using a headless Chromium instance. WRS runs an evergreen version of Chromium, so it supports modern JS features. But here's the catch: the rendering queue adds delay. Depending on your site's crawl priority and Google's resources, this delay can range from seconds to days, sometimes weeks for lower-priority pages.

Why This Matters

Every page that needs rendering costs Google more resources than a plain HTML page. That's a direct hit to your crawl budget. Google's own documentation states that rendering is resource-intensive and that Google may not render every page it crawls. On a 500-page portfolio site, this probably doesn't matter. On a 50,000-page e-commerce site, it's the difference between getting indexed and getting ignored.

// What Googlebot sees on first pass with CSR:
<!DOCTYPE html>
<html>
<head>
  <title>My App</title>
</head>
<body>
  <div id="root"></div>
  <script src="/bundle.js"></script>
</body>
</html>
// Content? Zero. Links? Zero. Structured data? Zero.

Running a JavaScript SEO Audit

This process consistently uncovers real rendering problems on JavaScript-heavy sites. Here's the sequence that works.

Step 1: Compare Rendered vs. Raw HTML

Start here. For every key page template, compare what's in the initial HTML response versus what appears after JavaScript runs.

Tools for this:

  • Google Search Console's URL Inspection tool (shows both the raw HTML and rendered HTML)
  • Screaming Frog's JavaScript rendering mode (set it to render in spider config)
  • Chrome DevTools: disable JavaScript and reload the page to see what's left

What you're looking for:

Element Must Be in Raw HTML Can Rely on JS
<title> tag ✅ Yes ❌ No
Meta description ✅ Yes ❌ No
Canonical tag ✅ Yes ❌ No
H1 heading ✅ Yes ❌ No
Main body content ✅ Strongly preferred ⚠️ Risky
Internal nav links ✅ Yes ❌ No
Structured data (JSON-LD) ✅ Yes ⚠️ Google says OK, but server-side is safer
Images with alt text ✅ Yes ⚠️ Risky
Lazy-loaded below-fold content ⚠️ Depends ✅ Usually fine

Step 2: Check for JavaScript Errors

Open Chrome DevTools, go to each page template, and watch the Console tab. JavaScript errors can silently stop content from rendering. Common culprits:

  • API calls that fail or time out (especially third-party services)
  • Missing environment variables in production builds
  • CORS errors blocking data fetches
  • Hydration mismatches in React/Next.js apps
// A common pattern that breaks rendering for Googlebot:
fetch('https://api.example.com/products')
  .then(res => res.json())
  .then(data => renderProducts(data))
  .catch(err => console.error(err)); // Fails silently, page stays empty

Googlebot won't retry failed API calls. If that fetch fails during rendering, your content doesn't exist as far as Google is concerned.

This one bites people constantly. If your internal links come from JavaScript, especially click-triggered navigation, infinite scroll pagination, or dynamically injected menus, Googlebot might not find those links at all.

Check that key navigation links exist as real <a href="/path"> elements in the initial HTML. Links built with onclick handlers, window.location redirects, or framework routing that skips real anchor tags stay invisible to crawlers on first pass.

Step 4: Test with Google's Mobile-Friendly Test

This tool uses the same WRS that Google uses for indexing. It shows you exactly what Google sees after rendering. Run your key templates through it and look for missing content, blocked resources, or layout issues.

Mobile SEO Audit: Beyond Responsive Design

Google finished the switch to mobile-first indexing for all sites in 2024. This means the mobile version of your page is what Google indexes. Not the desktop version. The mobile version. Period.

Most developers think "we use responsive CSS, we're fine." That's table stakes. A real mobile SEO audit goes deeper.

Content Parity

Every piece of content on your desktop page must also sit on mobile and stay accessible there. This includes:

  • Full text content (not truncated behind "Read more" buttons that need JS clicks)
  • Internal links in navigation menus (even if collapsed behind a hamburger icon, the <a> tags must be in the DOM)
  • Structured data markup (same JSON-LD on mobile and desktop)
  • Image alt text
  • Meta tags (canonical, robots, hreflang)

Large desktop mega-menus often hide dozens of internal links behind a mobile hamburger menu that only loads them via a JavaScript click event. Because Google indexes the mobile DOM, it sees zero navigation links in that case. This cuts off internal link equity to every page those links would otherwise reach.

Core Web Vitals on Mobile

Google's page experience signals get measured on mobile. These thresholds still apply:

Metric Good Needs Improvement Poor
LCP (Largest Contentful Paint) ≤ 2.5s ≤ 4.0s > 4.0s
INP (Interaction to Next Paint) ≤ 200ms ≤ 500ms > 500ms
CLS (Cumulative Layout Shift) ≤ 0.1 ≤ 0.25 > 0.25

For JavaScript-heavy sites, INP is usually the problem. Large JS bundles block the main thread, which makes interactions feel sluggish. A common fix is code-splitting non-critical components:

// Before: One massive bundle
import { everything } from './megaModule';

// After: Code-split and lazy-load
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

Also watch for CLS caused by dynamically injected content, such as ads, images without dimension attributes, or fonts that trigger layout shifts. Set explicit width and height on images and use font-display: swap with preloaded fonts.

Mobile Rendering Issues

Test your pages on real mobile devices, not just Chrome DevTools' device emulation. Real devices have less memory, slower CPUs, and flakier network connections. A JavaScript-rendered page that works fine in DevTools might time out on a mid-range Android phone, and that's the kind of device most of the world actually uses.

Testing on real devices, not just emulators, catches these issues early. Google's own testing infrastructure runs on moderate hardware, so a page that can't render quickly on a mid-range device such as a Pixel 6 will likely struggle in Google's rendering queue too.

JavaScript SEO Audit, Mobile SEO & Crawl Budget Optimization - architecture

Crawl Budget: What It Is and Why It Matters

Crawl budget is the number of pages Googlebot will crawl on your site within a given time window. Two factors set it:

  1. Crawl rate limit: How fast Google can crawl without overloading your server
  2. Crawl demand: How much Google wants to crawl based on page importance and freshness

For smaller sites with fast servers, crawl budget usually isn't a concern. Google will get to everything. Large sites, such as e-commerce catalogs, big content sites, and SaaS platforms with user-generated content, are where crawl budget becomes a real limit.

Signs You Have a Crawl Budget Problem

  • New pages take weeks to get indexed
  • Google Search Console shows a large gap between "Discovered - currently not indexed" and "Crawled - currently not indexed"
  • Server logs show Googlebot repeatedly crawling low-value pages (parameter URLs, old pagination, internal search results)
  • Your XML sitemap has URLs that haven't been crawled recently

Crawl Budget Optimization Strategies

These tactics reflect the crawl-budget strategy used on Not Another Sunday, a directory with 137,000 listings that keeps thin pages out of Google's index. They're ordered roughly by impact.

1. Eliminate Crawl Waste

The single highest-ROI crawl budget fix is stopping Google from wasting time on URLs that shouldn't be crawled. Common offenders:

  • Faceted navigation: /shoes?color=red&size=10&brand=nike creates thousands of parameter combinations. Use robots.txt to block these patterns or add proper canonical tags pointing to the base category page.
  • Internal search result pages: /search?q=blue+widgets. Always block these in robots.txt.
  • Session IDs and tracking parameters: /product?sid=abc123&utm_source=email. Handle these with canonical tags or parameter handling in Search Console.
  • Infinite pagination: /blog/page/47 with two posts on it isn't worth crawling. Use noindex on deep pagination pages.
## robots.txt - block crawl waste
User-agent: *
Disallow: /search
Disallow: /*?sid=
Disallow: /*?sort=
Disallow: /*?filter=
Disallow: /internal/

2. Fix Redirect Chains

Every redirect in a chain uses up a crawl. A to B to C to D means Google used four crawls to reach one page. Audit your redirects and flatten chains to single hops. Screaming Frog makes this easy. Crawl your site and filter for redirect chains longer than one hop.

3. Serve SEO Signals Server-Side

This is where JavaScript SEO and crawl budget optimization meet. Every page that needs rendering costs more crawl resources. Serving critical content, meta tags, canonical tags, and internal links in the initial HTML response eases the load on Google's rendering pipeline.

This is exactly why we recommend frameworks like Next.js with SSR/SSG or Astro for SEO-critical sites. It's the same architecture behind our SleepDr.com migration (WordPress to Next.js, Lighthouse score 35 to 94) and our bdManagedIT rebuild (WordPress to Astro, 95+ PageSpeed with zero-JS static pages). If you're weighing options, take a look at our Next.js development capabilities or Astro development services.

4. Optimize XML Sitemaps

Your sitemap should be a curated list of pages you want indexed, not an auto-generated dump of every URL on your site. Rules:

  • Only include pages that return 200 status codes
  • Only include canonical URLs (not URLs that canonical to something else)
  • Remove noindexed pages
  • Include accurate <lastmod> dates (Google uses these to prioritize crawling)
  • Split large sitemaps into logical groups (products, categories, blog posts)

5. Improve Server Response Times

Google's crawl rate adapts to your server's capacity. If your server responds slowly or throws 500 errors, Googlebot backs off. Faster responses mean more pages crawled per session.

Aim for a sub-200ms Time to First Byte (TTFB) for your HTML responses. Use edge caching, CDNs, and efficient server-side rendering. Static generation (SSG) is the gold standard here. A pre-built HTML file served from a CDN is about as fast as it gets.

6. Manage Index Bloat

Crawl budget and index budget are related but separate. Google keeps an index budget too. Just because a page is crawled doesn't mean it'll be indexed. Pages with thin content, duplicate content, or poor quality signals get rejected.

Regularly audit your index using site:yourdomain.com searches and the Pages report in Search Console. If you find indexed pages that shouldn't be there (old campaign pages, test URLs, thin tag pages), remove them with noindex directives or 410 status codes.

Server-Side Rendering vs. Client-Side Rendering for SEO

Here's the practical comparison:

Approach SEO Risk Crawl Budget Impact Implementation Effort Best For
Static Site Generation (SSG) Very Low Minimal -- plain HTML Medium Content sites, blogs, marketing pages
Server-Side Rendering (SSR) Low Low -- HTML ready on request Medium-High Dynamic content, e-commerce, personalized pages
Incremental Static Regeneration (ISR) Low Low Medium Large catalogs that update periodically
Client-Side Rendering (CSR) High High -- requires rendering queue Low (initially) Apps behind authentication only
Dynamic Rendering Medium Medium High Legacy SPAs that can't be refactored

For SEO-critical pages, CSR is almost never the right choice. If you're running a React SPA and wondering why your pages aren't indexing well, this is probably why.

Dynamic rendering, which means serving pre-rendered HTML to bots while serving the SPA to users, works, but it's a maintenance headache, and Google has said it's a workaround rather than a long-term recommendation. It's a stopgap, not a solution.

Next.js (with its hybrid SSG/SSR/ISR abilities) and Astro (which ships zero JavaScript by default and adds it only where needed) are the two frameworks referenced throughout this guide. Both give full control over what goes into the initial HTML response. If your site runs on a headless CMS with a JavaScript frontend, that's the kind of architecture decision covered by our headless CMS development services.

Tools and Workflows for Technical SEO Audits

Here's a practical toolkit for these audits, not a sponsored list:

Crawling and Rendering

  • Screaming Frog SEO Spider (paid annual license): The workhorse. Enable JavaScript rendering, set a custom Googlebot user agent, and crawl your entire site. Compare rendered vs. raw HTML for every URL.
  • Sitebulb (paid annual license): Better visualization than Screaming Frog. Great for explaining crawl issues to non-technical stakeholders.
  • Chrome DevTools: Free. Essential for debugging JS rendering issues, checking network requests, and profiling performance.

Log File Analysis

  • Screaming Frog Log File Analyser (included with SEO Spider license): Import your server access logs and see exactly which URLs Googlebot hits, how often, and what status codes it gets.
  • Botify (enterprise pricing): If you're dealing with millions of URLs, Botify combines crawl data, log data, and Search Console data in one place. Expensive but worth it at scale.

Search Console Data

  • Google Search Console: Free. The Pages report shows indexing status for every URL. The Crawl Stats report shows Googlebot's behavior on your site. Use both.
  • Search Console API + BigQuery: For large sites, export your data to BigQuery for custom analysis. You can cross-reference crawl data with log files to find pages Google is ignoring.

Performance Testing

  • PageSpeed Insights: Uses real Chrome UX Report (CrUX) data plus Lighthouse lab data. Always test the mobile version.
  • WebPageTest: More detailed than PageSpeed Insights. Use the filmstrip view to see exactly when content becomes visible.

Workflow

For a typical technical SEO audit, here's a recommended order:

  1. Pull recent server logs and filter for Googlebot activity
  2. Run a full Screaming Frog crawl with JS rendering enabled
  3. Export Search Console data (indexed pages, crawl stats, Core Web Vitals)
  4. Cross-reference: Which pages are in your sitemap but not being crawled? Which are being crawled but not indexed? Where is Googlebot spending the most time?
  5. Test 5-10 key page templates for JS rendering issues
  6. Run mobile performance tests on all templates
  7. Prioritize fixes by impact times effort

Putting It All Together: An Audit Checklist

Here's a condensed checklist for these audits. Copy it, adapt it, use it.

JavaScript SEO

  • Critical content visible in raw HTML (JS disabled)
  • Title, meta description, canonical in initial HTML
  • Internal links are real <a href> elements in DOM
  • No JavaScript errors blocking rendering
  • Structured data present in initial HTML
  • API calls that populate content are reliable and fast
  • Bundle size under 300KB compressed for main thread

Mobile SEO

  • Full content parity between mobile and desktop
  • Mobile navigation links in DOM (not JS-click-injected)
  • LCP under 2.5s on mobile
  • INP under 200ms on mobile
  • CLS under 0.1 on mobile
  • Touch targets at least 48x48px
  • No horizontal scrolling on mobile viewports
  • Viewport meta tag present and correct

Crawl Budget

  • Faceted navigation blocked or canonicalized
  • Internal search pages blocked in robots.txt
  • No redirect chains longer than 1 hop
  • XML sitemap contains only indexable, canonical 200-status URLs
  • TTFB under 200ms for HTML responses
  • No orphan pages (every important page linked from at least one other page)
  • Deep pagination handled (noindex or blocked beyond page 5-10)
  • Server log analysis shows Googlebot focused on high-value pages

If you're looking at this list and thinking "we need help," that's what we do. Check out our pricing or reach out directly. We specialize in building and fixing headless sites where these exact issues tend to show up.

FAQ

How does JavaScript affect crawl budget?

JavaScript-rendered pages use more crawl budget because Google must process them in two stages: first crawling the raw HTML, then queuing the page for rendering. That extra rendering step draws on Google's infrastructure, so fewer of your pages get processed in a given crawl session.

Pages that serve content in the initial HTML cost Google less to process, so more of them get crawled and indexed.

Can Google render modern JavaScript frameworks like React and Vue?

Yes. Google's Web Rendering Service runs an evergreen version of Chromium that keeps pace with browser releases, supporting modern JavaScript including ES modules, async/await, and current DOM APIs. For SEO-critical pages, you should still serve pre-rendered HTML through server-side rendering or static generation rather than relying on client-side rendering alone.

The issue isn't capability. It's cost and delay. Google can render your React app, but it's slower and more resource-heavy than reading plain HTML.

What's the difference between crawl budget and index budget?

Crawl budget sets how many pages Googlebot fetches from your site in a given period, while index budget sets how many of those crawled pages Google actually adds to its search index. A page can be crawled and still never make it into the index.

Thin content, duplicate content, conflicting signals, and quality issues are the usual reasons a crawled page gets rejected from the index. Optimizing both matters: cut crawl waste so Google reaches your important pages, and keep those pages good enough to earn indexation.

How do I check if Googlebot can see my JavaScript-rendered content?

Use Google Search Console's URL Inspection tool: enter any URL, click "Test Live URL", and it returns the fully rendered HTML that Google sees after running your JavaScript, including any content, links, or structured data added by scripts. Compare that output against your page's raw source HTML to spot what depends on rendering.

You can also use Screaming Frog with JavaScript rendering enabled to audit this at scale across many templates.

Does mobile page speed directly affect rankings?

Yes. Google uses Core Web Vitals (LCP, INP, CLS) as a ranking signal, measured on the mobile version of your pages using real user data from the Chrome UX Report. A page with poor mobile performance metrics won't rank as well as an otherwise equal page with good metrics.

The effect stands out most for competitive queries where multiple results are otherwise similar in quality and relevance.

How often should I run a technical SEO audit?

For most sites, run a full technical SEO audit every quarter and keep continuous monitoring of key metrics running in between audits. Set up automated alerts in Google Search Console for crawl errors and indexing drops, so you catch problems before they hurt rankings.

If you're making big changes, such as launching new page templates, migrating to a new framework, or restructuring your site architecture, run an audit before and after.

What's the best rendering strategy for SEO in 2026?

For most sites, a hybrid rendering approach using a framework like Next.js or Astro gives the best results: Static Site Generation for stable content, Server-Side Rendering for pages that change per request, and Incremental Static Regeneration for large catalogs that update on a schedule.

Save client-side rendering for interactive features that don't need to be indexed, like user dashboards or admin interfaces.

Should I use dynamic rendering to solve JavaScript SEO issues?

Dynamic rendering is a valid stopgap, but it's not a long-term fix. Google has explicitly called it a workaround rather than a recommendation. A better approach is to fix the underlying architecture by adopting SSR or SSG so all users get the same HTML response.

Dynamic rendering, which means serving pre-rendered HTML to search engine bots while serving a client-side rendered version to users, adds maintenance overhead because you're basically maintaining two versions of every page. It also carries risk: if your bot detection breaks or your pre-rendering service fails, Google suddenly sees empty pages. Serving the same HTML to humans and bots removes both problems.