Resin Rock's Shopify store scores 91 to 95 on mobile PageSpeed on a good run, and 99 on desktop. It started at about 60, and it got there in four working days without going down or losing an order. Along the way I found a fault in Google's own PageSpeed machines that hits every Shopify store, not just this one, and reported it to Google and Shopify.
Resin Rock sells resin-bound surfacing to contractors, out of seven locations, on a big Shopify store: the Concept theme, over a hundred pages, 29 apps, Meta ads, and a few lead pipelines feeding into it. The brief was one line. Make it fast without breaking anything. Every number below is from the job itself.
The short version Four working days on a live store, no design change, every lead pipeline and ad pixel kept. Mobile PageSpeed went from about 60 to 91 to 95 on Google's servers, desktop to 99, and blocking time from four or five seconds to under a fifth of one. Most of that was pulling out apps and tags that were already dead, not rewriting the theme. Then the scores started flipping between 60 and 95 with nothing changed, and running that down turned up a hold in Google's test fleet that meets the code Shopify puts in every store. I reported it to Google and Shopify.

What Resin Rock asked for#
Speed, without a single thing breaking. It is a big company on a busy store, and the client said it straight: one broken thing costs a lot. So the rules came before the work. No downtime, no design change.
Three things had to keep working exactly as they were. The hero video. The "Welcome, how can we help?" popup that shows the moment a first-time visitor lands. And every automation feeding a pipeline, from Mailchimp for customers to Prospect365 for leads to the Meta pixel for ads.
The usual answer to a slow Shopify store is to install a speed app and let it minify and lazy-load on a preset. On a store like this, that is how you break a lead form or blank a pixel and not notice for a week. A preset does not know which of your 29 apps is holding something up and which is a leftover. So I did the opposite. Find what each piece actually does, then change only what is safe to change.
Why the theme was not the slow part#
I started from the outside, with Lighthouse and a few network traces, but that only tells you so much. Once I had real access to the theme files, the media library and the live list of pixels, the picture changed.
The theme itself was not the main cost. What had been bolted onto it was. Each page was carrying 84 to 111 scripts and 2.2 to 2.4 MB of JavaScript, and most of it was dead.
Four Google tag containers, each fetched twice, came to 1.19 MB. There were three GA4 properties on a site that used one. The Shopify Forms app loaded a 254 KB runtime on every page, and the store had no forms in it, the forms it used were the theme's own and Prospect365's. A Roomvo visualizer polled the page every 60 milliseconds, forever, for a feature whose buttons were all switched off.
The client's worry was the right one: pull an app and you might quietly kill a pixel or a lead form. So nothing came off on a hunch. I wrote out what every app and pixel fed, and the client's team removed only the ones that map showed were dead. Five apps and eight pixels went. The live pixel list dropped from 11 to 3, the three that matter: Mailchimp, Google and Facebook.
One thing stayed slow on purpose. Once the dead code was gone, the JavaScript a real browser still runs is the client's own Facebook and Google tags, about 1.9 seconds of it on a throttled phone. They run Meta ads and keep those tags, so a Lighthouse test on a laptop still shows that time. That is the ads, not the theme, and no theme work takes it away.
Then the media, which is where the phone bandwidth and the slow paint were. The hero video was serving its 1080p copy, 3 MB, to phones, even though Shopify had already made 480p and 720p versions on upload. A training page autoplayed a 16.9 MB video on mobile. The projects gallery threw out 32 full-size photos with no width set, 27.8 MB on one page. A 9.6 MB PDF manual loaded into an iframe the second its page opened.
Four days on a live store, in order#
The store was taking orders the whole time, so nothing was edited live. I pulled the theme into git and worked on a duplicate, and checked every push against Shopify's API, because one push reported success without actually uploading anything.
After each change I loaded the main templates on a real phone and a real desktop, watching for script errors and broken images. There were none, start to finish. And every score came from Google's own servers, run in batches, never a single lucky pass.
The work went in three passes. The apps and pixels came off first, in the admin. Then the media. Shopify's Liquid only ever hands you the top video rendition, so I built a lookup from the Files API that mapped each video to its smaller copies. The player now picks by screen width, and holds autoplay for reduced-motion and data-saver visitors. The hero dropped from 3.1 MB to about 1 MB on phones.
Images were the rest of it. Product cards got a real sizes attribute, so a phone stops pulling a 1080-pixel image into a 200-pixel slot, and a collection page fell from 5.2 MB to 1.0 MB. The projects gallery went properly lazy, near zero before a scroll. The PDF now loads on a click, and its page went from 13.9 MB to 0.7 MB.
The last pass was first paint. I preloaded the largest image so it starts before the HTML is even parsed. And I took out a full-screen overlay the theme drew over everything until its script ran and then faded for a second, which on its own was costing about two seconds of first paint on every page.
The popup was the last piece. The theme built it with JavaScript after everything else, so it jumped on top of the page once it loaded, and that jump was the layout shift real users were getting. I moved it to render first, as the very first thing in the body. It still shows straight away, which is what the client wanted, and the content behind it no longer drags the score.
The scores that would not hold still#
With the work done, the scores started lying. The same page, nothing changed, scored 91 to 95 one run and 61 to 68 the next, minutes apart. On the low runs Chrome recorded first paint 1.1 or 2.2 seconds after the HTML had arrived, never in between, even though every blocking file had finished by 0.3 seconds and the main thread was idle. Lighthouse then pinned the slow paint on everything the apps had loaded during that blank stretch, and there went 30 points.
I spent two days finding where it lived. I built test pages, ran over a hundred passes on Google's servers, blocked iframes, moved stylesheets around, and read the filmstrips frame by frame.
The clearest proof is two pages. A page with the theme CSS and one text section, and no Shopify head code, held back zero times in 15 runs. The exact same page with Shopify's content_for_header added held back 9 times in 27. Allbirds, Gymshark and Fashion Nova show the same thing on PageSpeed, and local Chrome never does.
So the trigger is in the code Shopify puts in every store's head, and the measurement happens on Google's side. Nothing a theme paints or defers changes it.
I made the held runs less bad anyway. With the popup painting first and the dead Forms loader gone, the low runs went from 60 and 61 up to the mid-60s, and the good ones reached 91 to 95.
Then I wrote it up, with an evidence pack of 46 raw reports and their filmstrips. Shopify Support looked and confirmed the head code is outside their control. The two-page test is up on the Shopify Community, and it is filed with Google as Lighthouse issue 17230. I also sent it to Shopify's developer forum, which is still waiting on review. For the client, the part that counts is simple: real visitors never hit the hold, and the store's field data is green.
The scoreboard#
| Measure | Before | After |
|---|---|---|
| PageSpeed, mobile, home | about 60 | 91 to 95 on a good run, 63 to 68 on a held one |
| PageSpeed, desktop, home | 83 | 99 |
| Blocking time, Google's servers | 4 to 5 s | under 0.15 s |
| Home page weight, mobile | 7.7 MB | about 1.5 MB |
| Heaviest page, projects | 31.2 MB | near zero before scroll, 7.5 MB after |
| Training page | 20.9 MB | 0.4 to 4 MB |
| Product manual page | 13.9 MB | 0.7 MB |
| Live tracking pixels | 11 | 3 |
| Apps | 29 | 24 |
| JavaScript errors across 20 template loads | 0 | 0 |
| Real-user layout shift | 0.26, failing on the 28-day field | 0.004 on home, measured today |
| Design change, downtime | none, none |
What is not on the board is a business outcome. I do not have the sales or traffic figures from after this work, and I will not put an estimate up as a result. If Resin Rock shares them, they go here.
What I would tell you before your own Shopify speed project#
A few things from this job hold for any Shopify store.
Speed is an inventory, not an app. The biggest wins here were pulling out what was dead and sizing the media to the device, not clever theme code. Before you install a single optimizer, list every app and pixel and write down the one job each does. The ones you cannot finish that sentence for are your first savings. The same job on the other platform is the WooCommerce version of this story, Seal 'n Lock's store going from 59 to 95. What a store like yours costs to run each month is in the guide on the real monthly cost of a small online store.
Measure on the real fleet, and read the spread. Google's own docs say the score moves run to run with the network and the hardware. One 95 means nothing and one 61 means nothing. Ten runs together tell you the truth, and on Shopify a single number will mislead you because of the hold this job turned up.
The lab score is not your customer. The number Google ranks on, and the one a visitor feels, is the field data from real Chrome users over 28 days, the Chrome UX Report. Read that part first. On this store it was green while the lab number was still bouncing around. A store that is built rather than assembled starts there instead of fighting for it: the storefront on my homepage loads in 0.9 seconds because nothing dead was ever bolted to it.
If your store is somewhere in this story#
Run three checks this week. Open PageSpeed on your store and run it five times, then look at the range, not the best number. Scroll to the real-user section of that same report and see whether layout shift is green. And in your admin, count the apps and pixels and write the job of each in one line.
If one of those worries you and you are not sure why, book a call. It is thirty minutes, and I will tell you whether the fix is worth doing before you spend a day on it.
Questions people ask
Can a Shopify store reach 90 or more on mobile PageSpeed?
Yes, on a good run. Resin Rock's store holds 91 to 95 on mobile on Google's own servers when the test machine behaves, and 99 on desktop. Some runs still read 63 to 68 because of a hold in Google's test fleet that hits every Shopify store, not just this one. The number a visitor actually feels is the field data, and that is green.
Why does my Shopify PageSpeed score keep changing?
The same page can score 91 one run and 65 the next, minutes apart, with nothing changed. On the low runs Chrome records first paint a second or two after the page has already arrived. It comes from the code Shopify puts in every store's head meeting Google's test machines. I reproduced it on a two-page test and reported it to Google and Shopify.
Will removing Shopify apps speed up my store?
Only the dead ones, and only if you check first. On this store I mapped every app and pixel to what it fed, and the client removed five apps and eight pixels that were running with nothing behind them: zero forms, zero affiliates, disabled buttons. The apps that fed leads and ads stayed.
What slows a Shopify store down more, the theme or the apps?
On this store it was the apps and the media, not the theme. Each page carried 2.2 to 2.4 MB of app JavaScript, four Google tag containers fetched twice, and a 3 MB hero video playing full size on phones. The theme's worst habit was an overlay that hid the page until its script ran.
Is PageSpeed the number that matters for a Shopify store?
No. PageSpeed runs Lighthouse on a simulated slow phone and estimates a score, so it is a lab tool. What Google ranks on, and what a customer feels, is the field data from real Chrome users over 28 days. Read that part of the report first, then use the lab score to find what to fix.
Sources
- About PageSpeed Insights, Google for Developers
- Largest Contentful Paint, web.dev
- Total Blocking Time, web.dev
- Cumulative Layout Shift, web.dev
- Chrome UX Report, Chrome for Developers
- Storefront head code delays Chrome's first frame on PageSpeed, Shopify Community
- Inconsistent first paint on repeat runs, Lighthouse issue 17230, GitHub


