The Complete Lighthouse Guide: SEO, Accessibility & Best Practices

Back to Blog

Why all four Lighthouse metrics matter

Google Lighthouse scores your website on four metrics: Performance, Accessibility, Best Practices, and SEO. Most developers focus on Performance and ignore the rest. That's a mistake.

In our previous articles, we covered Performance optimization in detail—how to achieve 100/100 on PageSpeed and why professional websites often score poorly. Those techniques handle the Performance pillar.

This guide completes the picture. We'll cover the three remaining pillars: SEO, Accessibility, and Best Practices. Together with the Performance techniques from our earlier articles, you'll have everything needed to achieve 100/100 across all four metrics.

Why all four matter:

  • Performance affects load times and user experience
  • SEO determines whether Google can find and rank your site
  • Accessibility ensures everyone can use your site, including people with disabilities
  • Best Practices covers security, modern standards, and technical correctness

On every demo site we've built, SEO, Accessibility, and Best Practices score 100/100—no exceptions. Performance occasionally dips a few points on mobile (Nuxt overhead, Cloudflare scripts), but typically hits 100 as well. Seven out of eight scores are always perfect; often all eight are. This guide documents exactly how.


SEO: Making Your Site Discoverable

The Foundation Files

Before Google indexes your site, it checks two files: robots.txt and sitemap.xml. Missing these doesn't break your site, but it slows discovery significantly.

robots.txt tells crawlers which pages to index. Place it at your site root:

User-agent: *
Allow: /
Sitemap: https://yoursite.com/sitemap.xml

Common mistakes:

  • Using Disallow: / (blocks all crawlers—your site won't be indexed)
  • Forgetting the sitemap reference
  • Wrong file location (must be at root, not in a subfolder)

sitemap.xml maps all your pages. For small sites, write it manually:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://yoursite.com/</loc>
    <lastmod>2025-12-07</lastmod>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://yoursite.com/about</loc>
    <priority>0.8</priority>
  </url>
</urlset>

Strategy tip: Less is more. Don't index everything. Your Terms of Service page doesn't need to rank. A focused sitemap with strong pages beats a bloated one with thin content.

Meta Tags That Matter

Search engines and social platforms read specific HTML tags. Missing these means broken-looking links when shared.

Essential tags in your <head>:

<!-- Page basics -->
<html lang="en">
<title>Your Page Title - Under 60 Characters</title>
<meta name="description" content="150-160 characters. Shows in search results.">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="https://yoursite.com/page-url">

<!-- Open Graph (Facebook, LinkedIn, Slack) -->
<meta property="og:title" content="Your Page Title">
<meta property="og:description" content="Same as meta description">
<meta property="og:url" content="https://yoursite.com/page-url">
<meta property="og:image" content="https://yoursite.com/og-image.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:type" content="website">

<!-- Twitter/X -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Your Page Title">
<meta name="twitter:image" content="https://yoursite.com/og-image.jpg">

Why these matter:

  • Title and description: What appears in Google search results
  • Canonical URL: Prevents duplicate content issues
  • Open Graph: Controls how links appear when shared on social platforms
  • lang="en": Required for accessibility—tells screen readers which language to use

Common mistakes:

  • Title over 60 characters (Google truncates with "...")
  • Missing OG image dimensions (Facebook won't show preview)
  • Forgetting the lang attribute on <html> (fails Lighthouse accessibility check)

Structured Data (JSON-LD)

Structured data tells Google what type of content you have, enabling rich results in search:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Your Company",
  "url": "https://yoursite.com",
  "logo": "https://yoursite.com/logo.png",
  "sameAs": [
    "https://twitter.com/yourcompany",
    "https://linkedin.com/company/yourcompany"
  ]
}
</script>

Other useful types: Person (portfolios), LocalBusiness (physical locations), Article (blog posts), FAQPage (can display directly in search results).

Testing: Use Google's Rich Results Test to validate your JSON-LD.

Google Search Console Setup

After deploying, verify your site with Google Search Console:

  1. Add your domain
  2. Verify via DNS TXT record or meta tag
  3. Submit your sitemap URL
  4. Request indexing for important pages

Expect 1-2 weeks before pages appear in search results. Use Search Console to monitor progress.

Cloudflare Users: Check Scrape Shield

If you're on Cloudflare, check your Scrape Shield settings. The default "Email Address Obfuscation" injects a 500ms render-blocking script into every page. We lost 8 points on multiple demos before catching this.

Fix: Security → Scrape Shield → Disable "Email Address Obfuscation"


Accessibility: Building for Everyone

Accessibility isn't charity—it's good engineering. An accessible site works better for everyone: keyboard users, screen reader users, people with slow connections, and users on mobile devices.

Semantic HTML Structure

Lighthouse checks for proper HTML landmarks. Missing these fails the accessibility audit.

Required landmarks:

<header>
  <nav><!-- Navigation here --></nav>
</header>

<main>
  <!-- All primary content MUST be inside <main> -->
  <article>
    <h1>Page Title</h1>
    <!-- Content -->
  </article>
</main>

<footer>
  <!-- Footer content -->
</footer>

The <main> element is critical. Lighthouse specifically checks for it. Screen readers use it to skip navigation and jump directly to content.

Heading Hierarchy

Use one <h1> per page. Follow logical order: h1 → h2 → h3. Never skip levels (no h1 → h3).

Why this matters: Screen reader users navigate by headings. Skipped levels confuse navigation. Headings should describe content structure, not just style text.

Color Contrast

WCAG AA requires minimum contrast ratios:

  • Normal text (< 18px): 4.5:1 contrast ratio
  • Large text (≥ 18px or ≥ 14px bold): 3:1 contrast ratio
  • UI components (buttons, form borders): 3:1 contrast ratio

Links require special attention. Color alone isn't sufficient to distinguish links from surrounding text. Use underlines or other visual indicators.

Testing: Chrome DevTools → Inspect element → Accessibility tab shows contrast ratios. Or use WebAIM Contrast Checker.

Image Alt Text

Every image needs an alt attribute:

<!-- Meaningful image: describe the content -->
<img src="team-photo.jpg" alt="CodeCrank team at the 2025 developer conference">

<!-- Decorative image: use empty alt (not missing) -->
<img src="decorative-line.svg" alt="">

Common mistakes:

  • Missing alt attributes entirely (fails audit)
  • Using "image of..." prefix (redundant—screen readers already announce it's an image)
  • Empty alt on meaningful images (screen readers skip them entirely)

Form Accessibility

Every input needs an associated label:

<!-- Correct: label linked via 'for' attribute -->
<label for="email">Email Address</label>
<input type="email" id="email" name="email">

<!-- Also correct: input nested inside label -->
<label>
  Email Address
  <input type="email" name="email">
</label>

For required fields, don't rely on asterisks alone. Use the required attribute and aria-required="true".

Interactive Elements

Buttons and links need accessible names. Icon-only buttons need ARIA labels:

<!-- Icon button: needs aria-label -->
<button aria-label="Open menu">
  <svg><!-- hamburger icon --></svg>
</button>

<!-- Decorative icons: hide from screen readers -->
<span aria-hidden="true">★</span> 4.8 rating

Keyboard navigation: All interactive elements must be reachable via Tab key. Focus indicators must be visible (don't remove outlines without providing alternatives).


Best Practices: Security and Standards

Best Practices covers security, modern web standards, and technical correctness. Most failures here are easy to fix.

HTTPS Everywhere

Serve all content over HTTPS. No mixed content (HTTP resources on HTTPS pages). Modern hosting platforms handle this automatically.

Safe External Links

External links should use rel="noopener":

<a href="https://external-site.com" target="_blank" rel="noopener">
  External Link
</a>

This prevents the external page from accessing your window.opener object—a security vulnerability. Lighthouse flags links missing this attribute.

No Console Errors

Open DevTools Console before deploying. Fix all errors. Common culprits:

  • Missing resources (404s for images, scripts, fonts)
  • JavaScript errors from typos or undefined variables
  • Deprecated API warnings

Zero tolerance: Any console error can fail the Best Practices audit.

Image Aspect Ratios

Images need explicit dimensions to prevent layout shift:

<img src="photo.jpg" width="1200" height="800" alt="Description">

Or use CSS aspect-ratio:

img {
  width: 100%;
  height: auto;
  aspect-ratio: 3/2;
}

This prevents Cumulative Layout Shift (CLS) and satisfies Best Practices requirements for proper image sizing.

Modern Standards

Avoid deprecated APIs:

  • Use fetch() instead of XMLHttpRequest
  • Use addEventListener() instead of inline onclick attributes
  • Never use document.write()

Icons and Favicons

The finishing touches that make your site look complete:

Required files:

  • favicon.ico (32×32, legacy browsers)
  • favicon.svg (scalable, modern browsers)
  • apple-touch-icon.png (180×180, iOS home screen)
  • icon-192.png and icon-512.png (Android, PWA)

HTML tags:

<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.json">

Missing favicons don't fail Lighthouse, but they make your site look unfinished. Some browsers show broken icons, others show nothing.

Tool: RealFaviconGenerator.net generates all sizes from one image.


The Complete Checklist

Performance (covered in Article 1 & Article 2):

  • Critical CSS inlining
  • AVIF/WebP images with explicit dimensions
  • Deferred JavaScript loading
  • Zero layout shift

SEO:

  • robots.txt and sitemap.xml
  • Title, description, canonical URL
  • Open Graph and Twitter meta tags
  • Structured data (JSON-LD)
  • Google Search Console verification

Accessibility:

  • Semantic HTML landmarks (<main>, <nav>, <header>, <footer>)
  • Proper heading hierarchy (single h1, no skipped levels)
  • WCAG color contrast (4.5:1 for text)
  • Alt text on all images
  • Form labels properly associated
  • ARIA labels for icon buttons

Best Practices:

  • HTTPS everywhere
  • rel="noopener" on external links
  • Zero console errors
  • Explicit image dimensions
  • No deprecated APIs

The Expert Take

On every demo in our portfolio, SEO, Accessibility, and Best Practices hit 100/100. Performance usually does too, though it occasionally dips a few points on mobile due to framework overhead or CDN scripts. You can verify this yourself—click "PageSpeed Me" on any of our sites.

Time investment: First-time setup takes 4-6 hours. Once you know the patterns, subsequent sites take 1-2 hours.

Most agencies don't publish their Lighthouse scores. We put a verification button on every site we build. The work should speak for itself.

My side business DCTSoft builds custom websites for small businesses in record time, implementing all these techniques and often achieving perfect scores across the board.


This completes our PageSpeed series. For performance optimization techniques, see How to Achieve 100/100 on PageSpeed.

Back to Blog