Most WordPress speed guides hand you a list of plugins to install and call it a day. That’s not a strategy β it’s plugin bloat with extra steps.
I’ve hit 90+ PageSpeed scores on 100+ WordPress projects β from WooCommerce stores to agency sites to content-heavy blogs. In this guide I’ll show you the exact steps in priority order, with real code, not vague advice.
One thing most guides get wrong in 2026: Google replaced FID with INP (Interaction to Next Paint) as a Core Web Vital. If your guide still mentions FID, it’s outdated. This one covers INP properly.
Why PageSpeed Score Matters More Than Ever in 2026
Google uses Core Web Vitals as a direct ranking factor. A slow WordPress site doesn’t just frustrate visitors β it actively pushes you down in search results.
- Only 44% of WordPress sites pass all three Core Web Vitals on mobile
- A 1-second delay in page load reduces conversions by up to 7%
- Mobile users abandon pages that take longer than 3 seconds to load
- Improving from 50 β 90+ PageSpeed score can directly increase organic traffic
The good news: most WordPress sites are slow for 2β3 fixable reasons. Fix those and the score jumps fast.
Core Web Vitals Targets for 2026 (What You Need to Hit)
Before touching any settings, know your targets. PageSpeed Insights measures three signals Google actually uses for ranking:
- LCP (Largest Contentful Paint): Under 2.5 seconds β time until your hero image or main heading is visible
- INP (Interaction to Next Paint): Under 200ms β how fast the page responds to clicks, taps, and typing (replaced FID in 2024)
- CLS (Cumulative Layout Shift): Under 0.1 β elements must not jump around as the page loads
Important: PageSpeed Insights shows Lab data (simulated) and Field data (real Chrome users). Google’s ranking signal uses field data. A 95 lab score with poor field data still hurts SEO. Always check both.
Step 1: Fix Your Server First β TTFB Under 200ms
This is the step most developers skip. If your server takes over 600ms to respond (Time to First Byte), no amount of caching or optimisation will get you to 90+. Fix hosting before anything else.
What Your Hosting Needs for 90+ PageSpeed
- PHP 8.2 or higher (PHP 7.x is up to 3Γ slower)
- OPcache enabled with proper memory configuration
- Redis or Memcached for object caching
- HTTP/2 minimum β HTTP/3/QUIC is better (Cloudflare enables this free)
- NVMe SSD storage
Configure OPcache Properly
Most hosts enable OPcache with default settings that are too conservative. Add this to your php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.save_comments=1
opcache.fast_shutdown=1
Enable Redis Object Caching
WordPress makes database queries on every page load. Redis caches those results in memory. Add this to wp-config.php:
define('WP_CACHE_KEY_SALT', 'yourdomain_');
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_DATABASE', 0);
Then install the Redis Object Cache plugin and enable it. Most sites see TTFB drop by 150β400ms immediately.
Step 2: Fix LCP β Preload Your Hero Image
Your LCP element is almost always your hero image or H1 heading. This single fix alone typically improves PageSpeed score by 10β20 points β and takes under 10 minutes.
Add fetchpriority=”high” to Your LCP Image
Never lazy-load your LCP image. Add these two attributes:
<img
src="hero.webp"
alt="Hero image"
width="1200"
height="600"
fetchpriority="high"
decoding="async"
/>
Preload It in <head> via functions.php
add_action('wp_head', function () {
if (is_front_page()) {
echo '<link rel="preload" as="image" href="'
. get_template_directory_uri()
. '/img/hero.webp" fetchpriority="high" />';
}
}, 1);
Result: Google can start loading your LCP image before the rest of the HTML has finished parsing. This is the single highest-impact LCP fix available.
Step 3: Fix INP β The Core Web Vital Most Guides Ignore
INP (Interaction to Next Paint) replaced FID as a Core Web Vital in March 2024. It measures how fast your page responds to every user interaction β clicks, taps, form inputs β not just the first one.
The Biggest INP Killers on WordPress
- WooCommerce cart fragments running AJAX on every page load
- Undeferred third-party scripts β chat widgets, Facebook Pixel, Google Tag Manager
- Large JavaScript bundles blocking the main thread
- Too many event listeners on scroll/resize
Delay Third-Party Scripts Until First Interaction
This is the single most effective INP fix. Load analytics, pixels, and chat widgets only after the user interacts with the page:
<script>
(function () {
var loaded = false;
function loadThirdParty() {
if (loaded) return;
loaded = true;
// Google Analytics
var ga = document.createElement('script');
ga.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX';
ga.async = true;
document.head.appendChild(ga);
// Add Facebook Pixel or other scripts here
}
['scroll','click','keydown','touchstart'].forEach(function(evt) {
document.addEventListener(evt, loadThirdParty, { once: true, passive: true });
});
})();
</script>
Defer All Non-Critical JavaScript
// functions.php β defer all scripts except core dependencies
add_filter('script_loader_tag', function ($tag, $handle) {
$skip = ['jquery-core', 'jquery-migrate'];
if (in_array($handle, $skip)) return $tag;
return str_replace(' src=', ' defer src=', $tag);
}, 10, 2);
Step 4: Image Optimisation β 45β65% of Your Page Weight
Images are the single biggest file size category on most WordPress sites. Getting this right cuts load time faster than almost anything else.
Which Format to Use
- WebP: Default for all photos β 25β35% smaller than JPEG at same quality
- AVIF: ~50% smaller than JPEG β use for hero images if your build allows it
- SVG: Logos and icons β always vector where possible
- PNG: Only for lossless transparency that SVG cannot handle
Serve Modern Formats with JPEG Fallback
<picture>
<source srcset="hero.avif" type="image/avif" />
<source srcset="hero.webp" type="image/webp" />
<img src="hero.jpg" alt="Hero" width="1200" height="600" loading="lazy" />
</picture>
Always declare width and height on every image β this prevents CLS (layout shift) as the page loads. Missing dimensions is one of the most common CLS causes on WordPress sites.
Step 5: CSS and JavaScript Optimisation
Inline Critical CSS, Load the Rest Async
Critical CSS is the above-the-fold styles inlined in <head> so the page renders before the external stylesheet downloads. Here is the WordPress implementation:
// Inline critical CSS in <head>
add_action('wp_head', function () {
$critical = file_get_contents(get_template_directory() . '/css/critical.css');
echo '<style>' . $critical . '</style>';
}, 1);
// Load main stylesheet asynchronously
add_filter('style_loader_tag', function ($html, $handle) {
if ($handle === 'main-style') {
return str_replace(
"rel='stylesheet'",
"rel='preload' as='style' onload=\"this.onload=null;this.rel='stylesheet'\"",
$html
);
}
return $html;
}, 10, 2);
Remove Unused WordPress Features That Add Script Weight
// functions.php β Remove features you don't use
add_action('init', function () {
remove_action('wp_head', 'wp_print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wp_shortlink_wp_head');
add_filter('show_recent_comments_widget_style', '__return_false');
});
Step 6: Font Optimisation β The Detail Everyone Skips
Most guides say “self-host your Google Fonts.” That’s incomplete. Self-hosting a full unoptimised font can be slower than Google Fonts. The key is font subsetting β stripping out character sets your site doesn’t need.
Subset Your Fonts (48KB β 14KB Per Weight)
A full Google Font file includes Latin, Cyrillic, Greek, Vietnamese, and more. For an English site, you only need Latin. Use pyftsubset to strip the rest:
# Install: pip install fonttools brotli
pyftsubset YourFont-Regular.ttf \
--output-file="YourFont-Regular.woff2" \
--flavor=woff2 \
--layout-features="kern,liga,calt" \
--unicodes="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+FEFF,U+FFFD"
Preload Primary Font + Use font-display: swap
<!-- Preload only your primary font weight in <head> -->
<link rel="preload" href="/fonts/inter-400.woff2" as="font" type="font/woff2" crossorigin />
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-400.woff2') format('woff2');
font-display: swap; /* Prevents invisible text during font load */
font-weight: 400;
font-style: normal;
}
</style>
Step 7: CDN + HTTP/3 β Especially Important for USA/UK Clients
If you’re in India and your clients are in the USA or UK, your server response time will be high without a CDN. A request from New York to a Mumbai server adds 200β300ms of latency before a single byte is sent.
Cloudflare Free + APO
- Cloudflare Free: Automatic HTTP/3 (QUIC) β faster on mobile networks. CDN for static assets. Zero cost.
- Cloudflare APO ($5/month): Caches entire WordPress pages at Cloudflare’s edge. Reduces TTFB from ~400ms to ~40ms for international visitors. Best single upgrade for sites with US/UK traffic.
# .htaccess β Set cache headers for Cloudflare efficiency
<IfModule mod_headers.c>
<FilesMatch "\.(webp|woff2|css|js|svg)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>
Step 8: Automate Cleanup with WP-CLI
These WP-CLI commands run in minutes and are absent from most optimisation guides. They clean years of accumulated database bloat that slows every query.
# Delete all post revisions
wp post delete $(wp post list --post_type='revision' --format=ids) --force
# Delete spam comments
wp comment delete $(wp comment list --status=spam --format=ids) --force
# Delete expired transients
wp transient delete --expired
# Optimize database tables
wp db optimize
# Check which plugins are loading the most scripts
wp eval 'global $wp_scripts; foreach($wp_scripts->queue as $h){ echo $h."\n"; }'
Priority Action Plan β Do This in Order
Unlike other guides, this table is ranked by impact Γ· effort. Do them in order β the first 5 will get most sites to 90+ before you even reach step 6.
| # | Action | Impact | Time |
|---|---|---|---|
| 1 | PHP 8.2 + Redis object cache on quality hosting | π΄ High | 1 hr |
| 2 | Add fetchpriority=”high” to LCP image + preload tag | π΄ High | 10 min |
| 3 | Convert all images to WebP with width + height attributes | π΄ High | 30 min |
| 4 | Enable page caching (WP Rocket / LiteSpeed / Cloudflare APO) | π΄ High | 20 min |
| 5 | Delay third-party scripts until interaction | π‘ Medium | 30 min |
| 6 | Inline critical CSS, load main CSS async | π‘ Medium | 1 hr |
| 7 | Self-host + subset fonts, add font-display: swap | π‘ Medium | 45 min |
| 8 | Add Cloudflare + enable HTTP/3 | π‘ Medium | 30 min |
| 9 | WP-CLI database cleanup + remove unused plugins | π’ Low | 15 min |
Real Result: Before and After
Here’s a typical result from a recent project β a service business site in Delhi that came to me with a PageSpeed score of 38 on mobile:
- Before: PageSpeed 38 mobile / 61 desktop β TTFB 1.4s, LCP 5.8s, CLS 0.28
- After: PageSpeed 94 mobile / 97 desktop β TTFB 180ms, LCP 1.9s, CLS 0.04
- Changes made: Hosting upgrade (Cloudways), Redis enabled, LCP image preloaded, WebP conversion, critical CSS inlined, third-party scripts delayed
- Time taken: 4 hours total
The biggest single gain was the LCP preload β it alone moved the score from 38 to 61. Everything else compounded from there.
Need a WordPress Developer Who Builds Fast Sites by Default?
Every site I build targets 90+ PageSpeed from day one β fast hosting, optimised images, deferred scripts, and proper Core Web Vitals out of the box. Not an afterthought.
- Hire a Freelance WordPress Developer
- WordPress Developer for Hire in India
- WordPress Developer for USA Clients
- Freelance WooCommerce Developer
FAQs β WordPress PageSpeed Optimisation
What is a good PageSpeed score for WordPress?
90+ is the target for both mobile and desktop. Scores above 90 indicate your site passes Google’s performance thresholds and won’t be penalised in rankings. Anything below 50 on mobile is considered poor and will hurt both conversions and SEO.
Do I need paid plugins to reach 90+ PageSpeed?
No. As this guide shows, the highest-impact fixes are code-level changes β OPcache config, fetchpriority on your LCP image, font subsetting, and delaying third-party scripts. WP Rocket or LiteSpeed Cache help, but they’re not required if you implement the steps above manually.
Why does my PageSpeed score differ on mobile vs desktop?
Mobile tests simulate a mid-range Android device on a 4G connection. The CPU throttling is significant β JavaScript that runs fine on a desktop may block the main thread for 400ms on mobile. INP issues almost always show up on mobile first.
What replaced FID in Core Web Vitals?
INP (Interaction to Next Paint) replaced FID in March 2024. Unlike FID which only measured the first interaction, INP measures the responsiveness of all interactions throughout the page session. This means JavaScript-heavy WordPress sites with slow menus, filters, or form inputs now get penalised more accurately.
How long does it take to improve WordPress PageSpeed?
For most sites, the first 5 steps in the priority table above take 2β3 hours and will get you from a typical score of 40β60 to 80β90+. Getting from 90 to 95+ requires more granular work β font subsetting, critical CSS per template, and eliminating the last few render-blocking resources.
Does hosting really make that much difference?
Yes β it’s often the biggest factor. A shared hosting TTFB of 1.4 seconds cannot be overcome by any plugin or code change. Managed WordPress hosting (Cloudways, Kinsta, Rocket.net) consistently delivers TTFB under 200ms. If your TTFB is over 600ms, fix your hosting before touching anything else.
Rajan Gupta
FullStack Web DeveloperRajan Gupta is a passionate web developer and digital creator who loves sharing insights on WordPress, modern web design, and performance optimization. When not coding, they enjoy exploring the latest tech trends and helping others build stunning, high-performing websites.