How to improve INP on WordPress and pass Core Web Vitals
How to improve INP on WordPress: find the slow interaction with field data and DevTools, then fix plugin JS, third-party tags and builder bloat to pass CWV.
Here is how to improve INP on a WordPress site: find the specific interaction that is slow using field data, work out whether the time goes to input delay, event handling or rendering, and then cut the JavaScript that causes it, which on WordPress usually means plugin scripts, page-builder bundles and third-party tags. INP (Interaction to Next Paint) is the Core Web Vital that most often turns a WordPress site's PageSpeed Insights result to "Core Web Vitals Assessment: Failed", and generic speed plugins rarely fix it on their own.
Quick answer: A good INP is 200 ms or less at the 75th percentile of real visits. To improve it, remove or delay third-party scripts, stop plugins loading JavaScript on pages that do not need it, break up long tasks so the browser can respond between them, and simplify heavy page-builder layouts. Then confirm the fix in Search Console, which takes about 28 days of new data.
What INP measures, in plain English
INP measures how long a page takes to visibly respond after someone clicks, taps or presses a key. It replaced First Input Delay (FID) as a Core Web Vital on March 12, 2024 (opens in a new tab). FID only measured the delay before the first interaction started being handled. INP looks at almost every interaction during the visit, and at the full time until the next frame is painted.
According to web.dev's INP guide (opens in a new tab):
| INP at the 75th percentile | Rating |
|---|---|
| 200 ms or less | Good |
| Over 200 ms, up to 500 ms | Needs improvement |
| Over 500 ms | Poor |
A few details matter for WordPress sites:
- Only clicks, taps and key presses count. Scrolling and hovering do not. So a heavy hover effect on a mega menu does not affect INP, but tapping the menu button on mobile does.
- The worst interaction usually decides the score. INP ignores one highest interaction for every 50, and most visits have fewer than 50 interactions, so one slow accordion or "add to cart" button can fail the page.
- Each interaction has three parts: input delay (waiting for the main thread to be free), processing duration (your event handlers running), and presentation delay (the browser recalculating styles, layout and painting the result). The fix depends on which part is large.
Core Web Vitals assessment failed on WordPress: what it actually means
When PageSpeed Insights shows "Core Web Vitals Assessment: Failed", it is reporting field data from the Chrome User Experience Report (CrUX), collected from real Chrome users over the previous 28 days. It is not about the lab score in the colored circle below it.
From Google's PageSpeed Insights documentation (opens in a new tab):
- The assessment passes only if the 75th percentile of LCP, INP and CLS are all good.
- If there is not enough INP data, it can still pass on LCP and CLS alone.
- If the URL does not have enough data, PSI falls back to the whole origin (all pages on the domain). If the origin has too little data too, you see no real-user data at all.
Two consequences that confuse many site owners:
- A 95 lab score can still fail the assessment. Lab data does not measure INP at all; it measures Total Blocking Time (TBT) as a stand-in. Your test run on a fast connection may look great while real visitors on mid-range Android phones have a slow INP.
- "No data" is not a pass or a fail. Small sites often have no field data. You can still improve INP, but you will need your own measurement (below) to know it worked.
So the first step in any "core web vitals assessment failed wordpress" case is to read which metric failed, on which device type. Mobile and desktop are assessed separately, and INP failures are much more common on mobile.
Find the slow interaction
You cannot fix INP by looking at the home page in a lab test. You have to find which element, on which page, responds slowly.
Start with Search Console and CrUX
The Core Web Vitals report in Google Search Console groups URLs with a similar experience and shows which groups fail INP. That tells you which template is the problem: product pages, blog posts, the home page. PSI on a representative URL from that group gives you the 75th percentile for that page or origin.
Reproduce it in Chrome DevTools
Open the failing page in Chrome, open DevTools, go to the Performance panel, and use the live metrics view. It shows INP for your own interactions in real time and keeps a log of each interaction. To get closer to a real phone, enable CPU throttling (4x slowdown) and mobile emulation, then click everything a visitor would: the menu toggle, accordions, tabs, filters, add to cart, form fields.
When an interaction shows a high INP, record a trace while repeating it. The trace shows the long tasks around the interaction and which script files they came from. On WordPress, the file path usually names the culprit plugin directly (/wp-content/plugins/some-plugin/...).
Collect real-user data with the web-vitals library
For sites with traffic but no clear pattern, measure INP on real visits with Google's web-vitals library (opens in a new tab). The attribution build tells you which element was interacted with and how the time split across the three phases:
<script type="module">
import { onINP } from 'https://unpkg.com/web-vitals@5/dist/web-vitals.attribution.js?module';
onINP((metric) => {
const a = metric.attribution;
console.log('INP', Math.round(metric.value), metric.rating, {
target: a.interactionTarget,
inputDelay: Math.round(a.inputDelay),
processing: Math.round(a.processingDuration),
presentation: Math.round(a.presentationDelay),
loadState: a.loadState,
});
});
</script>
In production, self-host the file and send the data to your analytics instead of the console (GA4 events work well). After a week you have a list of the slowest elements and whether they are slow during page load (loadState of loading or dom-interactive) or later.
The usual suspects on WordPress
After profiling INP on WordPress sites, the same causes keep coming up:
- Third-party tags. Tag managers loading chat widgets, heatmaps, ad scripts, several analytics tools and marketing pixels. They run long tasks on the main thread, often right when the visitor first taps something.
- Plugin JavaScript loaded everywhere. Sliders, popups, form builders, review widgets and social feeds that enqueue scripts on every page, including pages where they do nothing.
- Page-builder bundles and huge DOMs. Builders output deeply nested markup and load frontend scripts for every widget type. A large DOM makes every style recalculation and layout slower, which shows up as presentation delay.
- jQuery-heavy themes with many handlers attached to scroll, resize and click, some doing layout reads and writes in a loop.
- "Delay JavaScript until interaction" settings. These help load metrics, but if a dozen delayed scripts all start running on the first tap, that first tap becomes the slowest interaction of the visit. Check this before assuming the setting helps INP.
- WooCommerce interactions. Variation selectors, AJAX add to cart, mini-cart updates and product filters that block the main thread while they rebuild parts of the page.
How to improve INP: the fixes that work
These are ordered from the safest and most effective to the more involved.
1. Remove and trim third-party scripts
Open your tag manager and list every tag. Remove anything nobody looks at. Keep one analytics tool. Load chat widgets only when the visitor clicks a static "Chat" button. Avoid A/B testing scripts that hide the page while they run. This step alone often moves a failing INP into the needs improvement range, and it costs nothing.
2. Stop loading plugin assets where they are not needed
Query Monitor's Scripts panel lists every enqueued script with its handle and the component that added it. Unload the ones a page does not use:
add_action( 'wp_enqueue_scripts', function () {
// Example: a slider used only on the front page.
if ( ! is_front_page() ) {
wp_dequeue_script( 'example-slider' );
wp_dequeue_style( 'example-slider' );
}
}, 100 );
Replace example-slider with the real handle. Asset manager plugins do the same through a UI if you prefer not to write code. Test the pages you changed, especially forms and checkout.
3. Defer scripts properly
Since WordPress 6.3, scripts can be registered with a loading strategy (make.wordpress.org (opens in a new tab)). For your own theme or custom plugin code:
wp_enqueue_script(
'theme-main',
get_theme_file_uri( 'assets/js/main.js' ),
array(),
'1.0.0',
array( 'strategy' => 'defer', 'in_footer' => true )
);
For a plugin script that is already registered, you can request a strategy without editing the plugin:
add_action( 'wp_enqueue_scripts', function () {
wp_script_add_data( 'example-plugin-frontend', 'strategy', 'defer' );
}, 100 );
WordPress treats the strategy as a request. If a dependent script or an inline script after it needs blocking behavior, WordPress keeps it blocking, which avoids breaking the page. Deferring reduces input delay during page load, because the parser and early interactions no longer wait behind those scripts.
4. Break up long tasks in your own code
A long task is any main-thread task over 50 ms (web.dev (opens in a new tab)). While it runs, the browser cannot respond to a tap. If a custom script does a lot of work in one go, split it and yield to the main thread between chunks:
function yieldToMain() {
if (globalThis.scheduler?.yield) {
return scheduler.yield();
}
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
async function processItems(items) {
for (const item of items) {
renderItem(item);
await yieldToMain();
}
}
scheduler.yield() is supported in Chromium-based browsers and recent Firefox; the setTimeout fallback covers the rest.
The same idea fixes slow click handlers. Show feedback first, then do the heavy work after the browser has painted:
button.addEventListener('click', async () => {
button.classList.add('is-loading'); // visible feedback in the next frame
await yieldToMain();
updateCartAndRecalculate(); // heavy work after the paint
});
INP stops counting at the next paint, so painting the feedback first is what the metric rewards, and it is also what users notice.
5. Reduce DOM size and rendering work
If DevTools shows high presentation delay, the browser is spending its time on style, layout and paint, not your JavaScript. Fixes:
- Flatten page-builder layouts: fewer nested sections, columns and inner wrappers.
- Remove hidden duplicate content, such as separate mobile and desktop versions of the same section both present in the HTML.
- Render long off-screen sections lazily with CSS
content-visibility: autoplus a sensiblecontain-intrinsic-size. - Avoid animating
width,height,toporlefton click; animatetransformandopacityinstead.
6. Fix jQuery and scroll handlers
Old theme code that reads layout (offsetHeight, getBoundingClientRect) and then writes styles in a loop forces repeated layouts. Batch reads first, then writes. Throttle scroll and resize handlers, or replace them with IntersectionObserver. These are small code changes with a visible effect on presentation delay.
Page-builder notes: Elementor and Divi
You do not always need to rebuild a builder site to pass INP. If you do rebuild, my Figma to WordPress guide compares builder, block theme and custom theme routes.
- Elementor: check the Performance and Features settings in recent versions, which control optimized asset loading and leaner markup, and disable widgets you do not use. Test changes on staging, since older layouts can depend on the legacy markup.
- Divi: the theme options include performance settings that load CSS and JavaScript for modules only where they are used. Turn them on and retest.
- Any builder: limit add-on packs, avoid popups and sliders on key landing pages, and keep the header and menu simple, because the mobile menu toggle is one of the most frequently tapped elements on any site.
If a builder site still fails after this, the honest answer may be that the layout is too heavy for mid-range phones, and a lighter theme for the key templates is the cheaper long-term fix. I cover the server and loading side of speed separately in why is my WordPress site slow.
How to pass Core Web Vitals assessment: LCP and CLS quick wins
This is also the short answer to how to improve Core Web Vitals on WordPress as a whole. To pass the assessment you need all three metrics in the good range at the 75th percentile: LCP at 2.5 seconds or less, CLS at 0.1 or less, and INP at 200 ms or less. While you are working on INP, these are the cheapest wins for the other two:
- LCP: serve the hero image at the right size in WebP or AVIF, do not lazy-load it, give it
fetchpriority="high", and make sure pages are served from a page cache so the server responds quickly. - CLS: set
widthandheighton images and embeds, reserve space for ads and cookie banners, and load web fonts withfont-display: swapand a fallback with similar metrics.
These matter because a site that fixes INP but still fails LCP will keep showing "Failed". Knowing how to improve Core Web Vitals on WordPress means treating the three together.
Validate the fix in Search Console
After deploying fixes:
- Re-test with DevTools live metrics and your web-vitals data. Field data in PSI updates gradually because it is a 28-day rolling window.
- In Search Console's Core Web Vitals report, open the failing INP issue and start validation. Google's Core Web Vitals report help (opens in a new tab) explains that this begins a 28-day monitoring period; the issue only counts as fixed if no URLs show it during that window.
- Keep a short change log with dates, so if something regresses you know which change to check.
If you also want Core Web Vitals checked alongside indexing, structured data and crawl issues, that is part of a technical SEO audit.
Frequently asked questions
How to improve INP core web vitals scores quickly?
The fastest wins are removing unused third-party tags and stopping plugins from loading JavaScript on pages that do not need it. Both reduce main-thread work without touching your design. After that, find the slowest interaction with DevTools and fix that specific handler.
Why does PageSpeed Insights show a high score but Core Web Vitals failed?
The score is lab data from one simulated load, and lab data does not measure INP. The assessment uses 28 days of real-user field data. A fast lab test and slow real interactions on mid-range phones can both be true at once.
Does a caching plugin improve INP?
Mostly no. Page caching speeds up server response, which helps LCP, but INP is about JavaScript and rendering work in the browser after the page loads. Some caching plugins include JavaScript deferral and delay features that can help, or hurt, INP depending on configuration.
What is a good INP score?
A good INP is 200 milliseconds or less, measured at the 75th percentile of page visits, separately for mobile and desktop. Between 200 and 500 ms needs improvement, and over 500 ms is poor.
How long until Search Console shows the INP fix?
Expect about four weeks. Field data covers a rolling 28 days, and Search Console's validation runs a 28-day monitoring period, so improvements appear gradually as new visits replace old ones.
If your WordPress site keeps failing INP and you would rather have the slow interactions found and fixed for you, that is exactly what my WordPress speed optimization work covers.