Official statement
Google handles both Ajax approaches: pushState and hashbang (#!). The pushState method, when properly configured, works natively without additional setup for crawling. The hashbang requires more implementation work and remains a fallback solution for legacy sites that cannot migrate.
What you need to understand
What are pushState and hashbang in the context of Ajax?
Modern web applications often reload content without refreshing the entire page. This Ajax navigation poses a historical problem: how can Googlebot crawl these dynamic contents?
The hashbang (#!) method used URLs like example.com/#!product/12. It required a HTML snapshots system on the server side for Google to crawl the static versions. Heavy and complex.
The pushState API (HTML5) allows modifying the displayed URL without refreshing the page: example.com/product/12. The server sends complete HTML for each URL, making the site natively crawlable by search engines.
Why does Google specify that it supports both methods?
This statement is aimed at sites that adopted hashbang between 2010 and 2015 when it was the only solution available. Google assures them that their infrastructure remains functional.
For new projects, the message is clear: pushState is the standard. The phrase “generally does not require additional support” means that if your server returns complete HTML on every route, you are compliant.
The term “generally” introduces a nuance: some misconfigured pushState implementations may still cause issues. A server that returns an empty shell and loads everything with JavaScript remains invisible to Googlebot, even with pushState.
What are the practical implications for crawling?
With well-implemented pushState, each URL returns a complete HTML page from the server (SSR or pre-rendered). Googlebot crawls normally, extracts content, meta tags, and internal links. Nothing specific to configure.
With hashbang, you need to maintain a snapshots system or alternative URLs. This requires additional infrastructure, development time, and introduces desynchronization risks between the user version and the bot version.
- pushState works if the server returns complete HTML on all routes
- hashbang requires a snapshot mechanism to make the content accessible
- An Ajax implementation that loads everything with client-side JavaScript remains invisible to Google, regardless of the URL method
- JavaScript rendering on Googlebot exists but remains secondary and unpredictable for quick indexing
- The best approach remains Server-Side Rendering (SSR) or static site generation (SSG) coupled with pushState
SEO Expert opinion
Is this statement consistent with observed field practices?
Yes, absolutely. Single Page Applications (SPA) that use pushState with SSR (Next.js, Nuxt, SvelteKit) index smoothly. Audits show that Googlebot follows internal links, indexes content, and treats these sites like any traditional site.
On the other hand, SPAs that use pushState but load all content with client-side JavaScript face regular indexing issues. Google can technically execute JavaScript, but rendering delays, crawl budget consumption, and execution errors create gaps in indexing. [To verify]: Google never communicates precise statistics about the failure rate of JavaScript rendering on Googlebot.
What nuances should be considered in this statement?
Google states that pushState “generally does not require additional support.” This “generally” conceals a reality: it completely depends on your implementation.
If your server returns empty HTML with a div id="root" and loads React lazily, pushState changes nothing to the issue. You remain dependent on JavaScript rendering. If your server pre-renders every route and sends structured HTML, you are compliant.
The hashbang has not been recommended since around 2015. Google still supports it for backward compatibility, but no modern framework uses it. If you maintain a legacy hashbang site, this statement reassures you without encouraging you to stay on this stack.
When does this rule not apply?
Sites that combine Ajax and real-time sensitive content (feeds, dashboards, personalized user data) need to think differently. Google will crawl a generic version, not the personalized version for each user.
Full client-side Progressive Web Apps (PWAs) pose another challenge. Even with pushState, if critical content loads after user interaction (infinite scroll, tab clicks), Googlebot may miss it. JavaScript rendering has its limits: a 5-second timeout, no complex simulated interactions.
Practical impact and recommendations
What should you do if you use Ajax?
Prioritize pushState with Server-Side Rendering. Configure your framework (Next.js, Nuxt, Remix, SvelteKit) to pre-render or statically generate your routes. Each URL should return complete HTML with meta tags, titles, text, and internal links.
Test with curl or the browser’s “View Source” tool. If you see your content in the source HTML (not just after JavaScript loads), that’s a good sign. If you see an empty shell, Googlebot will see the same initially.
Check in Google Search Console the “URL Inspection” tab: look at the HTML rendering and the visual rendering. Compare them. If the HTML rendering is empty and everything appears in the visual rendering, you depend on JavaScript rendering. Risky.
What mistakes should you absolutely avoid?
Don’t rely on Google’s JavaScript rendering as your primary solution. It works, but with unpredictable indexing delays, higher crawl budget consumption, and execution error risks.
Don’t let your server return 200 codes for non-existent URLs. If /product/999999 (which doesn’t exist) returns the same empty HTML shell as /product/1, Google will crawl thousands of empty URLs. Set up proper 404s on the server side.
Don’t implement hashbang on a new project. This technique is obsolete and unnecessarily complicates your infrastructure. If you have a legacy hashbang site, plan a gradual migration to pushState + SSR.
How can you check if your Ajax implementation is SEO-friendly?
Use Screaming Frog or Sitebulb in “JavaScript rendering disabled” mode. If the crawler finds all your content, titles, and internal links, your site is natively crawlable. If pages appear empty, you have a problem.
Compare indexing performance in Search Console before and after migration. A properly configured pushState + SSR site sees its indexing rate increase and positions stabilize faster.
- Set up Server-Side Rendering or static generation on all main routes
- Test each URL with curl to check for the presence of complete HTML content
- Enable pushState to manage Ajax navigation without refreshing the page
- Check HTTP codes: proper 404s on non-existent URLs, no soft 404s
- Validate HTML rendering in Search Console (URL Inspection tab)
- Monitor crawl budget and indexing rate in Search Console after migration
💬 Comments (0)
Be the first to comment.