Back to Blog
Technical Guide
Defer JavaScript in Shopify: Best Practices
Master JavaScript deferring to improve First Contentful Paint and reduce blocking time.
Why This Matters
JavaScript execution blocks HTML parsing. By deferring non-critical scripts, you allow content to render faster, improving perceived performance and Core Web Vitals.
Understanding defer vs async
Three ways to load JavaScript, each with different behavior:
- Normal: Blocks HTML parsing until downloaded and executed
- async: Downloads in parallel, executes immediately when ready (blocks parsing)
- defer: Downloads in parallel, executes after HTML parsing completes
When to Use defer
Use defer for scripts that:
- Don't need to run immediately
- Depend on the DOM being fully parsed
- Need to execute in order (multiple defer scripts run sequentially)
- Enhance functionality but aren't critical for initial render
Implementation in Shopify
Add the defer attribute to script tags in your theme:
<!-- In theme.liquid -->
{{ 'application.js' | asset_url | script_tag: defer: "defer" }}
<!-- Or manually -->
<script src="{{ 'theme.js' | asset_url }}" defer></script>Scripts to Defer in Shopify
These common Shopify scripts are safe to defer:
- Theme JavaScript (theme.js, application.js)
- Analytics scripts (Google Analytics, Facebook Pixel)
- Marketing widgets (email popups, reviews)
- Social sharing buttons
- Chat widgets
Scripts to NOT Defer
Some scripts must load synchronously:
- Scripts that write to the page using document.write()
- Critical functionality needed for above-fold content
- Scripts that other deferred scripts depend on
Testing Your Changes
After implementing defer, test thoroughly:
- Check PageSpeed Insights for improved scores
- Test all interactive features work correctly
- Verify no console errors appear
- Test on mobile devices
- Check that apps still function properly
Common Issues and Fixes
Issue: jQuery undefined error
Scripts depending on jQuery run before jQuery loads
Solution:
// Wrap code in DOMContentLoaded
document.addEventListener('DOMContentLoaded', function() {
// Your jQuery code here
})Expected Performance Gains
Performance Improvements
- • 20-30% faster First Contentful Paint
- • Reduced blocking time by 1-2 seconds
- • Better Lighthouse Performance score
- • Improved mobile experience
Let Us Optimize Your JavaScript Loading
We'll properly defer all scripts and fix any compatibility issues in 48-72 hours.