Mudassar Ali
← Blog

How I Take WordPress Sites from PageSpeed 60 to 90+

· 3 min read

Over the years I've moved a lot of WordPress sites from a mobile PageSpeed score of 60–70 into the 90s. The fixes are rarely magic. They're the same handful of problems, fixed in the right order.

Here's the order I work in.

1. Measure first, on mobile

Run the page through PageSpeed Insights and note three numbers:

  • LCP (Largest Contentful Paint): target under 2.5s
  • INP (Interaction to Next Paint): target under 200ms
  • CLS (Cumulative Layout Shift): target under 0.1

Also check the field data section at the top. That's what Google actually uses for ranking. The lab score is only a diagnostic tool.

2. Fix the hero image (usually the LCP)

On most sites the LCP element is the hero image or slider. Common fixes:

  • Serve it as WebP or AVIF at the size it's actually displayed.
  • Don't lazy-load it. WordPress adds loading="lazy" to many images, and lazy-loading the hero delays LCP.
  • Give it fetchpriority="high" so the browser fetches it first.
  • Replace hero sliders with a single image. The first slide is all most visitors see anyway.
add_filter( 'wp_get_attachment_image_attributes', function ( $attr, $attachment ) {
    if ( is_front_page() && (int) $attachment->ID === (int) get_theme_mod( 'hero_image_id' ) ) {
        $attr['loading']       = 'eager';
        $attr['fetchpriority'] = 'high';
    }
    return $attr;
}, 10, 2 );

3. Always set image dimensions

Missing width and height attributes are the number one cause of CLS I see. Every <img> (and every embed or ad slot) needs a reserved space before it loads.

4. Fonts

  • Self-host fonts instead of loading them from Google Fonts on every request.
  • Use WOFF2 and load only the weights you use. Most sites load 6–8 weights and use 2.
  • Add font-display: swap and preload the one font used above the fold.

5. Scripts: remove, defer, delay

This is where the biggest INP wins come from.

  1. Remove what isn't used. Page builders and plugins often load their JS site-wide.
  2. Defer what's needed but not urgent.
  3. Delay third-party scripts (chat widgets, heatmaps, some pixels) until the user interacts.

To stop a plugin's assets loading on pages that don't use them:

add_action( 'wp_enqueue_scripts', function () {
    if ( ! is_page( 'contact' ) ) {
        wp_dequeue_script( 'contact-form-7' );
        wp_dequeue_style( 'contact-form-7' );
    }
}, 100 );

For analytics, load everything through Google Tag Manager and trigger non-essential tags after the page loads, not on page view.

6. Critical CSS and unused CSS

Theme and page-builder CSS is often 300KB+, and most of it is unused on any given page. Inline the critical above-the-fold CSS and load the rest asynchronously. Tools like WP Rocket or Perfmatters handle this well. A lean custom theme avoids the problem in the first place.

7. Caching and hosting

  • Page caching (server-level if your host offers it, otherwise a caching plugin).
  • Object caching with Redis for WooCommerce and membership sites.
  • A CDN for static assets.
  • PHP 8.2+.

No amount of front-end tuning fixes a server that takes two seconds to respond. Check TTFB in PageSpeed Insights. It should be under 800ms.

8. Audit your plugins

I regularly find sites running three SEO, analytics or slider plugins that overlap. Deactivate one at a time and measure. Every plugin you remove is code that no longer runs on every request.

The order matters

If you only have an afternoon: fix the hero image, set image dimensions, and remove unused scripts. Those three changes alone usually add 15–25 points on mobile.

Want me to audit your site? Send me the URL.