# INP Attribution — Which Click Actually Broke The 200ms Budget

CWV Audit says your INP p75 is 340 ms. That&#39;s the aggregate. It doesn&#39;t tell you which click, which handler, which third-party script caused the jank. The new profiler loads your URL in an iframe, hooks PerformanceObserver + long-animation-frame, and attributes each slow interaction to a specific event target and script origin.

Author: J.A. Watte
Published: May 2, 2026
Source: https://jwatte.com/blog/blog-tool-inp-attribution/

---

_Part of the [performance audit tool stack](/blog/blog-new-performance-audit-tools-2026/).  See the pillar post for the full catalog of sibling audits and where this one fits in the lineup._

INP replaced FID as a Core Web Vital in March 2024. The aggregate number is easy to measure. The per-interaction attribution is the hard part — and it's what actually tells you what to fix.

[INP Attribution Profiler](/tools/inp-attribution/) loads your URL in an iframe, subscribes to `PerformanceObserver` with `event` + `long-animation-frame` types, and captures every interaction that crosses 50 ms. For each one, it records the event target (tag + id + class), the processing duration, and the script origins blocking the main thread during the long frame.

## The three signals it captures

**Interaction entries.** `PerformanceObserver` with `type: 'event'` fires once per slow interaction. Each entry includes `duration`, `processingStart`, `processingEnd`, and the target element. Anything over 200 ms is a CWV failure; anything over 100 ms is a warning.

**Long Animation Frame entries.** The LoAF API (2024) exposes which scripts executed during a frame that blocked rendering. You get a `scripts` array with `sourceURL` and per-script `duration`. This is how you attribute to a specific third-party bundle.

**Script-origin rollup.** The tool tallies blocking-milliseconds per origin across all long frames. One GA4 script blocking 1200 ms across 8 frames is the same signal as eight separate 150 ms blocks — and the tool makes both visible.

## What to do with the output

The AI fix prompt emits specific patches: defer heavy third-party scripts, break long tasks with `requestIdleCallback`, debounce input handlers, move expensive DOM measurements off the critical path. For any slow `pointerdown` / `click` interaction, the target selector tells you which React component needs a React.memo or a `useDeferredValue`.

## Limitations

Cross-origin iframes block `PerformanceObserver`. For accurate measurement, deploy this tool on the same origin as the target page (or run it against your own site). Same-origin runs expose everything; cross-origin runs gracefully degrade to a warning.

## Related reading

- [CWV Audit](/tools/cwv-audit/) — page-level aggregate
- [CWV Fix Generator](/tools/cwv-fix-generator/) — emits the patches
- [Render-Block Audit](/tools/render-block-audit/) — if the page itself is JS-heavy

## Fact-check notes and sources

- INP specification: [web.dev/articles/inp](https://web.dev/articles/inp)
- Long Animation Frames API: [web.dev/articles/long-animation-frames](https://web.dev/articles/long-animation-frames)
- PerformanceEventTiming: [developer.mozilla.org/en-US/docs/Web/API/PerformanceEventTiming](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEventTiming)
- GoogleChrome/web-vitals library: [github.com/GoogleChrome/web-vitals](https://github.com/GoogleChrome/web-vitals)

---

*The $100 Network covers shipping performant sites across a network. The attribution profiler is how you diagnose the one page that's dragging the aggregate down.*


---

Canonical HTML: https://jwatte.com/blog/blog-tool-inp-attribution/
RSS: https://jwatte.com/feed.xml
JSON Feed: https://jwatte.com/feed.json
Hero image: https://jwatte.com/images/blog-tool-inp-attribution.webp
