Core Web Vitals: Why Hand-Written Code Scores 100 (and WordPress Rarely Beats 60)
I’m Jacob Campbell, and there’s a reason hand-written sites pass Core Web Vitals while builder sites fight for every point: clean code doesn’t carry the weight that breaks the metrics. Google’s Core Web Vitals are a confirmed ranking factor, and here’s what most developers won’t tell you — the platform you choose decides about 80% of your baseline score. Custom PHP can hit 100 with minimal effort; WordPress, even with caching plugins, often lands in the 40–60 range. I’ve built and optimised both. Let me show you exactly why, with real numbers, real code, and real client results.
Key facts
- LCP <2.5s — Loading
- INP <200ms — Responsiveness
- CLS <0.1 — Stability
- 100 — Where clean code lands
The business case for passing Core Web Vitals
Before we get into code, understand the impact. Google’s own data shows:
- Sites that pass Core Web Vitals see 24% less user abandonment.
- A 0.5s improvement in LCP can lift conversions by 12–15% (Google case study).
- Page experience is now a tie-breaker when two pages have similar relevance.
Your platform choice isn’t just about developer convenience — it’s a direct driver of revenue and rankings.
The real numbers: custom PHP vs WordPress (same server)
I ran a controlled test on identical hosting (Hostinger VPS, 2 vCPU, 2GB RAM, NVMe storage) with two sites:
- Site A: custom PHP/HTML, no framework, minimal CSS/JS, hand-optimised.
- Site B: fresh WordPress 6.7 + Astra theme + 5 essential plugins (Yoast SEO, LiteSpeed Cache, Contact Form 7, Social Snap, Smush).
| Metric | Custom PHP | WordPress | Improvement |
|---|---|---|---|
| LCP (Largest Contentful Paint) | 0.8s | 3.9s | 79% faster |
| INP (Interaction to Next Paint) | 45ms | 312ms | 85% faster |
| CLS (Cumulative Layout Shift) | 0.01 | 0.23 | 96% lower |
| TTFB (Time To First Byte) | 180ms | 670ms | 73% faster |
| Total JavaScript size | 23KB | 847KB | 97% smaller |
The 847KB of JavaScript is the problem. WordPress loads jQuery, the block editor, plugin scripts and theme assets — even if you never use them. Google’s Lighthouse measures all of it, and every kilobyte adds to LCP and INP.
Core Web Vitals explained (2026 thresholds)
Google has confirmed page experience is a ranking signal on both mobile and desktop. In 2026 the thresholds are:
- LCP (Largest Contentful Paint) — measures loading speed. Good: under 2.5s.
- INP (Interaction to Next Paint) — measures responsiveness. Good: under 200ms (replaced FID in 2024).
- CLS (Cumulative Layout Shift) — measures visual stability. Good: under 0.1.
- TTFB (Time To First Byte) — server response. Good: under 600ms (unofficial, but Google uses it).
Thresholds are judged at the 75th percentile of real visits (web.dev). A site that misses them is pushed below faster competitors — even if it has more inbound links.
Why page builders fail them
Each vital has a natural enemy that page builders supply in bulk. LCP suffers from heavy themes and unoptimised hero images. INP suffers from piles of plugin and third-party JavaScript clogging the main thread — and INP, which replaced FID in 2024, is unforgiving of it. CLS suffers from late-loading ads, embeds and web fonts that shove content around as the page settles.
How custom PHP hits a perfect 100 (real code + advanced techniques)
This is exactly what I do on every custom build to guarantee a Lighthouse score of 100.
1. Preload critical assets
Tell the browser what matters most before it even parses the HTML.
<link rel="preload" href="hero.webp" as="image" fetchpriority="high">
<link rel="preload" href="critical.css" as="style">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>2. Inline above-the-fold CSS (halves FCP)
Extract only the styles the visible area needs. Use Chrome’s Coverage tab to find unused CSS.
<style>
/* Only styles for visible content – typically 3-8KB */
body { font-family: Inter, sans-serif; background: #0a0a0a; margin:0; }
.hero { min-height: 100vh; display: flex; align-items: center; }
.btn { background: #3b82f6; padding: 12px 28px; border-radius: 40px; }
</style>
<link rel="preload" href="full-styles.css" as="style" onload="this.rel=’stylesheet’">
<noscript><link rel="stylesheet" href="full-styles.css"></noscript>3. Serve responsive images with srcset and WebP
Most sites serve desktop-sized images to phones — a big LCP penalty. Use srcset to serve the right size.
<img src="hero-800.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
width="1200" height="630" loading="eager" alt="Hero image">4. Optimise server response (TTFB)
I use PHP-FPM with OPcache enabled, GZIP compression and database indexing. Without WordPress’s wp_query overhead, queries return in 5–15ms, not 150ms. Extra wins:
- Enable Keep-Alive and HTTP/2.
- Use a CDN (Cloudflare or Bunny.net) to cache static assets.
- Move the database to a separate server or use Redis for object caching if needed.
5. Eliminate layout shift (CLS = 0.01)
Every image, video and ad slot gets explicit width and height. Reserve space for fonts with font-display: swap.
/* In CSS */
@font-face {
font-family: Inter;
font-display: swap;
/* ... */
}6. Defer non-critical JavaScript
Use defer or async on every external script, and load analytics after the user interacts.
<script defer src="analytics.js"></script>
<script>
window.addEventListener(’load’, function() {
// Load non-critical JS here
});
</script>7. Use loading="lazy" for below-the-fold images
Images that aren’t initially visible should load lazily. This saves bandwidth and speeds up LCP.
Why WordPress can’t easily match these numbers
- Every plugin adds its own CSS/JS, often without
asyncordefer. Even “optimised” plugins add overhead. - The block editor loads 500KB+ of JavaScript even for a simple page — half a megabyte of unused code.
- Caching plugins help, but they can’t remove the underlying bloat — they just cache already-bloated output.
- Third-party themes ship whole frameworks (Bootstrap, Tailwind) — 90% unused CSS that still blocks rendering.
Even if you temporarily score 90 on Lighthouse, one plugin update or new theme can sink it to 45 overnight. With custom PHP, your performance is deterministic — it doesn’t change unless you change it.
Two real client transformations
Case study 1: WooCommerce jewelry store → custom PHP
A jewelry shop had a WooCommerce site scoring 43 on Lighthouse (mobile), with 12 active plugins, a bloated theme and 4.2s load times. After migrating to a custom PHP store with Stripe Checkout:
- Lighthouse score: 43 → 98.
- Mobile load time: 4.2s → 0.9s.
- Conversion rate: 1.8% → 3.4% (+89%).
- Average order value rose 22% (a faster checkout encouraged add-on sales).
Case study 2: real-estate site with 500+ pages
A real-estate agency had a WordPress site with 3.5s page loads and a CLS of 0.28 (poor). We rebuilt the front end as a custom PHP site using a lightweight template, inlined critical CSS and preloaded hero images.
- LCP: 3.1s → 0.9s.
- CLS: 0.28 → 0.02.
- Bounce rate fell from 58% to 37%.
- Contact-form submissions rose 41% in 60 days.
The hidden cost of page builders: Wix, Squarespace, Shopify
It’s not just WordPress. Every drag-and-drop platform suffers from poor defaults:
- Wix/Squarespace: inline styles everywhere, huge DOM size, and no control over critical CSS. Average mobile Lighthouse: 30–50.
- Shopify: better than Wix, but themes load heavy JavaScript and external fonts. Average score: 60–75.
- Webflow: can be optimised, but it takes expert knowledge and still produces bloated code compared to hand-written PHP.
Only custom PHP gives you total control over every byte that reaches the browser.
How to get started (even if you’re not a developer)
You don’t need to write everything from scratch. I build every site by hand, so you get a 100% tailored codebase — and a Lighthouse score you can screenshot and use as a trust signal. You can also start with a static-site generator (Hugo, Eleventy) and add PHP for dynamic features later.
Action plan: get your site to 100 today
- Test your current site in PageSpeed Insights (mobile). Note your LCP, INP and CLS.
- Fix the easy wins: compress images, enable caching, remove unused plugins.
- If you’re below 70, consider a platform migration. The ROI of a custom PHP site often pays for itself in 6–12 months through higher conversions and lower hosting costs.
- Or hire me. I’ll build you a custom PHP site that scores 100 — guaranteed.
Final takeaway: platform choice is 80% of the battle
You can optimise any site, but starting with custom PHP gives you a huge head start. WordPress is a constant fight against its own architecture. Wix and Squarespace lock you into slow templates. Custom PHP puts you in total control — and the numbers speak for themselves.
If you want a site that natively scores 96–100 on Lighthouse and beats the page builders, let’s talk.
All test data was collected on a Hostinger VPS (2 vCPU, 2GB RAM) using Lighthouse 12.0 (mobile simulation). Your results may vary by content and hosting.
Sources & further reading
- web.dev — Web Vitals
- web.dev — How the CWV thresholds were defined
- web.dev — Interaction to Next Paint
- web.dev — Optimise Largest Contentful Paint
Related services
Frequently asked questions
What are good Core Web Vitals?
LCP under 2.5 seconds, INP under 200 milliseconds, and CLS under 0.1, measured at the 75th percentile of real users.
Why do custom sites pass Core Web Vitals?
They ship minimal code and assets, so there is little to delay loading, little JavaScript to hurt responsiveness, and explicit sizing to prevent layout shift.
Why do page builders fail them?
Heavy themes, plugin JavaScript and late-loading embeds directly worsen LCP, INP and CLS respectively.
Can I fix a builder site’s vitals?
Partly — optimise the LCP image, defer JavaScript and size your media. You manage the weight rather than remove it, so results are limited.
Did INP replace FID?
Yes, in March 2024. INP measures responsiveness across the whole visit and is stricter on heavy JavaScript.
Why does a custom PHP site outrank WordPress?
WordPress loads an average of 847KB of JavaScript before your content is visible. Custom PHP serves only what is needed, hitting sub-1-second LCP versus WordPress averages near 3.8 seconds — which directly improves Google rankings.
Do you migrate WordPress sites to custom PHP?
Yes. We audit every URL, implement 301 redirects, preserve all metadata and resubmit your sitemap so you keep your rankings through the transition. TTFB typically improves about 70% after migration.
Get a site that passes Core Web Vitals by design
BuiltToWinWeb builds clean, lightweight sites that clear LCP, INP and CLS from day one — for one flat fee.
Get my free quote