Key Takeaways
- INP measures how fast your site responds to user interactions — clicks, taps, and keyboard input — with a threshold of 200ms
- INP replaced FID as a Core Web Vital in March 2024, and it’s significantly harder to pass because it measures the worst interaction, not the first
- The three phases of INP: input delay (blocked main thread), processing time (event handler execution), and presentation delay (browser rendering)
- Heavy JavaScript is almost always the cause — third-party scripts, jQuery handlers, bloated plugins, and unoptimised event listeners
- Breaking long tasks with
yield()patterns and deferring non-critical JavaScript are the highest-impact fixes for WordPress sites
What is INP and why WordPress sites struggle
Interaction to Next Paint measures the time between a user interaction — a click, tap, or key press — and the moment the browser presents the next visual update. It’s the newest Core Web Vital, replacing First Input Delay (FID) in March 2024, and it’s the metric most WordPress sites are now failing. INP answers the question every visitor asks: “Did my click actually do something?”
The threshold is 200 milliseconds. Under 200ms is good, 200–500ms needs improvement, and over 500ms is poor. Google measures your 75th percentile worst interaction from real users in the Chrome User Experience Report (CrUX). As we cover in our complete Core Web Vitals guide, this field data — not lab scores — determines your ranking impact. Unlike FID, which only measured the first interaction’s input delay, INP tracks every interaction throughout the entire page lifecycle and reports the worst one. That’s why sites that passed FID easily are now failing INP.
WordPress is particularly vulnerable because the platform accumulates JavaScript from plugins, themes, and inline scripts. A contact form plugin that loads 150KB of JavaScript on every page. A slider that registers dozens of event listeners. WooCommerce adding cart fragment AJAX on every click. Each of these individually might not break INP, but together they create a main thread so congested that a simple button click takes 400ms to produce a visual response.
Understanding the three phases of INP
Every interaction that INP measures goes through three phases, and fixing INP requires understanding which phase is causing your delay:
Phase 1: Input Delay. The time between the user’s interaction and when your event handler starts executing. This happens when the main thread is busy doing something else — parsing JavaScript, running a timer callback, or processing a previous interaction. If a third-party analytics script is executing a 150ms task when the user clicks, that’s 150ms of input delay before your click handler even begins.
Phase 2: Processing Time. The time your event handler takes to execute. This is the code that runs in response to the click — updating state, making API calls, manipulating the DOM. A poorly written WooCommerce “Add to Cart” handler that synchronously updates the mini-cart, recalculates totals, and triggers multiple jQuery callbacks can easily take 200ms of processing time alone.
Phase 3: Presentation Delay. The time between your event handler completing and the browser painting the visual update. This includes style recalculations, layout, and paint. If your handler changes CSS that triggers layout on hundreds of DOM elements, or forces a synchronous reflow by reading layout properties immediately after writing them, this phase balloons.
The total INP value is the sum of all three phases. A 300ms INP might be 100ms input delay + 120ms processing + 80ms presentation. You need to diagnose which phase dominates before choosing fixes.
How to diagnose INP issues
You can’t fix INP with lab tools alone — you need field data because INP depends on real user behaviour. But lab tools help you identify the problematic scripts.
Chrome DevTools Performance Panel. Open DevTools, go to the Performance tab, and enable “Web Vitals” in the timeline. Record while you interact with the page — click buttons, open menus, type in search boxes, toggle filters. Look for long tasks (marked with red triangles) that coincide with your interactions. Click the task to see the call stack and identify which script is responsible.
The Web Vitals Extension. Install Google’s Web Vitals Chrome extension and set it to “Console Logging” mode. It logs every interaction with its INP value, the target element, and which phase was slowest. This is the fastest way to find your worst interactions — it might be the mobile menu toggle, the WooCommerce quantity selector, or a filter button you didn’t think to test.
The Long Animation Frames API. For deeper analysis, the LoAF API (PerformanceObserver with type long-animation-frame) gives you frame-level data including which scripts blocked the main thread and for how long. This is particularly useful for identifying third-party scripts that cause input delay.
Key things to check on a WordPress site:
- Click every button and interactive element — don’t just test page load
- Test on a throttled CPU (4x slowdown in DevTools) to simulate real mobile devices
- Check WooCommerce product pages — quantity changes, variation selects, and add-to-cart are common offenders
- Test search forms, especially with live search or autocomplete plugins
- Check cookie consent banners — they often register click handlers on every element
Fix #1: Reduce input delay by eliminating long tasks
Input delay happens when the main thread is blocked by long tasks — JavaScript execution that takes over 50ms. Every plugin that loads JavaScript on your page contributes to this problem.

Start with a JavaScript audit. Open Chrome DevTools, go to Coverage (Ctrl+Shift+P, then “Show Coverage”), and reload the page. This shows exactly how much of each JavaScript file is actually used. On a typical WordPress site, 60–80% of loaded JavaScript goes unused on any given page. As we detail in our guide on deferring JavaScript in WordPress, removing or deferring this unused code is the single biggest thing you can do for INP.
The most impactful fixes:
Defer third-party scripts. Analytics, chat widgets, heatmaps, and social sharing buttons all load JavaScript that executes on the main thread. Move them to load after user interaction or after the page is idle. Google Tag Manager should use the defer attribute. Chat widgets should load on scroll or click, not on page load.

Conditionally load plugin scripts. Most WordPress plugins load their JavaScript and CSS on every page, even where they’re not needed. A contact form plugin loading its JavaScript on your blog posts. A slider script loading on pages with no slider. Use a performance plugin or custom code to restrict scripts to pages where they’re actually used. This reduces main thread work across your entire site.
Break up long tasks. If you have custom JavaScript that runs for more than 50ms, break it into smaller chunks using scheduler.yield() or the setTimeout(0) pattern. This gives the browser a chance to process pending user interactions between chunks:
// Instead of one long function:
async function processItems(items) {
for (const item of items) {
processItem(item);
// Yield to the main thread every 5 items
if (items.indexOf(item) % 5 === 0) {
await scheduler.yield();
}
}
}
Fix #2: Optimise event handler processing time
Processing time is the execution time of your event handlers — the JavaScript that responds to user clicks, taps, and key presses. On WordPress sites, this is often dominated by jQuery and plugin callbacks.
Audit jQuery event handlers. WordPress themes and plugins love chaining jQuery event handlers. A single button click might trigger 5 different handlers from 5 different plugins, each manipulating the DOM and recalculating styles. Open DevTools, go to Elements, select the problematic element, and look at “Event Listeners” in the sidebar. You’ll often find handlers from plugins you didn’t know existed.
Debounce scroll and resize handlers. Many WordPress themes register scroll and resize event listeners that fire dozens of times per second. These keep the main thread constantly busy, causing input delay for real interactions. Any scroll handler should be debounced or use IntersectionObserver instead:
// Bad: fires on every scroll event
window.addEventListener('scroll', updateHeader);
// Good: only fires when element enters viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) updateHeader();
});
});
observer.observe(document.querySelector('.header-trigger'));
Minimise DOM manipulation in handlers. Every DOM change can trigger style recalculation and layout. Batch your DOM changes: read all the values you need first, then make all your writes. Never interleave reads and writes — this causes “layout thrashing” that can multiply your processing time by 10x.
Move work off the main thread. Heavy computations like search filtering, data processing, or image manipulation should happen in a Web Worker, not the main thread. The main thread should only handle user interactions and DOM updates.
Fix #3: Minimise presentation delay
Presentation delay is the time between your event handler completing and the browser painting the visual update. It includes style recalculation, layout, compositing, and paint.
Reduce DOM size. WordPress page builders are notorious for generating massive DOM trees — 3,000+ nodes is common with Elementor or WPBakery. Every style recalculation has to process all these nodes. The impact on INP is quadratic — doubling DOM nodes roughly quadruples recalculation time. Keep your DOM under 1,500 nodes where possible. Like LCP and CLS, excessive DOM complexity makes everything worse.
Avoid layout-triggering properties. Some CSS properties trigger full layout recalculation when changed. Avoid changing width, height, top, left, padding, or margin in response to interactions. Instead, use transform and opacity — these only trigger compositing, which is vastly cheaper. A mobile menu that slides in using transform: translateX() instead of left: 0 will respond dramatically faster.
Use CSS content-visibility: auto. For long pages, this CSS property tells the browser to skip rendering offscreen content until it’s needed. This reduces the work the browser has to do when your event handler triggers a visual update:
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
}
Reduce CSS complexity. Complex selectors like .sidebar .widget ul li a:hover span.icon force the browser to walk up the DOM tree for every element during style recalculation. Flatten your selectors. Use BEM or similar methodology. The simpler your CSS selectors, the faster the browser can recalculate styles after DOM changes.
WordPress-specific INP problems and solutions
These are the most common INP issues we see specifically on WordPress sites:
WooCommerce cart fragments. WooCommerce loads a script called cart-fragments.js that fires an AJAX request on every page load to update the mini-cart. This isn’t just a performance problem on load — it registers handlers that fire on cart interactions and can block the main thread for 200ms+. If you don’t have a mini-cart in your header, disable it entirely. If you do, consider loading it only on shop pages.
jQuery Migrate. WordPress still loads jQuery Migrate (30KB) by default to support legacy plugins. This script wraps jQuery methods with compatibility shims that add overhead to every jQuery call. If your theme and active plugins don’t need it (most modern ones don’t), remove it. Test thoroughly after removal.
Contact form validation. Plugins like Contact Form 7 and Gravity Forms load validation scripts globally. Their real-time validation handlers fire on every keystroke, and on older devices this can push INP past 200ms. Load these scripts only on pages with forms, and consider switching to native HTML5 validation for simple forms.
Mega menus. Complex navigation menus that generate dozens of DOM elements on hover, load images, and run animation JavaScript are a common INP killer on mobile. When a user taps the menu toggle, the browser has to parse the handler, generate the DOM, recalculate styles, and paint — all in one long task. Build menus with CSS transitions instead of JavaScript animation, and use <details>/<summary> elements for native disclosure behaviour.
Lazy loading plugins. Ironically, some lazy loading plugins hurt INP by registering scroll handlers on every image. Each scroll event triggers intersection calculations for dozens of images, blocking the main thread. Native lazy loading (loading="lazy") is handled by the browser off the main thread and has zero INP impact.
Testing and monitoring INP
INP is uniquely difficult to test because it depends on real interactions, not page load. You can’t just run Lighthouse and get an accurate INP score.
Field data is essential. PageSpeed Insights shows field INP data from CrUX if your site has enough traffic. This is the score Google uses for rankings. Lab tests can identify potential issues, but only field data confirms them — a user on a low-end Android phone tapping your menu while a third-party script is executing creates a scenario you can’t reproduce in lab conditions.
Test methodically. When using DevTools, don’t just click randomly. Create a test protocol: click the navigation menu, interact with forms, use search, click product variations, add items to cart, toggle filters, expand FAQ accordions. Record each interaction and note the INP value. The worst one is what Google measures.
Throttle properly. In DevTools Performance tab, use 4x CPU slowdown to simulate a mid-range mobile device. Desktop hardware masks INP problems that are severe on mobile. Most of your users are on devices much slower than your development machine.
Monitor continuously. INP can regress silently. A plugin update that adds a new event listener, a theme update that changes the menu JavaScript, a new chat widget — any of these can push INP past 200ms without you noticing until rankings drop. Set up real-user monitoring to catch regressions immediately.
The goal isn’t just to get INP under 200ms once — it’s to keep it there as your site evolves.
Frequently asked questions
What replaced FID as a Core Web Vital?
Interaction to Next Paint (INP) officially replaced First Input Delay (FID) as a Core Web Vital in March 2024. INP is a much harder metric to pass because it measures the worst interaction throughout the entire page lifecycle, while FID only measured the delay of the very first interaction. Sites that passed FID easily may fail INP.
What is a good INP score?
A good INP score is under 200 milliseconds. Google measures your 75th percentile — meaning 75% of your users’ worst interactions must complete in under 200ms. Scores between 200–500ms need improvement, and anything over 500ms is rated poor. Google uses field data from real users (CrUX), not lab tests, to determine this.
Why is my INP score different from my FID score?
FID only measured the input delay (time before your event handler started) of the first interaction. INP measures the complete response time — input delay plus processing time plus presentation delay — of the worst interaction across the entire session. A page might have had great FID because the first click happened when the main thread was idle, but terrible INP because clicking a filter button later triggers 400ms of JavaScript processing.
Can I test INP in Lighthouse or PageSpeed Insights?
Lighthouse doesn’t directly measure INP because it’s a lab tool and INP requires real user interactions. PageSpeed Insights shows field INP data from the Chrome User Experience Report (CrUX) if your site has enough traffic. For lab testing, use Chrome DevTools Performance tab with the Web Vitals timeline enabled while manually interacting with the page. The Web Vitals Chrome extension is also useful for quick per-interaction testing.
Does INP affect SEO rankings?
Yes. INP is one of the three Core Web Vitals used in Google’s page experience ranking signal, alongside Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS). Failing INP won’t cause your site to disappear from search results, but it removes a ranking boost that competing pages with good INP scores receive. The impact is most noticeable in competitive niches where content quality is similar.
Is slow JavaScript killing your INP score?
Our engineers diagnose exactly which scripts are blocking your interactions and fix them. Every engagement includes full before-and-after INP measurements.