Rankwise logoRankwise
Product
Free auditPricingCompareResources
Sign inGet started

Footer

Rankwise logoRankwise

The infrastructure layer for AI search: measure, produce, and ship the fixes that make AI engines cite you.

Built for the answer engines

Product

  • Features
  • Pricing
  • Templates

Solutions

  • For agencies
  • For in-house SEO
  • For founders
  • Use Cases
  • Integrations
  • Compare
  • Alternatives

Resources

  • Resources
  • Articles
  • Guides
  • Case Studies
  • Learn
  • Glossary
  • Topics
  • API

Company

  • About
  • Contact
ImpressumAGBDatenschutz

© 2026 Rankwise. All rights reserved.

Tracking ChatGPT · Perplexity · Claude · Google AI Overviews

Rankwise

  1. Home
  2. Resources
  3. Guides
  4. From FMP to LCP: Migrating Your Performance Metrics
Guideintermediate

From FMP to LCP: Migrating Your Performance Metrics

A practical guide to transitioning from First Meaningful Paint to Largest Contentful Paint, with updated measurement strategies and optimization targets.

Rankwise Team·Updated Mar 12, 2026·5 min read

On this page

  • Why the switch happened
  • Step 1: Map your current FMP targets to LCP
  • Step 2: Identify your LCP element
  • Step 3: Update your measurement code
  • Step 4: Update CI/CD performance budgets
  • Step 5: Optimize specifically for LCP
  • For image LCP elements
  • For text LCP elements
  • For both
  • Step 6: Monitor in the field
  • Common migration pitfalls
  • Pitfall 1: Assuming FMP ≈ LCP
  • Pitfall 2: Lazy-loading the LCP element
  • Pitfall 3: Ignoring TTFB
  • Pitfall 4: Over-optimizing lab scores
  • Frequently Asked Questions
  • Can I still track "meaningful" content timing?
  • Does LCP affect SEO rankings?
  • What if my LCP element changes between page loads?
  • How often should I check LCP?

First Meaningful Paint (FMP) was deprecated in Lighthouse 6.0 because it relied on heuristics that produced inconsistent results across browsers and tools. Largest Contentful Paint (LCP) replaced it with an objective, reproducible measurement. This guide walks through the migration: what changes, what stays the same, and how to update your monitoring.


Why the switch happened

FMP tried to detect when the "most important" content appeared on screen by tracking layout changes and picking the biggest visual shift after First Contentful Paint. The problem: "important" is subjective.

Two different tools could report two different FMP values for the same page load because they disagreed on which layout change mattered most. LCP eliminates that ambiguity by measuring the render time of the largest image or text block visible in the viewport.

Key differences:

AspectFMPLCP
What it measuresBiggest layout change (heuristic)Largest visible element (objective)
ConsistencyVaried across toolsConsistent across tools
Browser supportRemoved from ChromeAll modern browsers
Lighthouse versionRemoved in v6.0Current standard
Correlation with UXModerateStrong

Step 1: Map your current FMP targets to LCP

If you had FMP performance budgets, translate them:

  • FMP < 2s → target LCP < 2.5s (good)
  • FMP 2–3s → target LCP < 4.0s (needs improvement)
  • FMP > 3s → target LCP < 4.0s minimum, ideally < 2.5s

Do not assume a fixed ratio. Measure actual LCP on your pages first, then set realistic targets based on your architecture.


Step 2: Identify your LCP element

Every page has a single LCP element: the largest image, video poster, or text block in the initial viewport. Find it:

  1. Open Chrome DevTools → Performance panel
  2. Record a page load
  3. Look for the "LCP" marker in the timeline
  4. Click it to see which DOM element triggered it

Common LCP elements by page type:

  • Landing pages: hero image or background image
  • Blog posts: featured image or first heading + paragraph block
  • Product pages: primary product image
  • Search results: first result card or list container

Step 3: Update your measurement code

Replace any FMP-specific measurement with the PerformanceObserver API for LCP:

// LCP measurement
new PerformanceObserver(list => {
  const entries = list.getEntries()
  const lastEntry = entries[entries.length - 1]
  console.log("LCP:", lastEntry.startTime, "ms")
  console.log("Element:", lastEntry.element)
}).observe({ type: "largest-contentful-paint", buffered: true })

For custom "meaningful" tracking, use the Element Timing API:

<img elementtiming="hero-image" src="hero.jpg" alt="Hero" />

<script>
  new PerformanceObserver(list => {
    list.getEntries().forEach(entry => {
      console.log(`${entry.identifier}: ${entry.startTime}ms`)
    })
  }).observe({ type: "element", buffered: true })
</script>

Step 4: Update CI/CD performance budgets

Replace FMP assertions with LCP in your Lighthouse CI config:

// lighthouse-ci.config.js
module.exports = {
  ci: {
    assert: {
      assertions: {
        "largest-contentful-paint": ["error", { maxNumericValue: 2500 }],
        "first-contentful-paint": ["warn", { maxNumericValue: 1800 }],
        "total-blocking-time": ["error", { maxNumericValue: 200 }],
        "cumulative-layout-shift": ["error", { maxNumericValue: 0.1 }]
      }
    }
  }
}

Remove any first-meaningful-paint assertions, since they will cause errors in Lighthouse 10+.


Step 5: Optimize specifically for LCP

LCP optimization differs from FMP optimization because you know the exact target element.

For image LCP elements

  • Add fetchpriority="high" and loading="eager" to the hero image
  • Preload the image with <link rel="preload" as="image" href="hero.jpg">
  • Serve correctly sized images (avoid layout shifts from dimension changes)
  • Use modern formats (WebP, AVIF) with appropriate fallbacks

For text LCP elements

  • Inline critical CSS or use <link rel="preload"> for the font
  • Avoid font-display: swap flash; use font-display: optional if speed is priority
  • Minimize render-blocking JavaScript before the text block
  • Reduce server response time (TTFB directly impacts text LCP)

For both

  • Reduce TTFB below 800ms (server, CDN, caching)
  • Eliminate render-blocking resources above the fold
  • Avoid lazy-loading the LCP element (a common mistake with blanket lazy-load policies)

Step 6: Monitor in the field

Lab metrics (Lighthouse) show potential. Field metrics (CrUX, web-vitals library) show reality.

Set up field monitoring with the web-vitals library:

import { onLCP } from "web-vitals"

onLCP(metric => {
  // Send to your analytics endpoint
  analytics.send({
    name: metric.name,
    value: metric.value,
    rating: metric.rating, // 'good', 'needs-improvement', 'poor'
    navigationType: metric.navigationType
  })
})

Compare your field LCP against your old FMP baselines. If LCP is significantly higher than FMP was, investigate whether your LCP element is loading slowly (image optimization issue) or rendering late (render-blocking resources issue).


Common migration pitfalls

Pitfall 1: Assuming FMP ≈ LCP

They measure different things. A page with a fast layout shift (good FMP) but a slow hero image (bad LCP) will look worse after migration. That is not a regression. It is a more accurate measurement.

Pitfall 2: Lazy-loading the LCP element

Many teams apply loading="lazy" to all images. The LCP image must use loading="eager" or have no loading attribute at all.

Pitfall 3: Ignoring TTFB

LCP cannot be faster than your server response time. If TTFB is 2 seconds, LCP will be at least 2 seconds. Optimize the server path first.

Pitfall 4: Over-optimizing lab scores

A lab LCP of 1.2s on a fast machine means little if field data shows 4.5s on real devices. Always validate with CrUX or RUM data.


Frequently Asked Questions

Can I still track "meaningful" content timing?

Yes. Use the Element Timing API to measure specific elements you consider meaningful. This gives you the custom insight FMP promised without the inconsistency. Mark elements with elementtiming="label" and observe them with PerformanceObserver.

Does LCP affect SEO rankings?

LCP is part of Core Web Vitals, which is a confirmed Google ranking signal. Pages with good LCP (under 2.5s) have a ranking advantage over pages with poor LCP, all else being equal.

What if my LCP element changes between page loads?

This can happen with A/B tests, personalized content, or ad placements. Identify all possible LCP candidates and ensure each one loads quickly. Use the Element Timing API to track which element wins on each load.

How often should I check LCP?

Monitor field data continuously via CrUX or a RUM provider. Run Lighthouse audits in CI on every deploy. Review the 75th percentile LCP in CrUX monthly to track trends.

Part of the SEO Fundamentals topic

Audit your Core Web Vitals
Newsletter

Stay ahead of AI search

Weekly insights on GEO and content optimization.

See also

Robots.txt Tester: Check for Errors Before They Tank RankingsTest your robots.txt file for crawl errors, blocked pages, and misconfigurations. Step-by-step guide with free tools and common mistake fixes.How to Eliminate Layout Shifts: A Practical CLS Optimization GuideStep-by-step guide to finding and fixing Cumulative Layout Shift issues. Covers images, fonts, ads, dynamic content, and CSS containment strategies.JavaScript SEO Best Practices: Ensure Search Engines Index Your JS ContentA technical checklist for making JavaScript-rendered content crawlable and indexable. Covers rendering strategies, meta tags, internal linking, and testing methods.Optimize CSS Delivery: Eliminate Render-Blocking StylesheetsA practical guide to optimizing CSS delivery for faster page rendering. Covers critical CSS extraction, async loading, code splitting, and removing unused CSS.Preventing Layout Shifts: Architectural Patterns for Stable Web PagesArchitectural patterns and CSS strategies that prevent Cumulative Layout Shift at the design level. Build pages that never shift instead of fixing shifts after launch.