info

Affiliate Disclosure: This article contains benchmarked tools that may compensate us. We only recommend hardware and software tested in our lab environments for maximum LCP and INP efficiency.

Solving Interaction to Next Paint (INP) at Scale

INP is the new standard for responsiveness. Here is a step-by-step guide to profiling and fixing JavaScript execution bottlenecks.

calendar_today folder

INP: The Core Web Vital That Replaced FID in 2024

Interaction to Next Paint (INP) replaced First Input Delay (FID) as a Core Web Vital in March 2024. While FID measured only the first user interaction delay, INP measures the worst interaction delay throughout the entire page session — clicks, keyboard events, and taps. Google’s threshold: under 200ms is “Good,” 200–500ms is “Needs Improvement,” above 500ms is “Poor.”

INP is harder to optimize than LCP because it measures JavaScript responsiveness during user interaction — deeply influenced by how much work the main thread is doing. A page that loads quickly can still fail INP if JavaScript blocks the main thread for 300ms when a user clicks a button.

The Main Thread Is the Bottleneck

Every JavaScript operation runs on a single main thread. When busy — running scripts, processing style calculations, executing layout — the thread cannot respond to user interactions. Common main thread blockers on WordPress sites: large JavaScript bundles from page builders (Elementor, Divi), third-party scripts (Google Tag Manager, analytics, chat widgets), and inefficient event listeners doing heavy DOM manipulation on every interaction.

Fix 1: Break Up Long Tasks

// Yield to the browser between operations to allow interaction processing
async function processLargeDataset(items) {
    for (const item of items) {
        expensiveOperation(item);
        if ('scheduler' in self) {
            await scheduler.yield(); // Modern browsers
        } else {
            await new Promise(resolve => setTimeout(resolve, 0)); // Fallback
        }
    }
}

Fix 2: Defer Third-Party Scripts Until User Interacts

// Load GTM only after first user interaction
let gtmLoaded = false;
function loadGTM() {
    if (gtmLoaded) return;
    gtmLoaded = true;
    // Standard GTM snippet
}
['click', 'scroll', 'keydown'].forEach(event =>
    document.addEventListener(event, loadGTM, { once: true, passive: true })
);

Fix 3: Optimize WooCommerce Interaction Handlers

  • Quantity changes: Debounce with 300ms delay to avoid recalculating on every keypress
  • Add-to-cart: Use CSS transitions and pre-built templates rather than full DOM replacement
  • Variation selection: Batch DOM updates into a single requestAnimationFrame callback

INP Budget Breakdown

INP ComponentBudget (200ms total)Description
Input Delay< 50msTime from interaction to event processing start
Processing Time< 100msTime for event handlers to execute
Presentation Delay< 50msTime for browser to paint the next frame

FAQ

What is a good INP score for WordPress?

Under 200ms is “Good.” Most well-optimized WordPress sites without heavy page builders achieve 80–150ms INP. Sites using Elementor, Divi, or heavy WooCommerce filtering can struggle to reach 200ms without explicit main thread optimization.