// Performance
How to Improve Your Google PageSpeed Score: A Practical Guide
Step-by-step guide to improving your PageSpeed Insights score. Covers Core Web Vitals, image optimization, render-blocking resources, caching, and server response time — with actionable fixes for each.
What PageSpeed Insights actually measures
Google PageSpeed Insights (PSI) is one of the most misunderstood tools in web development. Developers often chase the score itself — trying to hit 100 — when the score is really a proxy for something more fundamental: how fast your page feels to a real user on a real device on a real connection.
PSI measures five Core Web Vitals metrics: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), Cumulative Layout Shift (CLS), First Contentful Paint (FCP), and Time to First Byte (TTFB). Each metric maps to a specific user experience: LCP is how quickly the main content appears, INP is how fast the page responds to interaction, and CLS is how much the layout jumps while loading.
The score runs from 0 to 100, with 90+ considered good, 50–89 needs improvement, and below 50 poor. The mobile score is almost always lower than desktop because PSI simulates a mid-tier Android device on a 4G connection — conditions that match how most of the world actually browses the web. Fix for mobile first and desktop improvements will follow.
Images: the fastest wins
Images cause more PageSpeed problems than any other single factor. An unoptimized hero image can single-handedly move your LCP from 1.2 seconds to 6+ seconds. The fixes here are mechanical and produce immediate, measurable results.
Start by converting all images to WebP or AVIF. WebP typically reduces file size 25–35% compared to JPEG at equivalent quality; AVIF can cut another 20–30% on top of that. Most modern image editors, CDNs, and WordPress plugins handle this conversion automatically. Next, ensure every image has explicit width and height attributes set in the HTML — this prevents layout shift (CLS) as images load.
Implement lazy loading for every image below the fold using the native loading='lazy' attribute. This defers image downloads until the user is about to scroll to them, dramatically reducing initial page weight. However, never lazy-load your hero image or any image visible above the fold — those should load as early as possible, ideally with a preload hint in the document head.
- Convert to WebP/AVIF — use Squoosh, ImageMagick, or your CDN's auto-format feature
- Set explicit width and height on every img element to prevent CLS
- Add loading='lazy' to below-fold images; add fetchpriority='high' to the LCP image
- Size images to their rendered container — don't serve a 2400px image in a 400px slot
- Use a responsive srcset so browsers download the appropriate resolution
Eliminate render-blocking resources
Render-blocking resources are CSS and JavaScript files that the browser must download and parse before it can display anything on screen. Every render-blocking resource adds to your FCP and LCP. Most sites have several, and most of them can be made non-blocking with minor changes.
For CSS, the goal is to inline the styles needed to render above-the-fold content (critical CSS) directly in the HTML head, and load everything else asynchronously. Tools like Critical or Penthouse extract critical CSS automatically. For most sites, the critical CSS is under 14KB — small enough to inline without a separate network round-trip.
For JavaScript, add defer or async attributes to every script tag that isn't needed for initial rendering. The defer attribute maintains execution order while moving execution until after the HTML is parsed; async loads and executes immediately, suitable for independent scripts like analytics. Move script tags to the bottom of the body if you can't add defer or async.
- Add defer to all non-critical script tags
- Inline critical above-the-fold CSS in the head; load the rest asynchronously
- Audit third-party scripts — Google Tag Manager, chat widgets, and A/B testing tools are common offenders
- Use Chrome DevTools Coverage tab to find unused CSS and JavaScript
Server response time and TTFB
Time to First Byte (TTFB) is how long the browser waits before receiving the first byte of the HTML response. Google considers under 800ms good. If your TTFB is consistently above 1.5 seconds, no amount of frontend optimization will get you to a good LCP — the browser can't start rendering until the HTML arrives.
The main causes of slow TTFB are slow hosting, unoptimized database queries, and lack of caching. For shared hosting, upgrading to a VPS or managed hosting with better CPU allocation often halves TTFB immediately. For dynamic sites (WordPress, e-commerce), page caching — where the server sends a pre-built HTML file instead of generating it on every request — is the single highest-leverage fix available.
CDN usage dramatically improves TTFB for international audiences by serving responses from servers geographically close to the visitor. Cloudflare's free tier is sufficient for most small businesses and reduces TTFB by 50–80% for visitors far from your origin server.
- Enable page caching (WP Super Cache, Redis, Varnish, or platform-level caching)
- Use a CDN — Cloudflare free tier is sufficient for most sites
- Audit slow database queries with your hosting panel's query log
- Check your server's PHP version — PHP 8.x is 2–3x faster than PHP 7.2
Caching and compression
HTTP caching tells browsers to store your static assets (images, CSS, JavaScript, fonts) locally so repeat visitors don't re-download them. Without caching headers, every page load transfers the full asset set. With proper caching, repeat visitors load your site in milliseconds from their local cache.
Set Cache-Control headers with long max-age values for fingerprinted assets (files where the filename changes with the content). A max-age of one year is appropriate for these. For HTML and non-versioned assets, use shorter durations or no-cache to ensure visitors get fresh content.
Enable text compression on your server. Brotli is the modern standard and typically achieves 15–25% better compression than gzip on JavaScript and CSS files. Most modern servers and CDNs support Brotli. Check whether yours is sending the correct Content-Encoding header using your browser's Network panel.
Tracking progress and avoiding regressions
PageSpeed scores fluctuate with network conditions, server load, and the randomness inherent in lab testing. Measure trends over time, not individual test results. Run PSI three times and average the scores, or use the CrUX (Chrome User Experience Report) data shown in the PSI report — this reflects real users over 28 days and is more reliable than any single lab test.
Set up continuous performance monitoring so regressions get caught before they reach production. WebEnture's Performance Agent and Page Speed Agent can be scheduled to run weekly, alerting you when scores drop below your threshold. This is especially important after CMS updates, theme changes, or new third-party integrations — all common sources of performance regression.
Use WebEnture's Image Optimization Agent to identify oversized or unoptimized images across your entire site, not just the homepage. Product pages, blog posts, and gallery pages are where image problems usually accumulate unnoticed, and they contribute to your CrUX scores just as much as the pages you think to test manually.