Symptoms
- Google shows your 404 page in search results
- Pre-rendered HTML contains “Loading…” or spinner
- Content is blank or incomplete
How the Renderer Decides Your Page Is Ready
The renderer loads your page in a headless browser and runs through these checks:- Network idle — waits up to 5 seconds for all network requests to finish
- Loading indicator check — looks for visible spinners or loading text
- Content thresholds — requires at least 100 characters of visible text and 20 DOM elements
What counts as a loading indicator?
The renderer detects these CSS selectors:If your app uses none of these indicators while fetching data, the renderer has no way to know it should keep waiting. It may capture a half-rendered page that technically passes the content thresholds.
Common Causes and Fixes
No loading indicators while fetching data
No loading indicators while fetching data
Cause: Your app fetches data after mount but doesn’t show any loading state. The renderer sees the initial shell (which may have enough DOM elements and text to pass thresholds) and captures it before data arrives.Fix: Add a recognized loading indicator while data is being fetched:Use any of these recognized patterns:
.loading, .spinner, .skeleton, [data-loading], or [aria-busy="true"].Custom loading indicators not detected
Custom loading indicators not detected
Cause: Your app uses custom class names like
.is-loading, .page-spinner, or [data-state="loading"] that the renderer doesn’t recognize.Fix: Switch to one of the recognized selectors, or add a recognized class alongside your custom one:Content takes too long to render
Content takes too long to render
Cause: Your page takes longer than 12 seconds to render meaningful content — usually due to slow API calls, large data fetches, or heavy client-side computation.Fix: Optimize data loading for your critical content path:
- Fetch only the data needed for initial render
- Defer non-essential data (comments, recommendations) to load after primary content
404 page being pre-rendered
404 page being pre-rendered
Cause: Your app checks authentication or data, then redirects to a 404 or login page before content loads.Fix:
- Ensure public pages don’t require authentication
- Don’t redirect before content is fetched
- Return proper 404 status codes (not redirects to a 404 page)
JavaScript chunk loading failures
JavaScript chunk loading failures
Cause: Code-split bundles fail to load during pre-rendering. This typically happens when a new deployment changes chunk hashes but old URLs are still being rendered.Common errors:
ChunkLoadErrorLoading chunk [name] failedFailed to fetch dynamically imported module
- Ensure all JS chunks are available at the URLs your app references
- If using hashed filenames, make sure old chunks remain accessible during deployment transitions
- Add error boundaries to gracefully handle chunk failures
Page content below minimum thresholds
Page content below minimum thresholds
Cause: Your page has fewer than 100 characters of visible text or fewer than 20 DOM elements. The renderer keeps waiting for more content until it times out.This commonly happens with:
- Pages that are mostly images or video with minimal text
- Single-purpose pages (e.g., a login form with just a few fields)
- Pages where content is rendered inside
<canvas>or<iframe>
After Fixing
Once you’ve fixed the issue in your code:- Go to your Hado SEO Dashboard
- Navigate to the affected domain
- Click Recrawl to trigger a fresh pre-render
- Verify with SEO Bot Crawler Test