---
title: Optimizing for Interaction to Next Paint (INP)
description: >-
  Diagnose and fix poor Interaction to Next Paint (INP) by reducing JavaScript
  execution, optimizing event handlers, and addressing common Shopify theme
  interaction bottlenecks.
source_url:
  html: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/understanding-inp
  md: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/understanding-inp.md
api_name: liquid
---

# Optimizing for Interaction to Next Paint (INP)

[Interaction to Next Paint (INP)](https://web.dev/inp/) measures page responsiveness to user interactions throughout a single page visit. Chrome usage data shows that 90 percent of user time occurs after page load, and INP captures this by reporting on the worst or nearly worst interaction across the whole visit, not just the first tap. Its predecessor, FID, measured only the first interaction. Good INP is 200 ms or less. Poor INP is above 500 ms. Both thresholds are assessed at the 75th percentile of page visits, so a single fast interaction in a lab test doesn't tell you whether you're meeting them.

***

## Why

INP is a Core Web Vital that directly affects how users perceive your store's responsiveness. When a shopper taps **Add to Cart** and nothing happens for half a second, or when a variant selector feels sluggish, the experience feels broken, even if the page loaded quickly.

Unlike LCP and CLS, which measure loading and visual stability, INP measures the ongoing interactive experience. A page can have a perfect LCP score but still feel slow if JavaScript competing for the main thread delays interactions. Every installed app, analytics script, and theme JavaScript file contributes to the main-thread workload that INP measures.

***

## The three phases of INP

Every interaction is broken into three phases:

* **Input delay**: The time between the user's action (a tap, click, or keypress) and the browser starting to run the event handler. This delay happens when the main thread is already busy executing other JavaScript. If a third-party script is running a long task when the user taps a button, then the browser can't start processing the tap until that task finishes.
* **Processing time**: The time to run the event handlers attached to the interaction. This includes your theme JavaScript, app JavaScript, and any framework code that fires in response to the event. Multiple handlers can fire for a single interaction, for example, `pointerdown`, `mousedown`, and `click`.
* **Presentation delay**: The time for the browser to recalculate styles, perform layout, composite layers, and paint the visual update to the screen. Large DOM changes, expensive CSS recalculations, and forced synchronous layouts all increase this phase.

The total of all three phases is the interaction's latency. INP reports the worst (or near-worst) interaction latency from the page visit. A visit ends when the page is unloaded or discarded, and the value resets when a page is restored from the back/forward cache, so a restored page reports its own separate INP.

***

## How

### Step 1: Identify slow interactions in field data

Check your store's field data (CrUX or RUM) to see which pages have poor INP. Field data reflects real user interactions across many devices, including slower phones that might not show issues in your development environment.

If you have RUM data, then identify the specific interactions that are slow. Common slow interactions on Shopify stores include variant selection, cart drawer open/close, mega menu expansion, search input, and filter application on collection pages.

### Step 2: Reduce Java​Script execution

Before deep debugging, reduce the total amount of JavaScript running on the page. This lowers the baseline main-thread contention that causes input delay.

Use [Finding your worst JavaScript offenders](https://shopify.dev/docs/storefronts/themes/best-practices/performance/finding-worst-offenders) as a detailed guide:

1. Audit all installed apps.
2. Remove apps no longer used.
3. Check if "removed" apps still inject code into the theme.
4. Evaluate remaining apps: weigh performance cost against feature value.
5. Look for duplicate functionality across apps.

### Step 3: Profile specific interactions

Open Chrome DevTools and go to the **Performance** panel:

1. Click **Record**, or press Ctrl+E (Windows) or Cmd+E (macOS).
2. Perform the slow interaction, for example, clicking a variant selector.
3. Stop recording.
4. Look at the **Main** track for long tasks, which are marked with red corners.
5. Click the long task to see which functions are running during the interaction.

In the **Summary** tab at the bottom, note the breakdown of scripting time, rendering time, and painting time. This tells you which of the three INP phases is dominant.

### Step 4: Fix common Shopify-specific INP problems

#### Variant selector reflows

When a user selects a variant, theme JavaScript often updates the price, availability, images, and **Add to Cart** button text simultaneously. Each DOM update can trigger style recalculation and layout. Batch DOM reads and writes together to avoid forced synchronous layouts. Use `requestAnimationFrame` to defer visual updates to the next frame.

#### Cart drawer animations

Opening or closing a cart drawer that animates with properties like `width`, `height`, or `top` triggers layout on every frame. Use `transform: translateX()` instead for GPU-accelerated animation that doesn't block the main thread. See [Use `transform` for animations](https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-transform-for-animations).

#### Mega menu hover states

Complex mega menus that render large amounts of DOM on hover can cause long presentation delays. If the menu content is already in the DOM but hidden, then toggling visibility is much faster than inserting new elements.

#### Third-party scripts during interactions

Analytics scripts that listen for click events and run synchronous code during the handler add processing time to every interaction. Audit which third-party scripts attach event listeners using the **Event Listeners** panel in DevTools. Select an element, then check the **Event Listeners** tab in the **Elements** panel.

#### Large stylesheet counts

Pages with hundreds of separate stylesheet links cause expensive style recalculations during interactions. See [Reduce stylesheet count](https://shopify.dev/docs/storefronts/themes/best-practices/performance/reduce-stylesheet-count).

***

## Examples

### Profiling a variant selection interaction

This walkthrough shows how to diagnose a slow variant selection using the Performance panel:

1. Open your product page in Chrome with DevTools open.
2. Go to the **Performance** panel. Enable **Screenshots** for visual context.
3. Click **Record**.
4. Click a variant swatch, for example, changing the color from Black to Red.
5. Wait one second, then click **Stop**.

In the recording:

* Find the click event in the **Interactions** track. It shows the total interaction latency.

* Below it in the **Main** track, you can see the breakdown:

  * **Input delay**: Any long task that was already running when you clicked. This appears as scripting activity before the event handler starts.
  * **Processing time**: The event handler and any JavaScript it triggers. Look for functions in the call stack that belong to theme code, app code, or analytics.
  * **Presentation delay**: `Recalculate Style`, `Layout`, `Paint`, and `Composite Layers` entries after the JavaScript finishes.

If input delay is the largest phase, then the problem is other JavaScript blocking the main thread. Focus on reducing third-party scripts.

If processing time dominates, then the event handler itself is doing too much work. Look at the call stack to identify which functions are slow.

If presentation delay is the largest, then the DOM update is triggering expensive layout work. Check for forced synchronous layouts (the Performance panel highlights these with a red triangle) or large numbers of style recalculations.

### TBT as a lab proxy

[Total Blocking Time (TBT)](https://web.dev/tbt/) from a lab test correlates with INP. TBT measures only main-thread blocking during page load, not post-load interactions, but it's a useful indicator. If you measure 800 ms of TBT during page load and later find poor INP in field data, then reducing the main-thread work identified during page load likely improves post-load INP as well.

**Note:**

Lighthouse can't measure INP across a real page visit. Field testing with real users is required. TBT is a useful lab proxy but not a replacement for field data.

***

## Testing

* Check your store's [CrUX data](https://developer.chrome.com/docs/crux/) for field INP values. The [PageSpeed Insights](https://pagespeed.web.dev/) tool shows CrUX data at the top of the report.
* Use the **Performance** panel in Chrome DevTools to record specific interactions. Look for long tasks in the **Main** track and check the **Interactions** track for total latency.
* Use the **Performance Monitor** (**More tools** > **Performance Monitor**) for a live view of CPU usage, DOM node count, and style recalculations per second while interacting with the page.
* Use the [Web Vitals Chrome extension](https://chrome.google.com/webstore/detail/web-vitals/ahfhijdlegdabablpippeagghigmibma) to see INP in real time as you interact with the page. It shows the current worst interaction and which element triggered it.
* Test on a throttled CPU (**Performance** panel > gear icon > **CPU throttling: 4x slowdown**) to simulate slower devices that your customers might use.

***

## References

* [Announcing INP as the next Core Web Vital: What Shopify stores can do now](https://performance.shopify.com/blogs/blog/announcing-inp-as-the-next-core-web-vital-what-shopify-stores-can-do-now)
* [3 ways to find your worst JavaScript offenders for page load](https://performance.shopify.com/blogs/blog/3-ways-to-find-your-worst-javascript-offenders-for-page-load)
* [Audit and remove third-party scripts](https://shopify.dev/docs/storefronts/themes/best-practices/performance/audit-remove-third-party-scripts)
* [Finding your worst JavaScript offenders](https://shopify.dev/docs/storefronts/themes/best-practices/performance/finding-worst-offenders)
* [Use `transform` for animations](https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-transform-for-animations)
* [Debounce and throttle event handlers](https://shopify.dev/docs/storefronts/themes/best-practices/performance/debounce-throttle-event-handlers)
* [Reduce stylesheet count](https://shopify.dev/docs/storefronts/themes/best-practices/performance/reduce-stylesheet-count)
* [INP on web.dev](https://web.dev/inp/)

***
