Skip to main content

INP Case Study

This case study deconstructs an Interaction to Next Paint (INP) bottleneck on a WooCommerce storefront, where a 650ms delay correlated with higher cart abandonment. While LCP controls how quickly a site appears, INP controls how responsive it feels during interactions. We'll reduce main-thread congestion and improve backend responsiveness for interactive actions.

Quick Summary

A 650ms INP was delaying "Add to Cart" feedback. The main causes were main-thread JavaScript congestion (third-party scripts) and slow backend processing for AJAX. Adding Redis object caching and delaying non-essential scripts reduced INP to 180ms.

The Scenario

DetailValue
Site typeWooCommerce (1,500 active products)
ProblemTapping "Add to Cart" triggers a 2–3 second visually frozen delay
Initial INP650ms (Poor)
Initial LCP2.2s (Good)
Initial CLS0.07 (Good)
User impactCart abandonment rate skyrocketed from 22% to 35%

Visible Symptoms

  • Users click "Add to Cart" on mobile, but the UI provides zero visual feedback for up to 3 seconds.
  • Checkout form fields (like email inputs) respond sluggishly to rapid keystrokes.
  • Low-powered mobile processors experience exponentially worse delays than high-end desktop hardware.

Step-by-Step Diagnosis

Step 1: Run PageSpeed Insights

psi-results.txt
PSI Results (Mobile):
LCP: 2.2s (Good)
CLS: 0.07 (Good)
INP: 650ms (Poor)

Because LCP is entirely healthy, we know the server is feeding the initial render rapidly. The exclusive failure is INP, isolating the problem entirely to JavaScript execution and subsequent client-side interactivity.

Step 2: Profile CPU Interactions in DevTools

Using the Chrome DevTools Performance tab, we click Record, physically tap the "Add to Cart" button, and stop the recording.

Findings:

  • A massive cluster of Long Tasks (> 200ms) from WooCommerce cart fragments and Elementor UI events.
  • The background POST request to /wc-ajax=add_to_cart stalls for ~1.2s.
  • Third-party widgets compete for CPU time during interactions.

Step 3: Identify Main-Thread Blockers

thread-analysis.txt
Identified Long Tasks:
1. elementor-frontend.min.js → 320ms penalty
2. wc-cart-fragments.min.js → 180ms penalty
3. gtag (Google Analytics) → 150ms penalty
4. chat-widget.js → 120ms penalty

Total blocking delay during a single click: ~770ms

Solution: Layer-by-Layer Fixes

LayerBottleneckFix AppliedExpected Impact
ServerSlow backend AJAX processingIncrease PHP-FPM workers where appropriate; confirm OPcache is enabledFaster AJAX responses
CacheRepeated dynamic queriesEnable Redis object cacheReduced repeated DB work
FrontendHeavy marketing JS overwhelming the CPUDelay analytics, chat widgets, and uncritical scripts using PerfmattersMain thread effectively freed
DesignSwollen, overloaded DOMRip out unneeded recommendation sliders below the cart UIFaster script traversal speed

Executing the Sequence

resolution-metrics.txt
1. Enable Redis Object Cache:
The backend AJAX response improves from ~1.2s → ~0.4s by reducing repeated database work.

1b. Tune PHP execution (OPcache + PHP-FPM):
The backend AJAX response improves further from ~0.4s → ~0.15s.

2. Delay non-critical JavaScript (Perfmatters):
Push execution of analytics and chat widgets until user hover/scroll.
Main-thread total block drops from 770ms → 180ms.

3. Simplify the product DOM:
Eliminate hidden off-canvas menus and heavy slider configurations.
Total DOM complexity shrinks from 2,800 → 1,400 raw elements.

Final Verified State: INP = 180ms

Common Mistakes in INP Diagnosis

MistakeExplanationSolution
Only measuring initial page load timeINP specifically measures the friction that occurs after the page finishes visually loading.Profile real-world button clicks, mobile taps, and keystrokes independently.
Deferring checkout payment scriptsDeferring Stripe or PayPal scripts carelessly will permanently break checkout processing.Exclude payment gateway URLs entirely from any global JavaScript delay logic.
Relying only on lab resultsFast devices can hide main-thread problems that show up on mid-range phones.Validate on throttled/mobile profiles and confirm with field data (CrUX/Search Console).
Stacking marketing widgetsEach additional script can add long tasks and event-handler overhead.Remove redundant scripts and delay non-essential tags where safe.

Hands-On Practice

Profile Your Own Checkout Interaction

Task: Pull up DevTools Performance panel on your live site, start recording, tap your heaviest interactive button (Search, Add to Cart), and stop. Document the red "Long Tasks."

interaction-audit.txt
Number of Long Tasks: ____
Total Blocking Time: ____ms
Slowest Script Traced: _______________

Task: Navigate to your optimization plugin and write a delay rule explicitly targeting your heaviest third-party script (e.g., your chat widget or marketing tracker). Re-run the diagnostic to verify the CPU was freed.

Results Summary

MetricBeforeAfterChange Improvement
INP650ms180ms−72%
Backend AJAX Response1.2s0.15s−88%
Main-Thread Blocking Load770ms180ms−77%
DOM Element Count2,8001,400−50%
Cart Abandonment Rate35%24%−11 points Recovery
Conclusion

By reducing repeated backend work (object caching) and lowering main-thread contention (delaying non-essential scripts), interaction latency improved and the checkout flow became more responsive.

What's Next