Hey folks,
We’re investigating some slow LCP scores for pages that should be our fastest. We’ve identified a potential issue with how web vitals are calculated when navigating through a React Router app: The LCP calculation continues across page changes.
Environment details
react-router@7.12.0@shopify/shopify-app-react-router@1.1.0@shopify-api@v12.1.2- App Bridge and Polaris web components loaded via
@shopify/shopify-app-react-router - Embedded application
The issue
100% of high LCP values (>5s) are being captured AFTER navigation, indicated by:
- Missing FCP data: All 5 events with LCP >5s have
nullFCP (First Contentful Paint) - Quick navigation: Web vitals events are followed by pageview events within 578-4,319 milliseconds
- Pattern breakdown:
- High LCP (>5s): 100% missing FCP → post-navigation captures
- Medium LCP (2-5s): 40% missing FCP → some post-navigation
- Good LCP (<2s): 28.2% missing FCP → mostly accurate
This data is collected through 3rd party tools (Sentry and Posthog), so there is a discrepancy with how Shopify is collecting the data.
What’s happening
Looking at the worst case (22,055ms LCP):
- Web vitals captured at
15:04:41.596 - User navigated to
/app/feedsat15:04:42.174(578ms later) - Then to
/app/media,/app, and more pages within seconds
The LCP timer kept running in the background and reported 22 seconds - but the user had already moved on. They’re rapidly navigating through the app, which is actually good user behavior, not friction. The LCP calculation stops once they land on a page with a large image.
The real performance
The 39 events with good LCP (<2s) shows the actual page performance, with an LCP of 823ms. This aligns with local testing experience, where if we wait long enough before clicking on a page change, we get the accurate value. If we click fast enough on a link, we see the LCP keep counting.
If you have encountered this problem and solved it, I’d love to hear it. We’ve tried manually sending out pagehide and pageshow events when the page changes, but that doesn’t trigger the LCP to reset.