A Shopify store owner installed a premium mega-menu app last year. The app had great reviews, beautiful animations, and a clean interface. Sales stayed flat. Three months later, Google Search Console showed a 40% drop in crawled pages. The problem wasn’t the menu design — it was that the menu links only existed in JavaScript. Google’s crawler saw a homepage with no links to category pages. The categories were orphaned.
This is the most common navigation SEO mistake I see: a menu that looks perfect to users but is invisible to search engines. The fix isn’t complex, but it requires understanding the difference between real HTML links and JavaScript-only navigation patterns — and knowing how to audit your own site to catch the problem before it costs you traffic.
- Google crawls HTML anchor tags with href attributes — JavaScript click handlers don't count.
- View Source shows raw HTML before JavaScript runs — this is what Google sees first.
- Common mistakes: onclick handlers, javascript:void(0), div elements with data-url attributes.
- Fix: render links in HTML on the server, enhance with JavaScript for interaction only.
What Google’s crawler actually sees
When Google crawls a page, it makes an HTTP request to your server and receives HTML in response. The crawler parses that HTML looking for links — specifically, <a> tags with href attributes. Every URL it finds gets added to the crawl queue.
This is the first pass. Google’s crawler can execute JavaScript (it uses a version of Chrome under the hood), but JavaScript rendering happens later, in a second pass, and it’s not guaranteed for every page. Google prioritizes the first-pass HTML crawl because it’s fast and reliable. Pages that depend entirely on JavaScript for navigation are at a disadvantage.
Here’s what Google looks for:
<a href="/collections/summer-shoes">Summer Shoes</a>
This is a real link. The href attribute contains a URL. Google’s crawler extracts /collections/summer-shoes and adds it to the crawl queue. This page will be crawled and indexed.
Here’s what Google ignores or misses during the first pass:
<div onclick="window.location='/collections/summer-shoes'">Summer Shoes</div>
<a href="javascript:void(0)" onclick="navigate('/collections/summer-shoes')">Summer Shoes</a>
<button data-url="/collections/summer-shoes">Summer Shoes</button>
None of these are anchor tags with real href attributes. The URLs exist in the code (in onclick handlers or data attributes), but Google’s first-pass crawler doesn’t execute JavaScript or parse data attributes when discovering links. These links are invisible during the initial crawl.
Google might eventually discover these pages through other means (sitemaps, external backlinks, JavaScript rendering), but they won’t get the crawl priority or link equity that comes from being linked in the main navigation HTML.
View Source: the definitive test
You don’t need special tools to check whether your navigation is crawlable. Every browser has a “View Source” function that shows the raw HTML sent by the server before any JavaScript runs. This is exactly what Google’s first-pass crawler sees.
How to check
- Open your store’s homepage in Chrome, Firefox, or Safari.
- Right-click anywhere on the page and select “View Page Source” (or press Ctrl+U on Windows, Cmd+Option+U on Mac).
- A new tab opens showing the raw HTML.
- Press Ctrl+F (Cmd+F on Mac) and search for the URL of one of your main category pages — for example,
/collections/women.
If you find the URL inside an anchor tag like this:
<a href="/collections/women">Women's Clothing</a>
Your navigation is crawlable. Google can follow that link.
If the URL doesn’t appear in View Source at all, or if it only appears in a <script> tag or a data attribute like this:
<div class="menu-item" data-url="/collections/women">Women's Clothing</div>
Your navigation is not crawlable in the first pass. Google’s initial HTML crawl will miss it.
Mobile vs desktop
Many stores use different navigation implementations for mobile and desktop. The desktop version might use semantic HTML anchor tags while the mobile version uses JavaScript-only hamburger menus. Since Google uses mobile-first indexing (the mobile version is the primary version Google crawls), you need to check the mobile HTML separately.
In Chrome:
- Open DevTools (F12 or right-click → Inspect).
- Click the device toolbar icon (or press Ctrl+Shift+M / Cmd+Shift+M).
- Select a mobile device from the dropdown (iPhone SE, for example).
- Reload the page.
- Right-click and View Source again.
Search for your category URLs in the mobile HTML. If they don’t appear, Google’s mobile crawler isn’t seeing your navigation links.
Common patterns that fail the View Source test
Pattern 1: JavaScript-generated mega menus
Many modern menu apps work like this:
- The server sends minimal HTML — just a menu trigger button.
- When the user hovers or clicks, JavaScript fetches menu data from an API or parses a JSON object.
- JavaScript builds the full DOM (including all
<a>tags) and injects it into the page.
Example HTML sent by the server:
<button id="mega-menu-trigger">Shop</button>
<div id="mega-menu-container"></div>
<script>
const menuData = {
"women": {"label": "Women", "url": "/collections/women"},
"men": {"label": "Men", "url": "/collections/men"}
};
// JavaScript builds and injects links when user interacts
</script>
View Source shows the button and the empty container. The links don’t exist yet. Google’s first-pass crawl sees no links to category pages.
Pattern 2: Single-page app routing
Stores built with React, Vue, or other SPA frameworks often use client-side routing. The menu might look like this in the framework code:
<Link to="/collections/summer-shoes">Summer Shoes</Link>
Whether this is crawlable depends on how the framework renders it and whether the app uses server-side rendering. If the app is a pure client-side SPA (the server sends a single index.html shell and JavaScript renders everything), View Source shows an empty shell with no navigation links:
<!DOCTYPE html>
<html>
<head><title>Store</title></head>
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
</html>
All content, including navigation, is rendered by JavaScript. Google’s first-pass crawl sees nothing.
Pattern 3: Onclick handlers with no href
Some menus use anchor tags but put the navigation logic in onclick handlers and use javascript:void(0) as the href:
<a href="javascript:void(0)" onclick="goToCategory('women')">Women</a>
This looks like a link to users and even behaves like a link when clicked, but javascript:void(0) is not a real URL. Google’s crawler extracts javascript:void(0) from the href attribute and discards it because it’s not a crawlable URL. The real destination (/collections/women) is buried in the JavaScript function goToCategory(), which the crawler doesn’t execute during first-pass HTML parsing.
Pattern 4: Divs and buttons with data attributes
Developers sometimes build navigation using non-semantic elements:
<div class="nav-item" data-url="/collections/women" onclick="navigate(this.dataset.url)">
Women
</div>
This works for users (JavaScript reads the data attribute and navigates when clicked), but there’s no <a> tag and no href attribute. Google’s crawler doesn’t look for URLs in data attributes. The link is invisible.
How to fix JavaScript-only links
Fix 1: Render links in HTML, enhance with JavaScript
The best approach: your server (or static site generator) outputs complete HTML with real anchor tags. JavaScript adds interactivity on top.
Server-rendered HTML:
<nav>
<a href="/collections/women">Women</a>
<a href="/collections/men">Men</a>
<a href="/collections/kids">Kids</a>
</nav>
This HTML is crawlable. Google sees the links immediately.
Then JavaScript enhances it:
document.querySelectorAll('nav a').forEach(link => {
link.addEventListener('click', (e) => {
// Add smooth transitions, analytics, etc.
// Let the browser navigate normally (don't preventDefault)
});
});
The navigation works without JavaScript (graceful degradation), works perfectly with JavaScript (progressive enhancement), and is crawlable in both cases.
Fix 2: Use server-side rendering for SPAs
If your store is a single-page app built with React, Vue, or similar, implement server-side rendering (SSR) or static site generation (SSG).
Frameworks that make this easy:
- Next.js for React
- Nuxt for Vue
- SvelteKit for Svelte
- Gatsby for static sites
These frameworks render the full HTML (including navigation) on the server. The initial page load delivers complete, crawlable HTML. Then JavaScript hydrates the page and takes over for subsequent navigation, giving you the SPA experience for users and crawlable HTML for search engines.
Fix 3: Check your menu app settings
If you’re using a Shopify menu app, check the app’s settings for an “SEO mode” or “server-side rendering” option. Many apps offer this as a toggle. When enabled, the app renders navigation links in Liquid (Shopify’s server-side templating language) instead of JavaScript.
If your app doesn’t offer this option and you’ve confirmed (via View Source) that your navigation isn’t crawlable, consider switching to an app that does. Navi+ AI Menu Builder renders all links in HTML by default — the links are in the initial HTML payload, and JavaScript only handles interaction and animation.
Fix 4: Progressive enhancement for hamburger menus
Mobile hamburger menus often hide navigation until the user taps the icon. The menu can still be crawlable as long as the links exist in the HTML:
<nav class="mobile-menu" aria-hidden="true">
<a href="/collections/women">Women</a>
<a href="/collections/men">Men</a>
</nav>
CSS hides the menu by default:
.mobile-menu {
display: none;
}
.mobile-menu.is-open {
display: block;
}
JavaScript toggles the class when the hamburger is tapped:
hamburgerButton.addEventListener('click', () => {
mobileMenu.classList.toggle('is-open');
});
The links exist in the HTML (View Source shows them), so Google can crawl them even though they’re hidden by CSS. This is fine — Google doesn’t penalize hidden content as long as it’s not deceptive (you’re not hiding keyword-stuffed spam).
What doesn’t work: building the mobile menu DOM with JavaScript only when the hamburger is tapped:
hamburgerButton.addEventListener('click', () => {
const menu = document.createElement('nav');
menu.innerHTML = '<a href="/collections/women">Women</a>...';
document.body.appendChild(menu);
});
This menu doesn’t exist in the HTML until the user interacts. Google’s crawler doesn’t tap hamburger icons. The links are invisible.
Testing your fix
After you’ve updated your navigation, verify that it’s now crawlable:
- View Source test: Reload your homepage and View Source. Search for category URLs. Confirm they appear in anchor tags.
- JavaScript disabled test: In Chrome DevTools, disable JavaScript (Settings → Debugger → Disable JavaScript). Reload your homepage. Confirm that navigation links are visible and clickable. Clicking a link should navigate to the category page (the page will look broken without JavaScript, but the navigation should work).
- Google Search Console: Wait a few days, then check the Coverage report (Pages → Indexed). If previously orphaned category pages start showing up as indexed, your fix worked.
Check both desktop and mobileRun the View Source test on both desktop and mobile versions of your site. If your mobile navigation uses a different implementation (hamburger menu, different app, simplified structure), test it separately. Google's mobile-first indexing means the mobile version is what matters for rankings.
Why this matters more than you think
Navigation isn’t just one of many internal links on your site — it’s the most prominent, consistent set of links Google sees. The main navigation appears on every page. It’s in the header, near the top of the HTML document, where Google expects to find important links. When Google crawls your homepage, the navigation is the first set of links it encounters.
If those links aren’t crawlable, Google doesn’t just miss a few pages. It loses the primary signal for understanding your site architecture. Category pages become orphans. Products linked only from those category pages become orphans one level deeper. The entire site structure collapses from Google’s perspective.
And because navigation is so consistent (same menu on every page), the impact compounds. If your homepage navigation is JavaScript-only, every page on your site has the same problem. Google crawls 100 pages and finds zero navigation links on all 100 pages. That’s not a minor SEO issue — it’s a foundational crawlability failure.
The View Source test takes 30 seconds. If your category URLs don’t appear in the raw HTML, you’ve found the most important SEO fix you can make. Everything else — keyword optimization, backlinks, technical improvements — builds on the assumption that Google can crawl your pages. Without crawlable navigation, that assumption is false.
This article is part of the larger guide on Navigation SEO: making sure Google can crawl your menu structure.