DEV Community

Siraj A.
Siraj A.

Posted on • Originally published at peakspire.ca

How I Got a WordPress Site from PageSpeed 54 to 100 (Step by Step)

A client came to me with a WordPress site scoring 54 on Google PageSpeed Insights (mobile). Load time was 8 seconds. Core Web Vitals were all failing.

Seven days later, the same site scored 100/100 on Performance, Accessibility, Best Practices, and SEO. Load time dropped to under 2 seconds.

Here is exactly how I did it, step by step.

The Starting Point

  • PageSpeed Insights mobile score: 54/100
  • Largest Contentful Paint (LCP): 6.2s
  • Total Blocking Time (TBT): 1,800ms
  • Cumulative Layout Shift (CLS): 0.32
  • Load time: 8+ seconds on a mobile connection

The site was a standard WordPress build with Elementor, 12 plugins, unoptimized images, and render-blocking CSS/JS everywhere.

Step 0: Understand the Scoring System

Before touching any code, I read the Lighthouse 10 scoring documentation. This matters because the five metrics are weighted differently:

Metric Weight
Total Blocking Time (TBT) 30%
Largest Contentful Paint (LCP) 25%
Cumulative Layout Shift (CLS) 25%
First Contentful Paint (FCP) 10%
Speed Index (SI) 10%

TBT alone is 30% of the score. That told me where to focus first.

Phase 1: Kill the JavaScript (TBT: 1,800ms to 0ms)

The biggest win. I audited every enqueued script:

function peakspire_dequeue_scripts() {
    wp_deregister_script('jquery-migrate');
    wp_dequeue_script('elementor-waypoints');
    wp_dequeue_script('elementor-frontend');
    remove_action('wp_head', 'print_emoji_detection_script', 7);
}
add_action('wp_enqueue_scripts', 'peakspire_dequeue_scripts', 100);
Enter fullscreen mode Exit fullscreen mode

Result: TBT dropped from 1,800ms to 0ms. That alone jumped the score from 54 to ~75.

Phase 2: Fix the Fonts (LCP: 6.2s to 2.8s)

The site loaded three Google Font families (6 weights = ~75KB). On mobile 4G, these competed with main content for bandwidth.

The fix: load fonts only on desktop:

@media (min-width: 769px) {
    @font-face {
        font-family: 'Inter';
        src: url('/fonts/inter-v12-latin-regular.woff2') format('woff2');
        font-display: swap;
    }
}
body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
Enter fullscreen mode Exit fullscreen mode

Mobile uses system font stack. Zero font downloads. LCP improved dramatically.

Phase 3: Image Optimization (LCP: 2.8s to 1.8s)

  1. Convert to WebP: 60-70% smaller files
  2. Lazy load below the fold
  3. Explicit width/height on every <img> (prevents CLS)
  4. Preload the hero (LCP element):
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" type="image/webp">
Enter fullscreen mode Exit fullscreen mode

Phase 4: CSS Delivery (FCP: 3.1s to 0.8s)

Inline critical CSS, async-load the rest:

<style>
  :root { --text: #1a1a2e; --bg: #ffffff; }
  body { margin: 0; font-family: system-ui, sans-serif; color: var(--text); }
  .hero { min-height: 60vh; display: flex; align-items: center; }
</style>
<link rel="preload" href="/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
Enter fullscreen mode Exit fullscreen mode

FCP dropped from 3.1s to 0.8s.

The Result

Metric Before After
Performance 54 100
Accessibility 82 100
Best Practices 78 100
SEO 89 100
LCP 6.2s 1.2s
TBT 1,800ms 0ms
CLS 0.32 0

The Non-Obvious Lesson

After obvious fixes, the score stuck at 95-97. The breakthrough was the font strategy. Fonts only on desktop. Mobile saves 75KB on slow connections. That was the difference between 97 and 100.

I run PeakSpire in Ottawa, Canada. WordPress speed optimization for service businesses. Free speed audit: drop your URL in the comments.

Top comments (0)