A Shopify Plus client we worked with this summer had a Largest Contentful Paint of 4.8 seconds on mobile. Their previous agency had told them this was a ‘Shopify limitation’ that could not be fixed without migrating off the platform. Six weeks later the same store ships LCP at 1.9 seconds on the same device. Nothing about Shopify changed. The story ‘Shopify is slow’ was wrong.
LCP on Shopify Plus is fixable. The fix is rarely where the merchant expects. Here is the playbook we use on these audits, with the actual line items from the engagement above.
The starting baseline
The home page LCP on the client’s store was 4.8 seconds at the 75th percentile on mobile, measured through real user monitoring across two weeks. The LCP element was the hero image — a full-bleed 1920×900 product shot, served as a 280-kilobyte JPEG from Shopify’s image CDN.
The product page LCP was 4.1 seconds, also against a hero product image.
The collection page LCP was 3.8 seconds, against the first product card image in the grid.
The pattern was consistent. The LCP element was an image on every template. The image was being served at a reasonable size and weight. The slowness was upstream of the image itself.
What was actually slow
The Performance panel told the real story. The page had 380 kilobytes of JavaScript loading synchronously in the head. The scripts ran in this order:
- Google Tag Manager (52 kilobytes)
- Klaviyo tracker (94 kilobytes)
- Yotpo reviews loader (61 kilobytes)
- A wishlist app (43 kilobytes)
- A back-in-stock app (38 kilobytes)
- The theme’s main script bundle (87 kilobytes)
All six of these blocked the main thread for a cumulative 1.4 seconds on a mid-range Android phone. The browser could not start rendering the hero image until the JavaScript had parsed and executed. Even though the image bytes were available, the LCP timer kept ticking.
The fix, by line item
1. Hero image preload. The single highest-impact change. Adding a <link rel="preload" href="hero.jpg" as="image" imagesrcset="..." imagesizes="100vw"> to the head, computed dynamically per template. The hero image starts downloading the moment the HTML hits the browser, not after the JavaScript parses. LCP dropped from 4.8s to 3.4s on this change alone.
2. Hero image format and size. The 280-kilobyte JPEG dropped to 92 kilobytes as WebP, served through the Shopify image CDN with the correct image_url filter parameters. We also generated a 720-pixel-wide version for mobile and used srcset to pick the right one. LCP dropped from 3.4s to 2.8s.
3. Defer non-critical apps. Three of the apps in the script list (Yotpo reviews, the wishlist, and the back-in-stock) were not interacting with the LCP element. Moved them to a deferred load that fires after the page is interactive, using the standard defer attribute and an event listener for the load event. LCP dropped from 2.8s to 2.3s.
4. Move analytics to a delayed load. Google Tag Manager and Klaviyo were loaded eagerly. Both can be loaded after the first paint without losing meaningful tracking accuracy. We wired up a delayed load that triggers either after 3 seconds or on the first user interaction, whichever is first. LCP dropped from 2.3s to 2.0s.
5. Inline the critical CSS. The theme’s stylesheet was 78 kilobytes loaded as a render-blocking link tag. We extracted the above-the-fold CSS — about 7 kilobytes — and inlined it. The rest of the stylesheet now loads asynchronously. LCP dropped from 2.0s to 1.9s.
6. Drop one unused app. The store had a quote-request app installed that was used on three pages out of a thousand. The app’s script was loaded on every page. We restricted the app to its three pages. The home page lost 38 kilobytes of JavaScript. LCP held at 1.9s (the home page LCP was no longer image-limited; further wins would have to come from elsewhere).
The audit pattern
The six items above are not specific to this store. They are the same six items we recommend on almost every Shopify Plus LCP audit. The fixes are not exotic. They are good defaults that most Shopify themes do not apply by default.
The reason most Shopify Plus stores ship slow is not the platform. It is the accumulated weight of theme installation, app installation, and tracking installation that nobody has audited since launch. Each app feels small at install time. Three years in, the stack is 400 kilobytes of synchronous JavaScript and nobody remembers why.
What we do not touch
We do not generally recommend migrating off Shopify Plus to fix LCP. The platform is fast enough when used carefully. The migration cost (months, six figures) does not pay back against the fix cost (weeks, low five figures) for the LCP problem.
We also do not recommend going headless for LCP specifically. A headless Shopify front end on Hydrogen or Next.js will be faster than a Liquid theme on the same content, but the gain (typically 400 to 800 milliseconds of LCP) is smaller than the gain from fixing the Liquid theme well (typically 1.5 to 3 seconds). The right order is: fix the Liquid theme, measure, then decide whether headless is worth the additional engineering.
The number to chase
The Core Web Vitals ‘good’ threshold for LCP is 2.5 seconds at the 75th percentile. Most Shopify Plus stores we audit start between 3.5 and 5.5. With the playbook above, the target landing zone is 1.8 to 2.4 seconds. That is achievable on the platform, without exotic engineering, on a typical merchant theme. It is the audit we run on every Shopify Plus engagement before we agree to anything more ambitious.