Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.
SEOMedium

Fix invalid links

Detects malformed, empty, or syntactically invalid link formats on the page

Utilities
Quick take
Typical fix time 10 min
  • Invalid `<a>` tags (empty href, JavaScript voids, non-URL values) are not crawlable — Googlebot cannot follow them
  • Links must use crawlable `<a href='...'>` elements with valid absolute or relative URLs to pass PageRank and be followed
  • JavaScript-only navigation (onClick handlers without `href`) is invisible to search engine crawlers
Why it matters: Google can only follow links declared as valid `<a href>` elements with crawlable URL values. Invalid links — empty hrefs, JavaScript voids, or non-URL content — prevent PageRank from flowing to linked pages and stop Googlebot from discovering those destinations.

Rule Details

Not all <a> elements are crawlable by Googlebot. Google's crawlable-link documentation (opens in new tab) requires a valid href, so malformed anchors break discovery in the same way they undermine broader internal linking.

Code Examples

❌ Avoid — JavaScript void href (not crawlable)

<a href="javascript:void(0)" onclick="navigate('/products')">Products</a>
<!-- Googlebot sees href="javascript:void(0)" and does not follow -->

❌ Avoid — missing href attribute

<a onclick="goToPage('/about')">About Us</a>
<!-- No href: Googlebot cannot follow this link -->

❌ Avoid — empty href

<a href="">Home</a>
<!-- Empty href: not a valid crawlable link -->

❌ Avoid — div/span navigation (common in SPAs)

<div onclick="router.push('/contact')" class="nav-link">Contact</div>
<!-- Not an <a> element: completely invisible to crawlers -->
<a href="/products">Products</a>
<a href="https://example.com/about">About Us</a>
<a href="/contact">Contact</a>
<!-- href provides the URL for crawlers; JS enhances the UX -->
<a href="/products/modal-details" onclick="openModal(event, '/products/modal-details')">
  View Details
</a>
 
<script>
function openModal(event, url) {
  event.preventDefault()
  // Open modal instead of navigating
  showModal(url)
}
</script>
<!-- The fragment must match an existing id on the page -->
<a href="#features">Jump to Features</a>
 
<section id="features">  <!-- id="features" exists -->
  <h2>Features</h2>
</section>
// ✅ React Router — renders as <a href="/products">
<Link to="/products">Products</Link>
 
// ✅ Next.js — renders as <a href="/about">
<Link href="/about">About Us</Link>
 
// ❌ Avoid — useNavigate without a corresponding <a>
<button onClick={() => navigate('/products')}>Products</button>
// This is not crawlable; use <Link> instead

Why It Matters

  • Discovery failure: Pages only linked via invalid <a> elements may never be discovered by Googlebot, even if the route exists in your frontend router.
  • PageRank blocking: Invalid links cannot pass PageRank to destination pages.
  • Accessibility: Invalid links also fail accessibility checks — screen readers and keyboard users cannot navigate them, and the underlying HTML behavior is covered in MDN's anchor element reference (opens in new tab).

Google's crawlers can follow links that:

  • Are <a> elements (not <div>, <span>, or <button> with click handlers)
  • Have an href attribute
  • Have an href value that is a valid relative or absolute URL (not javascript:, void(0), or empty)

Exceptions

  • Staging, utility, login, account, or internal search pages may intentionally use different crawl or index signals if they are not meant to rank.
  • Temporary migration states can produce noisy intermediate signals; flag the live production URL pattern, not one-off transition artifacts.
  • When redirects, canonicals, robots directives, or indexability signals conflict, fix the strongest final signal first instead of reporting every downstream symptom as a separate blocker.

Standards

  • Use these references as the standard for the final search-facing HTML, metadata, and crawl behavior.
  • Check the implementation against Google Search Central: Crawlable links before treating the rule as satisfied.
  • Check the implementation against MDN: The anchor element before treating the rule as satisfied.

Verification

Automated Checks

  • Run a site crawl and filter for links that are not followed.

Manual Checks

  • Use browser DevTools to query: document.querySelectorAll('a:not([href]), a[href=""], a[href^="javascript:"]')
  • Review SPA navigation patterns — ensure all navigation uses <Link> or <a href> components, not raw onClick handlers.
  • Fix by adding real href values or replacing non-anchor elements with proper <a> elements.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Parse all `<a>` elements on the page. Flag links where `href`: (1) is empty (`href=''` or `href='#'` with no meaningful target). (2) starts with `javascript:` (e.g., `href='javascript:void(0)'`). (3) starts with `mailto:` or `tel:` — these are valid but not crawlable for page discovery. (4) contains only a fragment identifier that references an anchor not present on the page. (5) is absent entirely (`<a>` without any href attribute). Report the count per type.

Fix

Auto-fix issues

1. For links using `href='javascript:void(0)'` or `href='#'` as navigation triggers: - Add a real URL as the href value - Use JavaScript to enhance the navigation, not replace it - Before: `<a href="javascript:void(0)" onclick="openModal()">View Details</a>` - After: `<a href="/products/details" onclick="openModal(event)">View Details</a>` 2. For `<a>` elements without href (used as button-like elements): - If they trigger navigation: add href - If they trigger actions only: change to `<button>` elements 3. For empty `href=''`: either add the correct URL or remove the `<a>` wrapper 4. For `href='#'` anchors: use meaningful fragment IDs that reference actual page sections (`href='#features'` where `id='features'` exists)

Explain

Learn more

Google's documentation states that crawlable links must be `<a>` tags with an `href` attribute containing a valid URL. Links with `javascript:` hrefs, empty hrefs, or no href attribute are not followed by crawlers. This means pages only reachable through invalid links are not discovered by Googlebot, and any intended PageRank flow is blocked.

Review

Code review

Query all `<a>` elements in the rendered DOM. For each, extract the `href` attribute. Flag: absent href, empty string, `'#'` only, values starting with `javascript:`, values starting with `void`. Separately flag `<div>`, `<span>`, or `<button>` elements with `onclick` navigation handlers that lack a corresponding `<a href>` — these are not crawlable.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

SEO Link Best Practices for Google | Google Search Central  |  Documentation  |  Google for Developers

Google uses links as a signal when determining the relevancy of pages and to find new pages to crawl. Learn how to make your links are crawlable and improve you…

Google for DevelopersGuide

Rules that often go hand-in-hand with this one.

Resolve internal broken links

Detects and fixes internal links that return 404 or 5xx errors to improve user experience.

SEO
Add relevant external links

Validates that pages include outgoing links to authoritative external sources where appropriate

SEO
Do not link from HTTPS to HTTP

Detects links from HTTPS pages to HTTP destinations, which trigger mixed content warnings and lose ranking signals

SEO
Weak Internal Links

Detects pages with very few dofollow internal links pointing to them, indicating poor link equity distribution and crawl discoverability.

SEO

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385