How We Cut Page Load Time by 70% for an E-Commerce Client
This is a case study about a real client project — a fashion accessories e-commerce store with 340 products on Shopify loading in 6.8 seconds on mobile with a 34% bounce rate. The client noticed a direct correlation between their bounce rate and conversion rate: visitors who stayed longer than 10 seconds converted at 4.1%. Visitors who bounced in the first 3 seconds converted at 0.3%. Over 12 working days, we reduced average mobile load time to 1.9 seconds — a 72% improvement.
The Initial Audit
We start every performance engagement with a structured audit before touching any code. Using WebPageTest, Google PageSpeed Insights, and Shopify's Theme Inspector, we documented every performance issue. Initial Lighthouse scores were 28 on mobile, 41 on desktop. Largest Contentful Paint was 7.2 seconds. The waterfall revealed the problems: a 420KB hero image, 14 third-party JavaScript files loading synchronously, an app loading 3 CSS files on every page, and no image lazy loading on the 48-product collection grid.
Problem 1: Hero Image Overhaul
The hero image was a 4200x2800 pixel JPEG weighing 418KB — displayed at 390x260 on mobile, meaning the mobile version was downloading approximately 14x more image data than it needed. The fix: convert to WebP format (reducing the 1440px version from 418KB to 89KB — a 79% reduction), use Shopify's native srcset implementation to serve appropriately sized images at each breakpoint, and add explicit width and height attributes. This single change improved LCP by 2.8 seconds.
Problem 2: Third-Party Script Audit
The 14 third-party JavaScript files included a live chat widget, loyalty program app, Instagram feed app, recently viewed products app, countdown timer app, two different analytics tags (the client had installed a replacement but never removed the original), a heatmap tool, and several others. We categorized each by business value and load timing requirement, then implemented lazy loading for non-critical scripts using an IntersectionObserver-based approach. Total blocking time reduced from 2,100ms to 380ms.
Problem 3: Collection Page Image Lazy Loading
The collection page displaying 48 products was loading all 48 product images immediately on page load, even though only 8 were visible without scrolling. Adding loading='lazy' to the product card image in the collection template (a two-line change) resulted in 40 images being deferred until the user scrolled near them. On a slow mobile connection, this reduced initial page data transfer by 1.8MB.
Problem 4: App CSS and JavaScript Consolidation
Three separate Shopify apps were loading their own CSS stylesheets on every page — including the cart and 404 page where none of the apps appeared. We contacted support teams for two apps to request page-specific loading options. For the app that could not be configured, we implemented a JavaScript-based conditional loader. For the third app, which had not been actively used in six months, we simply uninstalled it.
Problem 5: Font Loading Optimization
The store was loading two Google Fonts families with four weight variants each via the standard Google Fonts CSS link — introducing a cross-origin DNS lookup and eight HTTP requests. We downloaded all font files, uploaded them to Shopify theme assets, and audited actual font usage across the site — finding four of the eight weight variants were not used anywhere. Removing unused weights halved font file requests from eight to four.
Problem 6: Duplicate Analytics Tags
Finding two analytics implementations on the same site — one legacy Google Analytics Universal tag alongside a GA4 tag — is more common than clients realize, particularly when analytics have been managed by multiple agencies over time. The legacy UA tag was adding unnecessary JavaScript execution and firing unnecessary network requests. After confirming with the client that the UA property was no longer in use, we removed it. This yielded a 140ms reduction in Total Blocking Time.
Problem 7: Cumulative Layout Shift Fixes
The CLS score was 0.31 — well above Google's 'Good' threshold of 0.1. Sources: the hero image layout shift (fixed with explicit dimensions), a promotional announcement bar that appeared after initial render causing the entire page to push down 48 pixels, and product badges injected via JavaScript after cards had already rendered. The announcement bar was refactored to render server-side with a consistent height reservation. CLS improved from 0.31 to 0.04.
Results and Key Takeaways
- Mobile PageSpeed score: 28 → 91. Desktop: 41 → 96
- Largest Contentful Paint: 7.2s → 1.4s on mobile
- Total Blocking Time: 2,100ms → 310ms
- Cumulative Layout Shift: 0.31 → 0.04
- Average mobile load time: 6.8s → 1.9s
- Bounce rate on collection pages: 34% → 18%
- Conversion rate on sessions >3 seconds: 4.1% → 5.7%