Back to Insights

SEO/GEO · On-Site

The On-Site SEO Workout

PageSpeed Insights is the scoreboard, not the workout. This is the training program — run on this exact site, with the numbers to show for it.

Eadweard Muybridge's The Horse in Motion (1878) — movement measured frame by frame against a grid
Eadweard Muybridge's The Horse in Motion (1878) — movement measured frame by frame against a grid
SEO On-Site

The score follows the movement, not the other way around

Chasing a PageSpeed number directly produces hacks. Training the critical path produces the number. This article is the training log of a real site going from 69 to 97 performance — every exercise, every measurement.

  • Prerendered HTML as the starting position
  • The render-blocking CSS diet: 162 KB to 38 KB
  • Icon font subsetting: 19 icons, not 512 KB
  • AVIF hero images and fetchpriority
  • Content-hashed bundles with immutable caching
Dan Stativa

Want your site put through the same workout?

Abstract: On-site SEO in 2026 is mostly a performance discipline, and performance is mostly a critical-path discipline. This article is a training log, not a theory piece: the site you are reading went from a 69 to a 97 performance score, from 1.4 s to 0.6 s first paint, from a 5-second to a 1.2-second LCP — with no redesign. The program: prerender everything you can, put the render-blocking CSS on a diet, serve images at the size they are displayed, and let the browser cache like it means it. The score was never the target. It was the side effect.

Nobody gets strong by staring at the scoreboard. A PageSpeed score is a measurement of movements your site performs every time a browser walks in: how fast it paints, how much it ships, how honestly it declares what is coming. You do not train the number. You train the movement — and the number follows.

1. The Scoreboard Is Not the Workout

PageSpeed Insights hands you four numbers that matter: First Contentful Paint, Largest Contentful Paint, Cumulative Layout Shift, Total Blocking Time. It is tempting to treat them as the goal. They are diagnostics — the gym mirror, not the muscle.

This matters because chasing the score directly produces hacks: inlining everything, lazy-loading the hero, stripping features on the audit’s user agent. Chasing the movement — what the browser must do before it can paint — produces durable speed that happens to score well.

The starting position matters more than any single exercise. A prerendered site — plain HTML files built ahead of time and served from a CDN — begins every request already ahead: no server think-time, no hydration cliff, no JavaScript standing between the visitor and the first byte of content. This site is prerendered by Astro, and its baseline audit still said 69.

A prerendered site with a 69 is not a rendering problem. It is a payload problem.

2. Compound Lifts: the Critical Path

The critical path is the compound lift of web performance: everything the browser must download, parse, and apply before it may paint a single pixel. Here, that was one CSS bundle — 162 KB gzipped — plus a render-blocking request chain to Google Fonts.

The audit found where the weight was hiding. Font Awesome Pro: 512 KB of CSS (100 KB gzipped) and roughly 850 KB of font binaries. The whole site uses nineteen icons.

That ratio — nineteen icons, half a megabyte of CSS — is worth sitting with. It is the default state of most sites: frameworks and icon packs shipped whole, consumed at one percent.

The exercises, in order of weight moved:

ExerciseBeforeAfterHow
Icon subset512 KB CSS + ~850 KB fonts1.6 KB CSS + 5 KB fontsScan source for used classes, subset the woff2 to those 19 glyphs
Self-hosted webfontsrender-blocking third-party chain (~490 ms)same-origin, zero external requestsVendor the Google Fonts CSS + woff2 files
Framework purgeBootstrap 31 KB gz~8 KB gzPurgeCSS against the actual templates, safelist for runtime classes
Animation subsetevery animate.css keyframethe 3 the site usesExtract only what the markup references

Result: the render-blocking path is now a single same-origin stylesheet, 37.8 KB gzipped. First paint moved from 1.4 s to 0.6 s on desktop, and the improvement is structural — there is simply less standing between the request and the pixel.

The trap: bundling and minification feel like the workout. They are the warm-up. Minifying 512 KB of icon CSS you don’t use produces 500 KB of minified CSS you don’t use. Subtract first, compress second.

3. Accessories: Images

LCP has a simpler personality than its reputation suggests: it is almost always one image, and that image is almost always too big.

Here it was the hero portrait — a 2.3 MB PNG, shipped at 1024×1536, displayed at 282×422. The browser downloaded eleven times more pixels than it painted. LCP: 5 seconds.

The fix is mechanical once you see it that way:

serve the display size  ->  srcset 400/640/960 + sizes
serve the modern format ->  <picture> AVIF first, WebP fallback
declare the priority    ->  fetchpriority="high" on the LCP image only
reserve the space       ->  width/height attributes (CLS insurance)
defer everything else   ->  loading="lazy" below the fold

The same portrait now arrives as a 37 KB AVIF. A 543 KB screenshot in a blog article became a 58 KB WebP, pixel-identical at its rendered size. LCP: 1.2 seconds. Nothing about the design changed — only the honesty of the delivery.

4. Conditioning: Caching and the Network

The first three exercises speed up the first visit. Conditioning is about every visit after that, and it is where advanced browser networking pays off quietly.

The core move is content-hashed filenames plus immutable caching. Each bundle’s name contains a digest of its own bytes — site.7e2d1a25.min.css — so the URL changes whenever the content does. That makes a one-year Cache-Control: immutable header safe: a stale file can never be served, because an update is, by definition, a different URL. Repeat visitors re-download exactly nothing.

first visit                     repeat visit
-----------                     ------------
HTML        ── CDN edge         HTML        ── CDN edge (revalidated)
site.css    ── 37.8 KB gz       site.css    ── memory cache, 0 bytes
site-core.js── 119 KB           site-core.js── memory cache, 0 bytes
hero AVIF   ── 37 KB            hero AVIF   ── disk cache, 0 bytes
fonts       ── 5 KB, immutable  fonts       ── 0 bytes

The rest of the conditioning program comes nearly free on a modern host: HTTP/3 and Brotli from the CDN, font-display: swap so text never waits for a font file, and no third-party origin left on the critical path — every preconnect you don’t need is faster than the one you optimized.

Curated Source

Precision caliper — measurement before optimization

Optimize Largest Contentful Paint

The web.dev guidance lands on the same conclusion as any decent training program: there is no single heroic lift. LCP improves when the whole chain improves — document delivery, resource discovery, download size, render order. Program over hack.

"It's rare that a quick fix to a single part of a page will result in a meaningful improvement to LCP."
Read the original guide

5. The Clean-Site Dividend

Here is the part the score does not advertise: the same work fixed things that had nothing to do with speed.

Declaring image dimensions for layout stability also ended the aspect-ratio distortions hiding in the CSS. Subsetting the icon font forced an inventory of what the site actually uses. The accessibility audit went from 90 to 100 on the way past — contrast ratios, labels wired to their inputs, heading order — because a performance pass is, in practice, an honesty pass. You read every request, every rule, every tag, and you delete the lies.

Browsers reward that the same way search engines do, and for the same reason: a site that ships only what it means is easier to parse, easier to cache, easier to trust. “Loved by browsers” is not a metaphor. It is a measurable posture.

6. Closing

The final board, same site, same design: performance 69 → 97, accessibility 90 → 100, best practices 77 → 100. First paint 0.6 s. One render-blocking file where there were dozens.

None of it came from optimizing the score. It came from training the movement — subtract the unused, right-size the images, hash the names, and let the browser do what it is built to do. The scoreboard caught up on its own. It always does.

Dan Stativa

Want your site put through the same workout?