Skip to content
AscendQ.ca — Websites, Apps & SEO Systems

Tutorial 12 min read

How to Get a 100/100 Google Lighthouse Score

A perfect Google Lighthouse score is not a vanity metric — it is a proxy for everything that makes a website feel fast, trustworthy, and easy to rank. When Performance, Accessibility, Best Practices, and SEO all read 100, it means real visitors get content almost instantly, screen readers can navigate cleanly, search engines can crawl without friction, and Google’s Core Web Vitals are comfortably in the green. The trouble is that most "how to score 100" advice is either hand-wavy or quietly cheats by stripping out the analytics, fonts, and tracking that real businesses actually need.

This is the version with nothing hidden. These are the exact techniques we use to build sites — including this one — that score 100/100 on desktop and very close to it on mobile, while still running analytics, custom fonts, and lead-capture forms. No removing functionality to game the test. If you are staring at a yellow or red Lighthouse report and wondering where the points went, this walks through each lever and what it is worth.

What A Lighthouse Score Actually Measures

Lighthouse grades four independent categories, and a "100/100" usually means all four. Performance is the hard one and the one people obsess over, but it is also the one where the others quietly cost you points if you ignore them. It is worth knowing what each category rewards before you start optimising, because chasing the wrong number wastes hours.

Performance is dominated by a handful of lab metrics: Largest Contentful Paint (how fast the biggest visible element renders), Total Blocking Time and Interaction to Next Paint (how responsive the page is while scripts run), and Cumulative Layout Shift (how much the page jumps around as it loads). Accessibility checks colour contrast, alt text, ARIA labels, and descriptive links. Best Practices flags things like missing HTTPS, console errors, and oversized images. SEO checks crawlability, meta tags, and descriptive link text. Almost every point you lose maps to one specific, fixable item in the report — Lighthouse tells you exactly what to fix, in priority order.

Start With A Build Step, Not A CDN

The single biggest architectural decision is how your HTML, CSS, and JavaScript get to the browser. Pulling Tailwind, jQuery, or a framework off a CDN at runtime is the most common reason a site can never reach 100 — every one of those requests is render-blocking, unminified, and shipped whether the page uses it or not.

We build static HTML ahead of time (this site uses Astro for static-site generation) and run Tailwind as a build step that strips every unused class. The result is a tiny, page-specific CSS file instead of a multi-hundred-kilobyte framework download. The principle applies whatever your stack: compile and tree-shake your CSS and JS at build time, ship only what the page uses, and let the browser do as little work as possible on arrival.

  • Use Tailwind (or any CSS) as a build step that purges unused styles — never the CDN runtime build
  • Pre-render pages to static HTML where you can, so the browser paints content without waiting on JavaScript
  • Minify and tree-shake everything; ship per-page bundles, not one giant app bundle

Tame Third-Party Scripts: Defer Google Tag Manager And Analytics

Third-party tags are where most real-world sites bleed performance. Google Tag Manager, ad pixels, chat widgets, and heavy analytics all run JavaScript on the main thread, and they almost always block interactivity (hurting Total Blocking Time and INP) and delay your largest paint. You rarely need to delete them — you need to stop them from running before your content does.

The fix is to load them as late as possible and off the critical path. Defer Google Tag Manager so it fires after the page is interactive, or delay it until the first user interaction (a scroll or tap) so the initial load is never charged for it. For analytics, we use a lightweight, privacy-friendly script loaded with the standard async tag rather than the heavier tagged-events build, and we fire custom events manually with plain function calls. That alone removed a "forced reflow" warning for us — the tagged-events script was reading layout properties on load and forcing the browser to recalculate the page geometry mid-render.

  • Defer GTM/analytics so they execute after the page is interactive — never in the <head> blocking render
  • Consider delay-until-interaction loading (fire on first scroll/click) for the heaviest tags
  • Prefer a lightweight analytics script over heavy "auto-event" builds that read layout and force reflows
  • Fire custom events with manual function calls instead of pulling in extra tracking JavaScript

Move Scripts To The Bottom And Ship Zero Render-Blocking JavaScript

Anything in the <head> that is not async or deferred stops the browser from rendering until it has downloaded and executed. The goal is for the page to paint completely before a single byte of non-critical JavaScript runs. We put the little JavaScript we do need (a mobile-menu toggle, a contact-form handler) inline at the bottom of the page or as deferred scripts, so the critical render path contains only HTML and CSS.

On a content site you should be able to get genuinely close to zero blocking JavaScript. If a feature seems to require client-side JS, ask whether it can be done at build time instead. Our live page-speed score badge and our Google reviews are both fetched once at build (or cached server-side) and baked into static HTML, so the visitor’s browser never pays for them. That mindset — "can this happen before the visitor arrives?" — is what keeps Total Blocking Time near zero.

  • Mark every script async or defer; nothing JavaScript-heavy belongs in a render-blocking <head>
  • Inline tiny, essential scripts at the end of the body instead of loading external files
  • Move work to build time or the server (data fetching, reviews, badges) so the browser does less

Preload Fonts And Eliminate The Font Request Chain

Custom fonts are a sneaky Lighthouse killer. By default the browser discovers a font only after it has parsed the CSS that references it, creating a request chain — HTML, then CSS, then font — that delays your text rendering and can spike Largest Contentful Paint when your headline is the largest element. Lighthouse flags this as a "critical request chain".

Self-host your fonts (no third-party Google Fonts request), serve them as modern woff2, and preload the specific weights that appear above the fold so the browser fetches them in parallel with the CSS instead of after it. We preload all the weights used in the header and hero. Pair that with font-display: swap so text is visible immediately in a fallback font and never blocks rendering while the custom font loads — that protects both your paint time and your layout stability.

  • Self-host fonts as woff2 — avoid the extra DNS/connection cost of a third-party font host
  • Preload only the weights used above the fold so they load in parallel, not in a chain
  • Use font-display: swap so text paints instantly and the custom font swaps in without blocking
  • Subset fonts to the characters you actually use to shave kilobytes

Optimise Every Image: Format, Dimensions, And Zero Layout Shift

Images are usually the heaviest thing on a page and the most common cause of both a slow Largest Contentful Paint and a poor Cumulative Layout Shift. Two rules fix the vast majority of image problems: serve modern formats at the right size, and always reserve the space an image will occupy before it loads.

We let the build pipeline convert everything to WebP (or AVIF), generate responsive srcsets so phones download phone-sized images, and tune quality so the file is as small as it can be without visible loss — a hero image sitting under a dark overlay can be compressed far harder than a product photo. Critically, every image gets explicit width and height attributes so the browser reserves the exact space and the page never jumps as images arrive. That single habit is often the difference between a CLS of 0 and a failing score. For the one image that is your Largest Contentful Paint (usually the hero), preload it so it starts downloading immediately.

  • Convert images to WebP/AVIF at build time and serve responsive srcsets per device
  • Always set explicit width and height (or aspect-ratio) so the layout never shifts — CLS toward 0
  • Compress aggressively where quality loss is invisible (e.g. images behind overlays)
  • Preload the single LCP image; lazy-load everything below the fold

Inline Critical CSS And Cache Assets Forever

Two server-side levers close out the Performance category. First, render-blocking CSS: a separate stylesheet request delays your first paint, so for small sites we inline the CSS straight into the HTML head, removing the request entirely. The browser paints the moment the HTML arrives.

Second, caching. Lighthouse explicitly flags assets with short cache lifetimes under "Serve static assets with an efficient cache policy". Because build tools fingerprint filenames with a content hash (the filename changes whenever the file changes), it is completely safe to cache those files for a year as immutable. We set Cache-Control: public, max-age=31536000, immutable on all hashed assets and fonts, while keeping HTML uncached so content stays fresh. One caveat from hard experience: a CDN in front of your server (like Cloudflare) can override your origin cache headers with its own shorter TTL — if PageSpeed still complains after you have set the headers correctly, check the CDN’s "Browser Cache TTL" setting and set it to respect your origin headers.

  • Inline critical CSS for small sites to remove the render-blocking stylesheet request
  • Set long, immutable Cache-Control on content-hashed assets and fonts (a full year is safe)
  • Keep HTML out of long caches so updates ship instantly
  • Watch for a CDN overriding your cache headers — set it to "respect existing headers"

Do Not Forget Accessibility, Best Practices, And SEO

Performance gets the attention, but the other three categories are where easy points hide — and losing them means you do not get your perfect 100. The good news is that they are mostly checklists, not engineering problems, and fixing them makes your site genuinely better for users and search engines.

Accessibility wants sufficient colour contrast, an alt attribute on every image, an aria-label on every icon-only button, a single logical heading order, and labelled form inputs. Best Practices wants HTTPS, no console errors, correct image aspect ratios, and no deprecated APIs. SEO wants a unique title and meta description per page, a canonical URL, descriptive link text (Lighthouse literally keeps a list of non-descriptive phrases — we lost a point once for a mobile button that just said "Start", and fixed it by changing the text to "Start Project"), valid structured data, and a working robots.txt and sitemap. Run the audit, read each flagged item, and clear them one by one — they almost always point to the exact element.

  • Alt text on every image, aria-labels on icon buttons, AA-contrast colours, logical heading order
  • HTTPS everywhere, zero console errors, correct image dimensions, no deprecated APIs
  • Unique title + meta description + canonical per page; descriptive link text (avoid "click here"/"start")
  • Valid JSON-LD structured data, a clean robots.txt, and a discoverable sitemap

Test Honestly: Lab Vs. Field, Desktop Vs. Mobile

A score is only meaningful if you measure it the way Google does. Always audit the production build, not your dev server — dev builds are unminified and unbundled and will never reflect reality. Run Lighthouse in an incognito window with extensions disabled, because browser extensions inject scripts that tank the score and have nothing to do with your site.

Expect desktop and mobile to differ: mobile is throttled to a slower CPU and network, so a perfect desktop score commonly lands around 98–99 on mobile, and that is normal rather than a defect. Be wary of anyone claiming a permanent, guaranteed "100/100" — Lighthouse scores vary run to run and across conditions. We show a live PageSpeed score on our own homepage rather than a hardcoded badge, precisely because the honest number is more credible than a number frozen in a screenshot. Optimise for the real-world field data (Core Web Vitals from actual visitors) and the lab score will follow.

Frequently Asked Questions

Is a 100/100 Lighthouse score actually achievable for a real business site?

Yes — including analytics, custom fonts, and lead-capture forms — if the site is built static with a purged CSS build step, defers all third-party scripts, ships near-zero render-blocking JavaScript, preloads fonts, optimises images with explicit dimensions, and caches hashed assets long-term. Desktop 100 is realistic; mobile commonly lands at 98–99 due to throttling, which is normal.

What is the single biggest cause of a low Lighthouse performance score?

Third-party JavaScript — Google Tag Manager, ad pixels, chat widgets, and heavy analytics. They block the main thread and delay interactivity. Deferring them or delaying them until the first user interaction is usually the single largest win, followed by eliminating render-blocking CSS/JS in the <head>.

Does removing Google Tag Manager hurt my marketing?

You do not need to remove it — you need to defer it so it runs after the page is interactive, or delay it until the first scroll or click. Your tags still fire and your data is still collected; the initial page load just is not penalised for waiting on them.

Why is my mobile score lower than desktop?

Lighthouse throttles mobile to a slower CPU and network to simulate a mid-range phone on a poor connection. A site that scores 100 on desktop will often score 98–99 on mobile. That gap is expected and is not a sign that something is broken.

How do I fix "Serve static assets with an efficient cache policy"?

Set a long, immutable Cache-Control header (max-age=31536000, immutable) on content-hashed files and fonts, while keeping HTML uncached. If the warning persists after that, a CDN like Cloudflare may be overriding your origin headers — set its Browser Cache TTL to "Respect Existing Headers".

Do I need to fix Accessibility and SEO to get a perfect score?

Yes. Lighthouse reports four separate categories, and "100/100" means all of them. Accessibility, Best Practices, and SEO are mostly checklists — alt text, ARIA labels, contrast, HTTPS, unique meta tags, descriptive links, and valid structured data — so they are quick wins once Performance is sorted.

Reach the Summit

Want help putting this into practice?

We bring a quarter of a century of scale to your website, SEO, AI, and growth systems.

Start the Conversation

Stuck below 100? Get a free PageSpeed audit of your site.