Files
seo-intel-docs/docs/03-metrics-reference.md
help4bis 76523db177 Add comprehensive metrics and engines documentation
Complete the documentation suite with:
- Deep-dive metrics reference (LCP, FCP, CLS, TBT, TTFB)
- Detailed testing engines comparison (Sitespeed vs PSI)
- Why TBT is the killer metric for rds.ink
- How to fix each metric using Hummingbird
- Score differences and when to use each engine

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 05:58:12 +10:00

11 KiB
Raw Permalink Blame History

Performance Metrics Reference

Deep-dive reference for each Core Web Vital metric captured by the seo-intel system.

The Five Metrics

Metric Full Name Unit Good Poor What Matters
LCP Largest Contentful Paint milliseconds ≤2,500ms ≥4,000ms When main content appears
FCP First Contentful Paint milliseconds ≤1,800ms ≥3,000ms When ANY content appears
CLS Cumulative Layout Shift unitless (0-1) ≤0.1 ≥0.25 How much page jumps
TBT Total Blocking Time milliseconds ≤200ms ≥600ms JS blocking interactions
TTFB Time to First Byte milliseconds ≤800ms ≥1,800ms Server response speed

1. LCP — Largest Contentful Paint

Definition

The time when the largest visible element (image, heading, paragraph block, video) appears on screen.

Why It Matters

Users need to see that the page is loading. LCP is the best metric for "when does the user perceive the page is starting to load?"

Thresholds

  • ≤ 2.5 seconds: Good — user feels the page is responding
  • 2.5 4.0 seconds: Needs improvement
  • ≥ 4.0 seconds: Poor — user thinks the page is slow/broken

What Affects LCP

  1. Server response time (TTFB) — If the server is slow, everything downstream is slow
  2. Large images/videos above the fold — Unoptimized media delays LCP
  3. Render-blocking JavaScript<script> in <head> delays rendering
  4. Render-blocking CSS — Large CSS files in <head> delay rendering
  5. Font loading — Web fonts block text rendering (can use font-display: swap)

How to Fix

  1. Optimise TTFB (server response)
    • Cache dynamic pages
    • Optimise database queries
    • Use a CDN for static content
  2. Lazy-load below-the-fold images
    • Use loading="lazy" on <img> tags
    • Hummingbird has automatic image lazy-loading
  3. Defer non-critical JavaScript
    • Add defer attribute to scripts that aren't needed for initial render
    • Move analytics/tracking to the bottom
  4. Critical CSS inlining (advanced)
    • Inline the CSS needed for above-the-fold content
    • Defer the rest with <link rel="preload">

2. FCP — First Contentful Paint

Definition

The time when the browser paints the first piece of non-whitespace content to the screen. This could be:

  • Text
  • An image
  • An SVG
  • A coloured background
  • Anything that's not white

Why It Matters

FCP is the user's first visual cue that the page is loading. It happens before LCP.

Timeline Relationship

0ms: User clicks link
|
50ms: Server starts responding
|
144ms (TTFB): Browser receives first bytes
|
2,116ms (FCP): Browser paints first content (this page)
|
2,500ms (LCP): Browser paints largest content
|
4,000ms: Page is fully interactive

Thresholds

  • ≤ 1.8 seconds: Good
  • 1.8 3.0 seconds: Needs improvement (this page is at 2.1s)
  • ≥ 3.0 seconds: Poor

What Affects FCP

  1. TTFB — Server has to respond first
  2. HTML parsing — Browser must parse HTML to find content
  3. Render-blocking resources — CSS/JS in <head> delay rendering
  4. Font loading — If fonts are slow, text doesn't paint until fonts arrive

How to Fix

Same as LCP:

  1. Optimise TTFB
  2. Defer render-blocking resources
  3. Lazy-load heavy assets

3. CLS — Cumulative Layout Shift

Definition

Measure of unwanted layout changes after the page is visually complete.

Example: You're reading an article, about to click a button, and an ad loads above the button, pushing the button down. You accidentally click the ad instead. That's layout shift.

Why It Matters

CLS directly impacts user experience frustration. Unexpected layout changes are one of the most annoying things on the web.

Measurement

CLS = sum of all individual layout shifts

Each shift is: (fraction of viewport moved) × (distance moved)

Example:
  - Ad loads, pushes button down by 50px
  - Viewport is 800px tall
  - Shift score = (0.5 × 800) / 800 = 0.5
  
If this happens once, CLS = 0.5
If it happens three times (each 0.5), CLS = 1.5

Shifts that happen > 500ms after user input are excluded (they don't surprise the user).

Thresholds

  • ≤ 0.1: Good — page is stable
  • 0.1 0.25: Needs improvement — some shifts happening
  • ≥ 0.25: Poor — page is jumpy

rds.ink Status: 0.0 = PERFECT ✓

This page does NOT shift after load. The images load lazily, product cards maintain their size, nothing pops up. Great job.

What Causes CLS

  1. Unset image/video dimensions — Browser doesn't know how much space to reserve
  2. Ads/widgets loading after page render — Third-party content shifts layout
  3. Custom fonts — Text changes size when font finishes loading
  4. Embeds/iframes — External content pushes layout
  5. Animations that move elements — Animation changing top / left / margin

How to Fix

  1. Set dimensions on images
    <img src="..." width="800" height="600" />
    <!-- or in CSS -->
    img { aspect-ratio: 800 / 600; }
    
  2. Reserve space for ads/lazy content
    <div style="width: 300px; height: 250px;">
      <!-- ad will load here -->
    </div>
    
  3. Use font-display: swap
    @font-face {
      font-family: 'Custom';
      src: url(...);
      font-display: swap;  /* show fallback first, swap when custom loads */
    }
    
  4. Animations: use transform instead of top/left
    /* GOOD: transform doesn't trigger layout recalc */
    @keyframes slide {
      from { transform: translateX(0); }
      to { transform: translateX(100px); }
    }
    
    /* BAD: left does trigger layout recalc */
    @keyframes slide {
      from { left: 0; }
      to { left: 100px; }
    }
    

4. TBT — Total Blocking Time 🔴 MOST COMMON PROBLEM

Definition

How long JavaScript is executing on the main thread, blocking all user interactions.

The browser can only do one thing at a time on the main thread:

  • Parse HTML
  • Execute JavaScript
  • Render CSS
  • Handle user input

If JavaScript is running, the browser cannot respond to clicks, scrolls, or keypresses.

Why It Matters

A page with high TBT feels frozen. User clicks a button, nothing happens for 1+ seconds. The page is technically loaded, but unusable.

Measurement

JavaScript task execution timeline:

0ms ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 200ms (long task, blocks for 200ms)
  User clicks button during this
  but browser doesn't respond

200ms (JavaScript done) → Click now registers (if still there)

TBT = sum of all "blocking" time. A task is "blocking" if it takes > 50ms.

For example:

  • 5 JavaScript tasks, each 100ms = TBT of 5 × 50ms = 250ms blocking
  • 2 JavaScript tasks, each 1,000ms = TBT of 2 × 950ms = 1,900ms blocking

Thresholds

  • ≤ 200ms: Good — page feels snappy
  • 200 600ms: Needs improvement — noticeable sluggishness
  • ≥ 600ms: Poor — page feels frozen

rds.ink Status: 1,807ms = CRITICAL 🔴

The page has 1,800ms of JavaScript execution blocking interactions. During page load, the user cannot interact for 1.8 seconds.

This is why the score is 77 instead of 95.

What Causes High TBT

  1. Large JavaScript bundles (1.8 MB on this page)
  2. Synchronous JavaScript execution — No chunking or deferring
  3. Too many plugins — Each plugin adds code to parse/execute
  4. Unoptimised heavy libraries — jQuery, older frameworks
  5. No code-splitting — Entire app loads upfront instead of as-needed

How to Fix (for WordPress/Hummingbird)

  1. Defer non-critical JavaScript (add defer attribute)
    • Page renders first
    • Scripts load in background
    • TBT moves to after page is interactive
  2. Lazy-load heavy plugins (load only when needed)
    • Gallery/lightbox: load when user clicks product
    • Booking widget: load only on booking page
  3. Disable unused plugins (every plugin = more JS)
  4. Code-split large bundles (Webpack/bundler feature)
    • Don't load everything upfront
    • Load only what's visible
  5. Minify/compress JavaScript (reduce parse time)

Expected Impact of Fixes

  • Current: 1,807ms blocking
  • After defer JS: ~400ms
  • After lazy-load: ~150ms
  • After disabling unused: ~100ms
  • Target: <200ms

5. TTFB — Time to First Byte

Definition

The time from when the browser makes a request until the server sends the first byte of the response.

User hits link at 0ms
    ↓
0-50ms: Network latency
    ↓
50-100ms: Server processes request
    ↓
100-144ms: Server sends response (for this page)
    ↓ This is TTFB
144ms: Browser receives first byte

Why It Matters

TTFB is a server-side metric. It measures how fast your infrastructure is.

Everything downstream depends on TTFB. You can't optimise FCP if TTFB is 2 seconds.

Thresholds

  • ≤ 0.8 seconds: Good
  • 0.8 1.8 seconds: Needs improvement
  • ≥ 1.8 seconds: Poor

rds.ink Status: 144ms = EXCELLENT ✓

The server responds in 144ms. This is good. Not the bottleneck.

What Affects TTFB

  1. Server processing time — Database queries, rendering, etc.
  2. Network latency — Distance from client to server
  3. Server hardware — CPU/RAM/I/O speed
  4. Caching — Is the page/response cached?
  5. DNS resolution — Domain lookup time

How to Fix

  1. Enable page caching (Hummingbird)
    • Cached pages: TTFB 50ms
    • Uncached: TTFB 144ms
  2. Optimise database queries (most common bottleneck)
    • Use database indexing
    • Avoid N+1 queries
    • Query Monitor plugin helps diagnose
  3. Use a CDN for static assets
    • CSS, JS, images served from fast edge servers
  4. Upgrade hosting (if server is slow)
    • More CPU cores
    • Faster SSD storage
    • Better network connection

Summary Table

Metric Causes Quick Fixes
LCP Slow TTFB, lazy images, render-blocking JS Defer JS, optimize TTFB
FCP Slow TTFB, render-blocking resources Defer JS, lazy load
CLS Unset dimensions, ads, fonts, animations Set dimensions, use transform
TBT (THE PROBLEM) Large JS, too many plugins, sync code Defer JS, lazy-load plugins, disable unused
TTFB Slow server, no cache, slow DB Enable cache, optimize queries

See also: