A Shopify store can look beautiful and still feel slow.
One of the most common situations I've seen is a product page containing large images, multiple sections, third-party scripts, app blocks, and custom JavaScript.
The first reaction is often:
"We need a new theme."
But sometimes you don't need to rebuild the entire Shopify store.
You can get significant improvements by finding the actual bottleneck and fixing it at the theme level.
In this article, I'll walk through a practical example of improving a Shopify product page using Liquid, JavaScript, and better image loading techniques.
If you need help with Shopify theme customization, performance improvements, or custom development, you can also check out my Shopify development service:
Shopify Store Design & Development Service
The Problem
Imagine a Shopify product page like this:
Product Page
│
├── Large Hero Image
├── Product Gallery
├── Product Information
├── Reviews App
├── Recommendation App
├── Recently Viewed App
├── Custom Animation
├── Newsletter Popup
└── Chat Widget
The page looks great.
But on mobile, customers experience:
- Slow initial loading
- Images appearing late
- Layout shifting
- Delayed interactions
- Slow product gallery
- Unnecessary JavaScript execution
The important question is:
Which part is actually causing the problem?
Step 1: Don't Guess — Measure First
Before changing code, check the page using tools such as:
- Chrome DevTools
- Lighthouse
- PageSpeed Insights
- Shopify's own analytics/performance information
Look for:
- Large image files
- Render-blocking resources
- Long JavaScript tasks
- Third-party scripts
- Layout shifts
- Slow network requests
For example, if your product hero image is 2500×2500 pixels but the customer is viewing it at 600×600 pixels, you're sending significantly more image data than necessary.
That's an easy place to start.
Step 2: Optimize Shopify Images
Shopify's image CDN can generate appropriately sized images.
Instead of simply outputting:
{{ product.featured_image | image_url }}
you can request an appropriate width:
{{ product.featured_image | image_url: width: 800 }}
Then use it inside an image element:
<img
src="{{ product.featured_image | image_url: width: 800 }}"
alt="{{ product.featured_image.alt | escape }}"
width="800"
height="800"
>
This gives the browser a more appropriate resource instead of unnecessarily downloading a huge original image.
Step 3: Use Responsive Images
A better approach is to provide multiple image sizes.
<img
src="{{ product.featured_image | image_url: width: 800 }}"
srcset="
{{ product.featured_image | image_url: width: 400 }} 400w,
{{ product.featured_image | image_url: width: 800 }} 800w,
{{ product.featured_image | image_url: width: 1200 }} 1200w
"
sizes="(max-width: 749px) 100vw, 800px"
alt="{{ product.featured_image.alt | escape }}"
width="1200"
height="1200"
>
Now the browser can choose an appropriate resource based on the device and available layout size.
This is especially useful for product galleries.
Step 4: Don't Lazy-Load the Main Product Image
Here's an important distinction.
You may want to lazy-load images that are below the fold.
But the main product image is often one of the first important visual elements on the page.
For the primary image, I generally avoid unnecessarily delaying its loading.
For example:
<img
src="{{ product.featured_image | image_url: width: 1200 }}"
alt="{{ product.featured_image.alt | escape }}"
fetchpriority="high"
width="1200"
height="1200"
>
For images further down the page, lazy loading can make more sense:
<img
src="{{ image | image_url: width: 800 }}"
loading="lazy"
alt="{{ image.alt | escape }}"
width="800"
height="800"
>
The idea isn't:
"Lazy-load everything."
The idea is:
"Load important content early and defer content that isn't immediately needed."
Step 5: Reduce Unnecessary JavaScript
Another common problem is loading JavaScript for functionality that the customer may never use.
For example, imagine a custom animation script:
document.querySelectorAll('.product-card').forEach(card => {
// animation logic
});
If your page contains hundreds of product elements, this can become unnecessarily expensive.
Instead, initialize functionality only when it's actually needed.
For example:
const products = document.querySelectorAll('.product-card');
if (products.length > 0) {
products.forEach(card => {
// Initialize only when product cards exist
});
}
You can also defer non-critical scripts.
<script src="{{ 'custom.js' | asset_url }}" defer></script>
The defer attribute allows the browser to continue parsing the HTML while the script downloads.
Step 6: Don't Load an App's Assets Everywhere
This is another issue that can appear in heavily customized Shopify stores.
Suppose an app is only needed on the product page.
There is little reason to load its assets across every page if the implementation allows you to control where they are loaded.
A Liquid condition can help:
{% if request.page_type == 'product' %}
<script src="{{ 'product-feature.js' | asset_url }}" defer></script>
{% endif %}
Now the script is only included when the current page is a product page.
The exact implementation depends on the app and how its assets are injected, but the principle is important:
Don't load functionality where it isn't needed.
Step 7: Prevent Layout Shifts
Another common problem is images without defined dimensions.
For example:
<img src="product.jpg" alt="Product">
The browser doesn't necessarily know how much space the image will occupy before it loads.
This can cause content to move when the image appears.
Instead:
<img
src="product.jpg"
alt="Product"
width="800"
height="800"
>
Or use CSS with a controlled aspect ratio:
.product-image {
aspect-ratio: 1 / 1;
overflow: hidden;
}
This reserves space for the image and can help create a more stable layout.
Step 8: Be Careful With Third-Party Apps
Apps are useful.
But every app can potentially add extra resources to your store.
For example:
Reviews
Chat
Analytics
Popup
Wishlist
Upsell
Tracking
Recommendations
Individually, each one might seem small.
Together, they can create a noticeable performance cost.
Before adding another app, ask:
"Can this functionality be implemented simply in the theme?"
Sometimes a small custom Liquid/JavaScript solution can be cleaner than adding another dependency.
Step 9: A Simple Shopify Product Image Implementation
Putting some of the ideas together, a product image could look like this:
{% assign product_image = product.featured_image %}
{% if product_image %}
<img
src="{{ product_image | image_url: width: 1000 }}"
srcset="
{{ product_image | image_url: width: 400 }} 400w,
{{ product_image | image_url: width: 800 }} 800w,
{{ product_image | image_url: width: 1000 }} 1000w,
{{ product_image | image_url: width: 1400 }} 1400w
"
sizes="(max-width: 749px) 100vw, 50vw"
alt="{{ product_image.alt | default: product.title | escape }}"
width="1400"
height="1400"
fetchpriority="high"
>
{% endif %}
This gives you:
- Responsive image selection
- Appropriate image sizing
- Better accessibility
- Reserved image space
- Priority loading for the main visual
What I Would Check After Making the Changes
After making changes, don't immediately assume the page is faster.
Test it again.
Check:
Before
↓
Lighthouse / PageSpeed
↓
Make one change
↓
Test again
↓
Compare results
Pay attention to:
- LCP
- CLS
- INP
- FCP
- TTFB
- Total page weight
- Number of requests
Most importantly, check the experience on an actual mobile device.
A good Lighthouse score is useful, but real users are the final test.
The Bigger Lesson
One of the biggest mistakes in Shopify development is trying to fix performance by rebuilding everything.
Sometimes the real problem is much smaller:
One oversized image.
One unnecessary script.
One third-party app.
One poorly implemented section.
One animation running unnecessarily.
Before rebuilding a Shopify store, find the actual bottleneck.
Then fix the bottleneck.
This approach can save development time while keeping the existing store, products, theme structure, and branding intact.
Need Help With Shopify Development?
If your Shopify store needs theme customization, performance optimization, responsive design fixes, custom Liquid development, or a complete redesign, I provide Shopify development services.
You can check out my Fiverr service here:
Shopify Store Design & Development Service
If you're working with Shopify, I'd love to know:
What's the biggest performance issue you've faced in a Shopify store — images, apps, JavaScript, or something else?
Top comments (0)