Where 1.8 seconds actually came from
A commerce performance rebuild, accounted for line by line. The images everyone blamed were worth 200 milliseconds. The tag manager nobody mentioned was worth a full second.
Start by measuring the right thing
The brief was that the site felt slow. The analytics dashboard said average load time was 2.1 seconds, which sounded acceptable, and that number was the reason the problem had gone unaddressed for two years.
Averages hide everything. At the 75th percentile on mobile — which is the number Core Web Vitals actually grades you on, and which described most of their traffic — largest contentful paint was 4.3 seconds. We threw away the dashboard and instrumented real user monitoring, segmented by device class and connection type, before changing a single line.
Where the 4.3 seconds actually went
This is the breakdown we arrived at after a fortnight of measurement. It is worth publishing because it contradicts what nearly everyone in the room predicted at the start.
- Third-party tag manager and the eleven scripts it loaded — 1.04s
- Render-blocking CSS, most of it unused on the page in question — 0.71s
- Server response time on an uncached category query — 0.68s
- Client-side hydration of components that were never interactive — 0.52s
- Web font loading with no fallback strategy — 0.31s
- Images, the presumed culprit — 0.20s
- Everything else — 0.84s
Six people independently guessed images. Images were the sixth-largest contributor and worth less than a fifth of the tag manager.
The tag manager
Eleven scripts had accumulated over four years. Two were analytics tools nobody had logged into for eighteen months. One was a chat widget that had been replaced but never removed. One was a heatmap tool running on every page to serve a campaign that ended in 2023.
We audited each one with the marketing team, asking a single question: who looked at this data in the last quarter? Four survived. The survivors were moved to load after the page was interactive, and conversion tracking moved server-side, which had the side benefit of surviving ad blockers.
Rendering strategy, not framework choice
The rebuild used Next.js, but the gain came from choosing the right rendering mode per route rather than from the framework. Category and product pages became statically generated with incremental revalidation, served from the edge. Only the cart, checkout and account areas render per request.
The hydration cost fell out of this naturally. If a product description is static text, it does not need to ship its component code to the browser at all. Auditing which components genuinely needed interactivity removed around 60% of the client bundle.
The result, and the honest caveat
LCP at the 75th percentile went from 4.3s to 2.5s — the 1.8 second improvement in the headline. Mobile conversion rose 34% and average order value rose 22% over the following quarter.
The caveat worth stating: the checkout was also redesigned during the same period. We cannot cleanly separate how much of the conversion lift came from speed and how much from the new checkout flow. Anyone who tells you they can attribute that precisely is selling something. The speed work stands on its own merits regardless.
Tell us what you are building
A short call, an honest read on whether we are the right fit, and a clear next step either way. No pitch deck.
Replies within one working day
