// blog / speed

How I find what's slowing Interaction to Next Paint

Interaction to Next Paint measures how long a page takes to show a visible response after a tap, click or key press, and web.dev counts 200 milliseconds or less as good. I don't start with a lab score. I find the slow interaction in field data, then trace it in DevTools to the script blocking the main thread.

By Muhammad Younus Updated 10 min read Speed

Speed and Core Web Vitals: illustration for "Finding what slows INP"
// 01 - the metric

What is Interaction to Next Paint, and how is INP calculated?

The INP metric is the time from a visitor's tap, click or key press to the next frame the browser paints in response. If a menu takes 400 milliseconds to open after a tap, that tap scored 400. It's one of the three Core Web Vitals, and when it fails on the templates that earn money, it's the metric I trace to the plugin or script behind it as a Core Web Vitals consultant.

web.dev defines it as the latency of every click, tap and keyboard interaction across the whole visit. Hovering, scrolling and zooming don't count. The page's INP is the longest interaction it saw, and on pages with lots of interactions one of the highest is dropped for every 50, so a single freak tap doesn't decide it. The verdict is then read at the 75th percentile across visits.

Each interaction splits into three parts, and naming the part that's slow is half the diagnosis.

The three parts of one interaction, and where I look first on WordPress
PartWhat's happeningWhere I look first on WordPress
Input delayThe tap is waiting because the main thread is busy with something elseScripts still evaluating during page load, from plugins, the theme and third-party tags
Processing durationThe page's own event handlers are runningThe click handler of a menu, filter, slider or add to cart button doing too much at once
Presentation delayThe browser is working out the new layout and painting itA very large DOM, often from nested page builder containers

The thresholds come straight from web.dev: 200 milliseconds or less is good, anything over 500 is poor, and the range between needs improvement. The other two metrics have their own posts, Cumulative Layout Shift and Largest Contentful Paint. And INP isn't a slow page load: if the whole page drags before anyone taps, that's a loading problem, and I've written up how I find out why a WordPress site is slow.

// 02 - field versus lab

Why does field INP differ from what a lab test shows?

Because a lab test doesn't tap anything. The lab section of PageSpeed Insights is one simulated load on one device, and a plain page load has no interactions to time. web.dev names Total Blocking Time as the lab stand-in. It tells you the main thread was busy during load, but not whether anyone's tap landed in that busy spell.

Field data comes from the Chrome User Experience Report: real visits over a trailing 28 days, on whatever phones and connections your visitors actually have. A mid-range phone can spend far longer evaluating the same JavaScript than a developer's laptop, and visits like that set the 75th percentile. So a page can post a green lab score and still fail INP in Search Console, and when the two disagree I go with the field.

What each INP source can and can't tell you
SourceWhat it tells youWhat it can't tell you
Search Console Core Web Vitals reportWhich URL group fails INP, by device, over 28 daysWhich element or script is slow
PageSpeed Insights field sectionThe URL's own INP, or the whole origin's when the URL has too few visitsWhich interaction set the number
web-vitals attribution build or a RUM toolThe element, the interaction type, the three parts and whether the page was still loadingAnything about visits from before it was installed
DevTools Performance panelThe exact long task and the file that owns it, for one interaction you reproduceHow often real visitors hit it
// pro tip

No field data at all? Search Console shows No data available when CrUX hasn't got enough visits. Then I tap through the usual visitor paths while the page loads, as web.dev suggests, and call the result an estimate.

// 03 - the method

How I find the slow interaction, step by step

I go from the widest view down to one function in one file, in this order, and I don't skip ahead to the lab.

  1. Step 01

    Read the Core Web Vitals report by device

    In Search Console I note which URL groups fail on INP, mobile and desktop separately. The example URLs tell me which template to test.

  2. Step 02

    Check the URL's own field reading

    PageSpeed Insights shows the tested URL's field INP when it has enough visits and falls back to the origin when it hasn't. An origin reading covers the whole site, so I test several templates before blaming one.

  3. Step 03

    Capture which element was slow

    The web-vitals library's attribution build reports a CSS selector for the element behind the page's INP, such as button#save, plus the interaction type, the three parts and whether the page was still loading. A RUM tool, if the site runs one, shows the same.

  4. Step 04

    Record the same tap in DevTools

    In the Chrome DevTools Performance panel I press Record, make the interaction and stop. The Interactions track shows input delay and presentation delay as whiskers either side of the processing block, and long tasks carry a red triangle in their corner.

  5. Step 05

    Reproduce it the way a visitor meets it

    If it's fast on my machine, I throttle the connection and tap as soon as the page paints, because web.dev notes the main thread is often busiest at startup.

  6. Step 06

    Name the file that owns the long task

    Under the long task, the Main track shows the script and function that ran. On WordPress the file path gives the owner away: /wp-content/plugins/ is a plugin, /wp-content/themes/ is the theme, and a third-party domain means a tag or widget.

  7. Step 07

    Change one thing, then wait for the field

    I fix the owner of the worst long task, retest the same tap in the lab, and start validation in Search Console. Its monitoring window runs 28 days, so the field result arrives about a month later.

// watch out

Don't chase the lab Performance score. A higher number can come from delaying more scripts, which moves their cost onto the first tap and can make field INP worse, not better.

Rather have me do this? One person, whole job.

Book a call on Upwork
// 04 - the usual owners

Which WordPress features cause most slow INP?

These are the features I check first when the long task's file path points inside WordPress. Each maps to a part of the interaction.

  1. i.

    Sliders and carousels

    A slider sets itself up with JavaScript while the page loads. If that setup runs as one long task, any tap that lands during it waits, and it shows up as input delay.

  2. ii.

    Chat and support widgets

    Many load a sizeable third-party script, evaluated on your visitor's phone, so its cost lands on the same main thread your buttons need.

  3. iii.

    Heavy menus

    Mega menus and off-canvas menus from themes and page builders can run a lot of work in the tap handler, or open a panel with hundreds of elements. That lands in processing and presentation delay.

  4. iv.

    Add to cart and filter scripts

    On WooCommerce, an add to cart or product filter click can update the cart and redraw part of the page in one go. When a single handler does all of it, the processing part grows.

  5. v.

    Very large pages from nested containers

    web.dev ties presentation delay to DOM size. Page builders that wrap each element in several containers make every repaint after a tap more expensive.

  6. vi.

    Tags and consent banners

    A consent banner's accept button can fire every tag it was holding back. That's one tap paying for a stack of scripts at once.

  7. vii.

    A delay JavaScript setting

    It makes loading look lighter and can slow the first tap, as the next section shows.

// 05 - delayed scripts

How can a delayed-JavaScript setting make the first tap slower?

A delay JavaScript setting holds scripts back until the visitor does something. WP Rocket's documentation lists what its version waits for: moving the mouse over the page, touching the screen, scrolling, or pressing a key. Until then the held scripts don't run, which is why the lab load looks so light.

The cost doesn't disappear; it moves to the first interaction. On a phone there's no mouse movement, so the first touch is often the trigger, and the browser now has to fetch and evaluate every held script at once. web.dev names script evaluation during load as a main source of input delay, so a page can pass a lab test and fail INP on the very tap that woke the scripts up.

I don't switch the setting off wholesale, because it does help loading. I test the first tap on a cold load with it on and off, then use WP Rocket's exclusion field for the scripts the first interaction needs, like the menu, the cart button and the consent banner.

There's a search side as well. Googlebot doesn't tap or scroll the way a visitor does, so if a held script draws content or links, I check the rendered HTML, which is whether Google can read what your scripts put on the page.

// watch out

Two optimisation plugins that both delay scripts is the one setup I untangle before measuring anything, because the trace won't mean much until only one decides what runs.

// 06 - the fix

How do I improve Interaction to Next Paint once the script has a name?

The fix follows the owner, and that's my honest answer to how to improve INP: change what the trace named, not a generic setting. These are the fixes I reach for, matched to the part that's slow.

  1. i.

    Stop a plugin loading where it isn't used

    A plugin that's only needed on one page shouldn't evaluate its scripts on every page. Less script at startup means less input delay for an early tap.

  2. ii.

    Swap or remove the widget

    A widget that isn't earning its cost gets replaced or removed. That's your call, but the trace shows what it costs.

  3. iii.

    Break up the long task

    When one handler does too much, web.dev's advice is to yield to the main thread, for example with setTimeout, right after the part that updates the screen. As it puts it: "Yielding indiscriminately is better than not yielding at all."

  4. iv.

    Stop layout thrashing

    Code that changes styles and then reads layout values in the same task forces the browser to lay out the page early. web.dev calls it layout thrashing, and DevTools flags it with a red triangle on Recalculate Style or Layout.

  5. v.

    Shrink what the tap redraws

    Presentation delay grows with DOM size, so cutting nested builder containers on the failing template makes every repaint after a tap cheaper.

When the honest fix is a new theme or a rebuilt layout, that's build work outside the SEO scope I sell here, and I'll say so plainly. My part is the diagnosis, the targeted fixes and the field-data check afterwards, which is how every project I take on runs. I won't tell you a better INP will move rankings, and I haven't got a case study that measures INP work, which is why the case studies on this site don't claim one.

// when to hand this over

If Search Console flags INP and you'd rather one person traced it from the report to the file and fixed what's in scope, that's the Core Web Vitals work I do, remotely, over Zoom, Meet or async.

Book a call on Upwork

Is this your site? Send me the URL.

Book a call on Upwork
// questions - speed

What else do people ask about this?

What is a good INP score?

200 milliseconds or less, read at the 75th percentile of visits. web.dev calls anything over 500 milliseconds poor, and the range between 200 and 500 needs improvement.

Is INP the same as First Input Delay?

No. First Input Delay only timed the wait before the first interaction's handlers started. INP replaced it as a Core Web Vital and times the whole response, for every click, tap and key press in the visit.

What if no INP value is reported?

web.dev gives three reasons: the visitor never clicked, tapped or pressed a key, they only scrolled or hovered, which INP doesn't count, or the visit was a bot such as a search crawler. PageSpeed Insights also falls back to the origin when a URL has too few visits.

Can a caching plugin fix INP on its own?

Not usually. Caching speeds up the server response, which helps loading, but INP is about the main thread after the page arrives. A caching plugin's delay JavaScript option can even move script cost onto the first tap.

// sources - checked

Where do these rules come from?

Platform and Google documentation, opened and read on the day this was written. Everything else is how I work.

  1. web.dev: Interaction to Next Paint (INP)
  2. web.dev: Optimize Interaction to Next Paint
  3. web.dev: Find slow interactions in the field
  4. web-vitals library README: INP attribution
  5. web.dev: Diagnose slow interactions in the lab
  6. Search Console Help: Core Web Vitals report
  7. PageSpeed Insights: about field and lab data
  8. WP Rocket documentation: Delay JavaScript execution
Muhammad Younus, WordPress technical SEO consultant
// who wrote this

One consultant, writing down his own method

I'm Muhammad Younus, a WordPress technical SEO consultant with 8+ years of experience and 100+ client sites fixed. Top Rated Plus on Upwork with a 100% Job Success Score. Every post here is the way I actually do the job, written in the first person because it's one person doing it, remotely, with no team behind the name.

Nothing in these posts is a client I can't name or a number I can't show. Where a figure comes from a client's Search Console, it's from a published case study, and where a rule comes from Google or a platform, the source is linked at the bottom of the post.

// the service behind this post
Muhammad Younus pointing toward the camera with an inviting smile
// next step

Want this done on your own site?

Book a call on Upwork, send the URL and read-only Search Console access, and you'll get a written scope for the search side before any work starts. One person does the whole job, remotely.

Book a call on Upwork