Before you change a single thing, measure the right number. Almost every store we are asked to speed up has already had someone chase a lab score, and the lab score is not what Google uses or what your shoppers experience.
The short version of the diagnosis order: get field data at the 75th percentile, break LCP into its four sub-parts, and fix whichever sub-part is over budget. For most stores that means images first, third-party JavaScript second, server location third — not the other way round, which is how it usually gets done.
What are the current Core Web Vitals, and what changed?
If your reference point is a few years old, one of the three metrics no longer exists. First Input Delay was replaced by Interaction to Next Paint: web.dev announced that INP would officially become a Core Web Vital on 12 March 2024, and Chrome subsequently ended support for FID entirely, with the metric dropped from the CrUX BigQuery schema from the 202409 dataset onward.
The current set, with Google's own thresholds:
| Metric | What it measures | Good | Poor |
|---|---|---|---|
| Largest Contentful Paint (LCP) | Loading | 2.5 seconds or less | — |
| Interaction to Next Paint (INP) | Responsiveness | 200 ms or less | above 500 ms |
| Cumulative Layout Shift (CLS) | Visual stability | 0.1 or less | — |
Sources: Web Vitals and Interaction to Next Paint. INP's middle band is above 200 ms up to 500 ms.
Two details on that table matter more than the numbers themselves. First, Google's guidance is to measure at the 75th percentile of page loads, segmented by mobile and desktop. Your median shopper is not the one you are being judged on; the one at the 75th percentile is, and on an Indian mobile network that is a meaningfully different person. Second, Time to First Byte and First Contentful Paint are diagnostic metrics, not scored ones — Shopify's own performance documentation says so plainly. They are useful for finding the problem, not for reporting on it.
The practical implication: look at field data in Search Console or the field section of PageSpeed Insights before you look at a Lighthouse run. If the field data says you are passing and Lighthouse says 48, you have a Lighthouse problem, which is a different and much less urgent thing.
How do I tell a server problem from an image problem?
This is the single most useful diagnostic step and almost nobody does it. LCP breaks into four sub-parts, and Google publishes a recommended budget for each:
| LCP sub-part | Share of total LCP |
|---|---|
| Time to First Byte | roughly 40% |
| Resource load delay | under 10% |
| Resource load duration | roughly 40% |
| Element render delay | under 10% |
Split your actual LCP against that and the answer falls out:
- TTFB is eating most of it. That is a server, redirect or caching problem. Go to the next section.
- Resource load duration is eating most of it. Your LCP image is too heavy. This is the most common case by a wide margin on Indian D2C stores, and it is the cheapest to fix.
- Resource load delay is high. The browser found out about the image late — it is behind a CSS background, injected by JavaScript, or buried in a carousel. Shopify's documentation is specific here: mark the LCP image with
fetchpriority="high", never lazy-load it, and avoid using a CSS background image for hero content. - Element render delay is high. Something is blocking rendering after the image has arrived — usually a font, a render-blocking stylesheet, or an A/B testing anti-flicker snippet left behind by a test that ended months ago.
If your hero image is over a couple of hundred kilobytes on mobile, it is almost certainly not being resized per breakpoint. On Shopify, the image_tag and image_url filters handle srcset, dimensions and CDN delivery; on WooCommerce you want modern formats generated at upload. Google's guidance on image formats is that WebP and AVIF "will generally provide better compression than older formats, and should be used where possible" — it publishes no headline percentage saving, and neither should anyone quoting one at you.
Why is a store slow for shoppers in India specifically?
Two reasons, and they are different problems.
Distance is latency, and latency is arithmetic. A new HTTPS connection costs at least three round trips before the first byte of HTML arrives: DNS, then the TCP handshake, then TLS. TTFB's own components, per Google, are redirect time, service worker startup, DNS lookup, connection and TLS negotiation, and the request itself. If your origin sits in a US or European region and your shopper's round trip to it is 200 ms, you have spent around 0.6 seconds on geography before your server has done any work — against a TTFB budget where 0.8 seconds is the threshold for good and 1.8 seconds is poor. Measure your own round trip rather than assuming that figure, but the shape of the problem does not change.
Google also names the two aggravating factors directly: visitors arriving through multiple redirects, and content that cannot be served from a CDN edge server. An http to https to www to apex redirect chain — very common on Indian stores that changed domains or added SSL after launch — is pure added TTFB on every cold visit.
Edge coverage in India is better than most people assume, so not using it is the mistake. Cloudflare's network page lists 348 cities, 22 of them in India, from Mumbai, Delhi, Chennai, Hyderabad and Bangalore down to Sambalpur and Kannur. If your HTML is cacheable and you sit behind a CDN with that footprint, your shopper in Coimbatore is not waiting on your origin at all. If your HTML is not cacheable, the edge gives you nothing on the document — it speeds up your logo and nothing else.
On Shopify you do not get to choose where the origin is, and you largely do not need to — Shopify's CDN is Cloudflare-backed and assets are served from the edge without configuration. On WooCommerce you do choose, and the choice is straightforward: put the origin in an Indian region if your traffic is Indian, put a full-page cache in front of it, and make sure the cache actually hits. Then confirm you are on WooCommerce's current requirements — PHP 8.3 or newer, MySQL 8.0 or MariaDB 10.6 or newer, a 256MB memory limit — because an underfed PHP process is a slow one regardless of where it sits.
What do apps and plugins actually cost?
More than their vendors say, and you have to measure it per store.
Shopify publishes the methodology it expects app developers to use, and you can run it yourself: install the app, then run Lighthouse on home, product and collection pages before and after, weighting the result 17% home, 40% product, 43% collection. Shopify's own example shows an app taking a store from 92 to 87. There is no published pass mark — apps must only "consistently demonstrate low or no negative impact" — which tells you Shopify knows this is a judgement call.
The mechanism applies equally to WooCommerce plugins. Shopify's performance docs state that scripts run on the main thread and are a primary cause of poor INP and delayed LCP. INP itself is made of input delay, processing time and presentation delay, and long main-thread tasks inflate the first of those. Every review widget, chat launcher, popup builder, upsell app and pixel competes for the thread your Add to Cart button needs.
So audit every script on a product page and delete whatever cannot justify itself — Shopify's docs say exactly that, including tracking pixels and theme code — and prefer app embed blocks that load only on the pages that need them. The chat widget does not need to be on the collection page.
On WooCommerce the equivalent structural fix is High-Performance Order Storage, which moves orders into dedicated tables instead of the shared WordPress posts tables. Default for new installs since WooCommerce 8.2 — but existing stores are not migrated automatically, so a store built in 2022 is probably still on the old storage and nobody has mentioned it.
What about layout shift?
CLS on e-commerce stores is almost always one of three things: images without width and height attributes, fonts swapping late, or app content injected after first paint.
The third is the one people miss. Shopify's documentation recommends reserving space for app-injected content using App Blocks and a min-height, which is a neat admission that apps will shift your layout unless you pre-empt them. For fonts, the guidance is to self-host on the CDN or use system fonts, with size-adjust and fallback overrides so the swap does not move anything.
CLS is also the cheapest of the three to fix properly, and the most likely to stay fixed, because dimensions on an image do not regress when someone installs a new app.
So what order do I fix things in?
| Step | What you do | Why it is here |
|---|---|---|
| 1 | Pull field data at the 75th percentile, mobile and desktop separately | Stops you optimising something that is already passing |
| 2 | Split LCP into its four sub-parts | Tells you whether this is a server problem or an image problem |
| 3 | Fix the LCP image: correct size per breakpoint, modern format, fetchpriority="high", never lazy-loaded |
Biggest win per hour on most Indian stores |
| 4 | Kill redirect chains and confirm HTML is cacheable at the edge | Directly reduces TTFB, which is around 40% of your LCP budget |
| 5 | Audit third-party scripts on the product page and delete or defer | The main lever on INP |
| 6 | Reserve space for injected content, set image dimensions, sort out fonts | Fixes CLS and tends to stay fixed |
| 7 | Only now consider hosting tiers, Liquid micro-optimisation or a rebuild | Real but small by comparison |
Step 7 is not a dismissal. Shopify's docs note that compounding Liquid optimisations can save 25 to 50 ms of TTFB on complex themes, which is real — just the wrong place to start when a hero image is costing you two seconds.
What is usually a waste of time?
Chasing a Lighthouse 100. It is a throttled lab simulation. Shopify's Theme Store minimum is an average Lighthouse performance score of 60 across home, product and collection pages, which should tell you how much headroom the people who build themes professionally consider necessary.
Installing a speed optimisation app. Shopify's own performance documentation warns about "fake performance apps that game Lighthouse or PageSpeed tests" — which is a remarkable thing for a platform to have to write about its own app store. An app that improves a score without reducing bytes or main-thread work has improved nothing.
Putting a second CDN in front of Shopify. Shopify's documentation is explicit that request proxies add a network hop between the browser and Shopify, increasing latency for every resource. It also notes that Cloudflare headers on a Shopify response do not prove a proxy is present, because Shopify's CDN is Cloudflare-backed — so people "confirm" their setup is working by reading headers that were always going to be there. The highest-risk features are script rewriting, which can break module loading and delay interactivity, and proxy caching, which can serve stale prices and inventory. If you cannot remove a proxy that is in place for WAF reasons, Shopify's advice is to proxy only HTML document requests and keep the HTML cache TTL at five minutes or less.
Preloading everything. Shopify's guidance is to reserve preload for one or two resources the browser would discover late. Preloading twelve things is a queue, not a priority.
Minifying CSS while a 1.8MB JPEG is still being served. Order of magnitude matters. The same goes in reverse: do not change hosts before checking whether your HTML is cacheable, because a faster origin you still hit every time is worth less than not hitting it at all.
When does none of this help?
If your product pages render their content client-side from JavaScript, you are not tuning a slow store — you are tuning the wrong architecture, and each fix above buys a hundred milliseconds of a problem that is seconds deep. Shopify's own advice is to render essential content in Liquid and HTML rather than client-side, and the equivalent holds anywhere. If your catalogue pagination is enormous, the same applies: Shopify suggests keeping it under 25,000 objects, and past a certain size the answer is a different browse architecture, not a faster one.
And if the real complaint is conversion rather than speed, say so before spending the budget. Speed is one conversion input. Stores pass all three Core Web Vitals and still convert badly because the photography is poor and the shipping cost appears at step four of checkout.
Where to start this week
Open PageSpeed Insights, look only at the field data section, note your LCP sub-part split, and resize whichever image is your LCP element. That is one afternoon, and usually the largest single improvement available.
If the field data points at TTFB rather than images, the conversation is about architecture and hosting, which is where our ecommerce development work usually starts — and whether the store runs on Shopify or WooCommerce changes the fixes available, not the diagnosis order. If a rebuild looks likely, our current cost ranges for India are kept updated.
Send us your store URL and we will tell you which of the seven steps above applies to you, including the common case where the answer is one image and no invoice.
Bharat Vasireddy
Founder & Digital Marketing Strategist8+ years of experience in performance marketing and web development. I help businesses scale through data-driven SEO, Google Ads, and high-performance websites.
