Technical SEO MasteryCore Web Vitals, mobile-first indexing and security · Lesson 14 of 18

INP deep dive: long tasks, attribution and real-user monitoring

Article · 16 min · 8 min lecture

Video lecture

INP deep dive: long tasks, attribution and real-user monitoring

13 chapters · about 8 min · full transcript

Coming soon

Chapter 1 of 13

INP deep dive

  • Anatomy of an interaction
  • The right tools
  • RUM that names the culprit

The narrated lecture is in production

Every chapter is scripted and ready. Browse the chapters and read the full transcript now — the video will appear here when it’s published.

Chapters

Why INP needs its own lesson

Interaction to Next Paint is the Core Web Vital sites fail most often on mobile, and it's the hardest to debug because it depends on real interactions on real devices. Lab tools can't reproduce your users' taps on a mid-range Android phone with twelve third-party scripts loaded. This lesson gives you the model, the tooling and a real-user monitoring (RUM) set-up that tells you which element and which script make interactions slow.

The anatomy of an interaction

INP observes interactions (clicks, taps, key presses) during the page visit and reports a value close to the worst one (for pages with many interactions, high outliers are ignored). Each interaction has three phases:

PhaseWhat happensTypical causes of delay
Input delayTime until event handlers can startMain thread busy with other long tasks (hydration, third-party scripts, timers)
Processing durationYour event handlers runHeavy handler logic, synchronous state updates, large re-renders
Presentation delayBrowser renders the next frameLarge DOM, expensive style/layout, forced synchronous layout

Good INP is ≤ 200 ms at the 75th percentile; poor is > 500 ms.

Tooling

  • Chrome DevTools Performance panel: record an interaction; look at the Interactions track and the long tasks around it. Live metrics show INP for interactions you perform locally.
  • Long Animation Frames (LoAF) API: exposes frames that took longer than 50 ms, with script attribution (which script, which function, which source URL) — far more useful than the older Long Tasks API.
  • web-vitals library (attribution build): reports INP from real users with the interaction target, phase breakdown and associated LoAF entries.
  • CrUX / Search Console: tell you that you have a problem, per URL group, but not why.

Hands-on: RUM for INP with the web-vitals attribution build

<script type="module">
  import { onINP } from "https://unpkg.com/web-vitals@5/dist/web-vitals.attribution.js?module";

  onINP(({ name, value, rating, attribution }) => {
    const body = JSON.stringify({
      metric: name, value: Math.round(value), rating,
      target: attribution.interactionTarget,          // CSS selector of the element
      type: attribution.interactionType,              // "pointer" or "keyboard"
      inputDelay: Math.round(attribution.inputDelay),
      processing: Math.round(attribution.processingDuration),
      presentation: Math.round(attribution.presentationDelay),
      scripts: (attribution.longAnimationFrameEntries || [])
        .flatMap(f => f.scripts || []).map(s => s.sourceURL).slice(0, 5),
      page: location.pathname,
    });
    navigator.sendBeacon("/rum", body);               // or send to GA4 as an event
  });
</script>

Pin the library version in production (self-host or bundle it) rather than loading from a public CDN, and check the web-vitals README for the current attribution field names when you upgrade. Aggregate server-side by page template and target, and rank by the 75th percentile of value. The scripts list is where third-party culprits reveal themselves.

Fix patterns by phase

Input delay — reduce what's running when users interact:

  • Defer or remove non-essential third-party scripts; load chat widgets on interaction.
  • Split hydration (islands/partial hydration) so the whole page doesn't hydrate at once.
  • Avoid long-running timers and polling on the main thread.

Processing duration — make handlers cheap and yield:

button.addEventListener("click", async () => {
  showSpinner();                                  // immediate visual feedback
  await (globalThis.scheduler?.yield?.() ?? new Promise(r => setTimeout(r, 0)));
  const result = expensiveFilter(items);          // heavy work after the next paint opportunity
  render(result);
});

Presentation delay — keep rendering cheap:

  • Reduce DOM size; virtualise long lists.
  • Avoid layout thrashing (reading offsetHeight right after writing styles).
  • Use content-visibility: auto for off-screen sections.

Worked example: a Dubai marketplace's filter taps

A Dubai marketplace (illustrative) has poor mobile INP on category pages. RUM shows the worst interactions are taps on filter chips (button.filter-chip), with large processing duration, and LoAF script attribution pointing at the site's own bundle plus a tag-manager-loaded heatmap script. Fixes: the filter handler updates the chip state immediately and yields before recomputing the product grid; grid rendering is virtualised; the heatmap script is sampled to a small share of sessions. RUM p75 INP for filter taps drops into the "good" range over the following weeks, later confirmed in CrUX.

Measuring success

  • RUM p75 INP by template and by top interaction target.
  • Share of interactions rated "good".
  • CrUX/Search Console status for the URL group after the 28-day window.

Common mistakes

  • Optimising Total Blocking Time in Lighthouse and assuming INP is fixed.
  • Collecting INP without attribution, so nobody knows which element is slow.
  • Blaming "the framework" before checking third-party scripts in LoAF data.

Key takeaways

  • INP reports near-worst interaction latency at p75: ≤ 200 ms good, > 500 ms poor.
  • Each interaction splits into input delay, processing duration and presentation delay; fixes depend on the dominant phase.
  • Long Animation Frames (LoAF) and the web-vitals attribution build name the element and scripts behind slow interactions.
  • Give instant feedback, then yield; defer third parties; shrink the DOM and virtualise lists.
  • Measure with RUM by template and target, then confirm in CrUX after the 28-day window.

Check your understanding

Quick questions to lock in the lesson. They don’t count towards your certificate.

  1. RUM shows slow taps dominated by input delay. What's the most likely cause?
  2. Which API attributes slow frames to specific scripts and source URLs?
  3. Lighthouse Total Blocking Time improved. Is INP fixed?

Put it into practice

Add the web-vitals attribution snippet to one template for a week, rank the five slowest interaction targets by p75, and write a ticket for the worst one naming its dominant phase and scripts.

Enrol for free to save your progress

Reading is always free. Enrol to keep your place, take the final assessment and earn a verifiable certificate.