If your Core Web Vitals report in Search Console still says "Poor" three weeks after a speed engagement, the likely reason is that someone optimised the wrong device. Shopify speed optimization that starts with a desktop Lighthouse run will produce a green number and a store that still takes four seconds to paint on a Redmi Note over a congested Jio cell in Ghaziabad at 8pm. Those are the sessions Google measures. That is also where most of your revenue comes from.
The target is a 75th-percentile Largest Contentful Paint under 2.5 seconds on mobile, measured from real visitors, not from a lab. For an Indian D2C store that usually means the hero image on your homepage and the first product image on a PDP have to be decoded and painted before anything else competes for bandwidth. Everything below is about getting there without ripping out your theme or breaking the Razorpay and COD logic you spent months getting right.
Why your Shopify store is slow on mobile when it looks fine on your laptop
Open your store on your own phone, on office WiFi, with the page already in cache. It feels quick. Now consider what a real session looks like: a mid-range Android with a two-year-old chipset, 4G that is nominally fast but shares a tower with a few thousand other people during the evening peak, and a browser that has never seen your domain before.
Three things go wrong on that device that never go wrong on yours.
First, JavaScript execution. A desktop CPU chews through 400KB of app scripts in a couple of hundred milliseconds. A budget Android takes three to five times longer on the same bundle, and it does that work on the main thread, which is the same thread that has to lay out and paint your hero image. This is why stores with a dozen apps installed have a poor Interaction to Next Paint even when the images are perfectly sized.
Second, network round trips. Every third-party script is a DNS lookup, a TLS handshake and a fetch. On a lossy mobile connection each of those costs 150-400ms before a single byte of useful content arrives. Ten apps, ten sets of round trips, some of them chained.
Third, image weight. A 1600px hero at 380KB is fine on fibre. On a 3Mbps effective connection that is roughly one second of download time on its own, before the browser has even started decoding.
Lighthouse score versus what real users experience
Lighthouse is a lab test. It runs one simulated device, one simulated network, one cold load, on whatever machine happens to be running it. Chrome User Experience Report data, which is what Search Console shows you and what Google actually uses, is 28 days of real Chrome sessions from real people on real connections.
They disagree constantly. We have seen a store report 68 in Lighthouse mobile and pass Core Web Vitals in the field, and another report 84 and fail. The reasons are boring: the lab test doesn't know that 60% of your traffic lands on a Meta ad URL with UTM parameters that bust the cache, or that your PDP hero is a different asset on the templates people actually visit, or that half your sessions come from tier-2 cities where median throughput is well below what Lighthouse simulates.
So the rule we work to: use Lighthouse for diagnosis, use field data for the pass/fail decision. If someone shows you a before-and-after slide with only Lighthouse numbers on it, ask for the Search Console field report for the same period. If the 75th-percentile LCP hasn't moved, nothing has moved.
The LCP element is almost always an image, and almost always fixable
Run PageSpeed Insights on your homepage and your best-selling PDP, mobile tab, and look for the LCP element it names. On Indian D2C stores it is one of three things: a homepage hero banner, a PDP featured image, or occasionally a large H1 sitting inside a slideshow that renders late.
Here is a worked example from a fairly typical fashion store. Hero image served as a 2000px-wide JPEG at 412KB. Effective downlink on a throttled 4G session, call it 1.6Mbps after protocol overhead. 412KB is 3.3 megabits, which at 1.6Mbps is about 2.06 seconds of transfer alone. Add 0.4s for connection setup and server response, plus 0.25s to decode and paint on a slow CPU, and LCP lands around 2.7 seconds with everything else going perfectly. It never goes perfectly.
Resize the same hero to 1200px, serve it as WebP, and it comes down to roughly 95KB. That is 0.76 megabits, about 0.48 seconds of transfer. Same connection, same phone, LCP now lands near 1.2s. One change, 1.5 seconds saved, no theme surgery.
The specific fixes that do this work:
- Serve the hero at the size it actually renders. Shopify's image_url filter with a width parameter and a srcset does this properly; hardcoded img tags with a full-size source do not.
- Add fetchpriority="high" to the LCP image and remove loading="lazy" from it. Lazy-loading the hero is a mistake we find on maybe one theme in three, usually because someone applied a blanket lazy-load fix.
- Preload the hero with a link rel=preload in the head, especially when it sits inside a slideshow section that the browser discovers late.
- Kill the homepage slideshow if it has more than two slides. Every slide loads. Carousel click-through past slide one is dismal, and you're paying full download cost for the privilege.
App scripts: the part nobody wants to touch
This is where most of the remaining time hides, and it's the part that makes merchants nervous, because the scripts in question are the ones handling checkout and payments.
Be clear about the boundary. Your Razorpay, PayU or Cashfree checkout runs on Shopify's checkout pages, not your theme. Deferring or removing a storefront script does not touch it. What you can break is a COD order form app, an OTP verification widget, a pincode-serviceability checker or a WhatsApp button that some developer wired into the product template with an inline script. Those live on your pages and they do need testing after any change.
Our sequence, in order:
- Open the theme code and list every script tag that isn't Shopify's own. Then open Settings, Apps and sales channels, and list every installed app. Match them up. There are almost always orphan scripts from apps uninstalled months ago, still loading, still costing round trips.
- Check which apps have moved to Shopify's app embed system. Those you can toggle off per-template. A review widget that only matters on PDPs should not be loading on the cart page.
- Defer what can be deferred. Chat widgets, analytics beyond the primary pixel, exit-intent popups, loyalty widgets, currency switchers. None of these need to run before first paint. A simple approach: load them on first scroll or after a 2-second timeout, whichever comes first.
- Audit your pixels honestly. We routinely find Meta Pixel installed twice — once via the Shopify channel and once pasted into theme.liquid by a previous agency — plus GA4, Google Ads, a Clarity script and two attribution tools nobody has looked at since last Diwali.
Removing three dead apps and deferring four widgets typically pulls 600-900ms off Time to Interactive on a mid-range Android. It's unglamorous work. It also has the best ratio of hours spent to milliseconds saved of anything on this list.
Speed optimisation app versus manual theme fixes
Both, in a specific order. The honest split:
A good speed app handles the repetitive, mechanical work well. Image compression and format conversion across a 900-SKU catalogue, lazy-loading below-the-fold assets, minifying CSS and JS, adding preconnect hints, and — the underrated part — monitoring the score continuously so you find out when a newly installed app has cost you 400ms. Doing that by hand every month is a waste of a developer's time. Our own app, SwiftStore, scans a store's PageSpeed, applies what it can fix automatically and tracks the score over time, which covers exactly this layer.
What no app can do: decide that your homepage doesn't need a video background, restructure a section so the LCP element renders in the first HTML response instead of after a JavaScript hydration, remove an app you're paying for because a 40-line snippet does the same job, or rewrite a bloated collection template that renders 60 products server-side when 24 would do. Those are judgement calls on your specific theme.
The failure mode is buying an app, watching the score jump twelve points, and stopping. Twelve points on the lab score with an unchanged field LCP is not a result.
Free options, and where they stop being enough
If your budget is zero right now, there is real ground to cover before you spend anything.
Shopify's built-in Web Performance dashboard under Online Store gives you field LCP, CLS and INP split by page type. Free, and it's real user data. PageSpeed Insights gives you the CrUX field data plus a lab diagnosis. Also free. Chrome DevTools has a device emulation and network throttling mode — set it to a mid-tier mobile CPU throttle and Slow 4G, and you'll see what your customers see.
Then do the free work: compress and resize your top ten images, delete apps you no longer use, remove duplicate pixels, cut the slideshow to one slide, drop any custom web font you're loading for a single heading. Most stores can get 30-40% of the available improvement this way in an afternoon.
Free speed apps on the App Store exist and some of them do a reasonable job on image compression and minification. The limits show up on themes with heavy custom sections, on stores with several apps injecting scripts, and when the LCP element is buried in a JS-rendered section. At that point you need someone in the code.
What Shopify speed optimization costs in India
Rough bands, from what this work actually takes:
₹15,000 – ₹35,000. A focused pass on a standard Dawn-based or lightly customised theme. Image pipeline, lazy-loading, script deferral, dead app removal, font handling, preloads. Two to four days of developer time. This is the right spend for most small and mid-sized stores and it's where the majority of the LCP gain lives.
₹40,000 – ₹90,000. Heavily customised themes, page builder pages, stores with 15+ apps, or Hindi/regional-language variants. Includes template-level section rework, replacing apps with native code, and a proper before-and-after measured on field data over 28 days.
₹1,00,000+. Theme rebuild territory. Usually the honest answer when a store is on a five-year-old vintage theme that predates Online Store 2.0. Sinking money into optimising it is throwing good money after bad — you're better off rebuilding on a modern base, which fixes speed as a side effect and gets you sections everywhere. Our note on what Shopify development costs in India breaks the wider pricing down.
One thing worth saying plainly: if you're paying a monthly retainer for "speed optimisation" and nobody sends you a monthly field-data report, you're paying for a subscription, not a service.
Where speed actually shows up in the P&L
Not in an abstract conversion-rate lift. Two concrete places.
Meta and Google traffic is the first. Your ad click lands on a page that has to load twice — once for the browser, once through the in-app browser Instagram uses, which is slower. Every bounce before first paint is CPC you paid for and got nothing back. At a ₹18 CPC and 40,000 clicks a month, a 3-point drop in pre-render bounce is roughly 1,200 sessions retained, ₹21,600 of spend that now reaches a page instead of a blank screen.
The second is COD. Slow pages push people toward abandoning at the form, and the ones who do complete on a struggling page skew toward the impulsive end, which correlates with higher RTO. We can't put a clean number on that, and won't pretend to. But a pincode checker that takes four seconds to respond is a pincode checker people give up on, and every merchant running COD in tier-2 and tier-3 markets knows what that costs in refused deliveries.
Getting through the festive peak
Traffic multiplies between Navratri and Diwali, and the same weeks are when merchants add the most: countdown timers, sale badges, festive popups, gift-with-purchase logic, a spin-the-wheel. Each one is script weight, added at the worst possible moment.
Freeze the theme two weeks before your first big sale day. Run the speed check before the freeze, not after. If a festive app must go in, install it, measure the field data for a few days, and be prepared to pull it. Shopify's infrastructure will hold up under your traffic spike; your theme is the part that won't.
And check your collection pages specifically. Festive traffic lands on collections far more than on the homepage, and a collection template rendering 48 products with a heavy filter widget is a much slower page than your carefully tuned hero. If your catalogue is large enough that filtering matters, the filter app you choose has a real weight cost — worth checking before you commit.
A sensible order of work
If you're doing this yourself over the next week:
- Pull your current field LCP from Shopify's Web Performance dashboard. Write the number down. You need a baseline that isn't a lab score.
- Identify the LCP element on your homepage and your top-traffic PDP via PageSpeed Insights.
- Fix those two images: correct dimensions, WebP, fetchpriority high, no lazy-load, preload if it's discovered late.
- Delete every app you haven't consciously used in 60 days, then grep theme.liquid for leftover scripts.
- Defer the chat widget, popups and secondary analytics.
- Test checkout end to end. Real COD order, real UPI order, real card. Do not skip this.
- Wait 28 days. Check the field data again.
That last step is the one people skip. CrUX is a rolling 28-day window, so you will not see the improvement the next morning, and refreshing Search Console daily for a week will only make you miserable.
If you'd rather have someone else measure it properly, we run a free store audit that includes field Core Web Vitals split by template, a list of what's actually loading on your pages, and an honest read on whether you need four days of work or a new theme. If you already know it's the second, our speed work page covers what that engagement looks like.


