If you want to async load or defer a JavaScript file in Shopify, the short answer is simple: edit the relevant theme file, find the <script> tag, and add either async or defer. In practice, though, choosing the wrong attribute can break product pages, carts, sliders, and app widgets, so the real job is knowing which scripts are safe to change.
I have worked on Shopify themes and apps for years, and this is one of those tasks that looks trivial until a merchant adds async to the wrong file and suddenly variant selectors, add-to-cart buttons, or analytics events stop behaving properly. If you are not fully comfortable editing theme code, duplicate your theme first and consider using a Shopify Partner or Expert.
If your goal is speed, it is also worth reading my guide on Shopify speed optimisation scams because a lot of so-called fixes are either risky, temporary, or simply cosmetic. Async and defer can help, but only when applied with a clear understanding of dependencies.
What is the difference between async and defer in Shopify?
Async downloads a script while the page is parsing and executes it as soon as it is ready. Defer also downloads during parsing, but waits to execute until the HTML has finished parsing, which makes it safer for most theme scripts.
This distinction matters because Shopify storefronts often rely on JavaScript that interacts with the DOM, product forms, cart drawers, variant pickers, and app blocks. In my experience, defer is usually the better default for theme files, while async is better for independent third-party scripts like analytics or ad tracking.
| Attribute | Download timing | Execution timing | Order preserved? | Best Shopify use cases |
|---|---|---|---|---|
async |
While HTML is parsing | As soon as the file finishes downloading | No | Analytics, pixels, ad scripts, independent trackers |
defer |
While HTML is parsing | After HTML parsing completes | Yes | Theme scripts, jQuery-dependent code, sliders, cart logic, DOM manipulation |
A good rule is this: if a script does not depend on the DOM and does not need to run in sequence with other scripts, async may be fine. If a script powers visible store functionality or depends on another file loading first, use defer instead.
How do I async load or defer a JS file in Shopify?
To async load or defer a JS file in Shopify, go to Online Store - Themes - Actions - Edit code, find the script tag, and add the relevant attribute. For most theme assets, defer is the safer option.
This works whether the script is in theme.liquid, a section file, a snippet, or occasionally in older themes inside header.liquid or footer.liquid. On modern Online Store 2.0 themes, you will usually see scripts included directly in layout or section files.
- In Shopify admin, go to Online Store - Themes.
- Click the three dots on your live theme and choose Duplicate.
- Open the duplicate theme and click Edit code.
- Search for the script you want to change.
- Replace the existing tag with a version using
asyncordefer. - Save the file and test key pages thoroughly.
Here is the basic Shopify asset version using defer:
<script src="{{ 'example.js' | asset_url }}" defer></script>
And here is the same idea using async:
<script src="{{ 'example.js' | asset_url }}" async></script>
If you currently have this older Liquid pattern:
{{ 'example.js' | asset_url | script_tag }}
You will usually need to replace it with a full manual script tag, because the standard script_tag output does not always give you the control you want over loading attributes. That is the key change many basic tutorials miss.
Which Shopify scripts should use async, and which should use defer?
The best scripts for async are third-party scripts that can run independently. The best scripts for defer are scripts that affect storefront functionality or rely on the DOM.
When I test stores, the biggest mistakes usually come from putting async on jQuery, theme.js, product scripts, or slider libraries. That often causes race conditions where one script runs before the DOM or a dependency is ready.
| Script type | Recommended attribute | Why |
|---|---|---|
| Google Analytics / GTM | async |
Usually independent and non-render-critical |
| Facebook Pixel / ad tags | async |
Tracking scripts do not usually need DOM order |
| Theme main JS file | defer |
Often controls menus, cart drawer, variant logic, sections |
| jQuery | defer |
Many dependent scripts expect predictable load order |
| Slider or gallery libraries | defer |
Usually need DOM elements ready first |
| Review widgets | Case by case | Some can be async, others need DOM hooks |
| App embed scripts | Case by case | Depends on how the app injects and initialises content |
If you are also trying to improve product page revenue, my guides on maximising Shopify product pages and cart drawer upsells are worth reading, because some speed changes can accidentally break conversion-critical UI.
What code should I use in Shopify theme files?
The correct code depends on whether the file is a Shopify asset, an external script, or a script generated by an app. For most assets in your theme, a manual <script> tag is the most reliable approach.
Below are the most common examples I use when auditing or editing Shopify themes.
How do I defer a Shopify asset file?
Use this when the JavaScript file is stored in your theme's assets folder. This is the most common pattern for custom theme scripts.
<script src="{{ 'theme-custom.js' | asset_url }}" defer></script>
How do I async load an external JavaScript file?
Use this for independent third-party scripts such as analytics or ad platforms. Only do this if the script does not need to run in sequence with another file.
<script src="https://example.com/script.js" async></script>
How do I defer multiple scripts in the correct order?
Defer preserves order, which is one reason it is safer for theme functionality. If one file depends on another, list them in the order they should execute.
<script src="{{ 'jquery.min.js' | asset_url }}" defer></script>
<script src="{{ 'slick.min.js' | asset_url }}" defer></script>
<script src="{{ 'product-gallery.js' | asset_url }}" defer></script>
This is a common fix for the exact problem many merchants run into: moving scripts to the footer or making them async, then finding that product galleries or variants stop working.
Why does my Shopify product page break when I defer or async a script?
Your Shopify product page usually breaks because the script has a dependency, expects the DOM to exist, or relies on load order. In most cases, async is the culprit rather than defer.
This is exactly what happens in many forum threads and Stack Overflow questions. A merchant moves jQuery or a slider library to the bottom of the page, or adds async, and then the product page stops initialising correctly because the code runs at the wrong time.
- jQuery loads after a script that needs it
- A DOM element is not available yet
- An app script expects a specific hook in the head
- Inline JavaScript runs before the deferred file is ready
- Theme code assumes synchronous loading
If your functionality breaks, revert the change and test again with defer instead of async. If it still breaks, the script may need to stay as-is, be moved into a better sequence, or be rewritten so it initialises on DOMContentLoaded.

How do I test async and defer changes safely in Shopify?
The safest way to test script loading changes in Shopify is to work on a duplicate theme and verify key customer journeys before publishing. Never make these edits blind on a live theme.
In my experience building Shopify apps, the right workflow is more important than the code itself. A one-line speed tweak can affect add-to-cart, upsells, subscriptions, review widgets, localisation, and analytics attribution.
- Duplicate your theme before editing anything.
- Test the homepage, collection pages, product pages, cart, and checkout handoff.
- Test on mobile and desktop.
- Open the browser console and check for JavaScript errors.
- Use PageSpeed Insights and GTmetrix before and after.
- Verify analytics events still fire using browser tools or platform debuggers.
For a more complete performance strategy, Shopify merchants should also review Shopify's theme best practices for JavaScript and stylesheet tags. Shopify's own guidance increasingly favours loading scripts efficiently and avoiding unnecessary blocking resources.
Should I edit content_for_header or app scripts?
You should be very cautious with content_for_header and app-injected scripts. In most stores, editing app output is riskier than editing your own theme assets.
Shopify and apps often inject scripts automatically through {{ content_for_header }}. Some advanced developers rewrite or filter parts of this output, but I would only recommend that if you are confident reading minified script output and understand the implications for app compatibility, tracking, and support.
For most merchants, the better approach is:
- Remove apps you no longer use
- Disable app embeds that are not needed
- Load app widgets only on relevant templates where possible
- Ask the app developer if they support conditional loading
If you are dealing with app-related bloat, my article on managing Shopify customer data without losing sales touches on the broader issue of balancing functionality with performance and tracking.
What are the best practices for Shopify speed in 2025?
In 2025, the best practice is not just to add async or defer everywhere. The real goal is to reduce JavaScript execution time, load less code, and only run scripts where they are needed.
Google's performance focus has shifted beyond raw page load to user-centric metrics like Core Web Vitals, especially responsiveness. On Shopify stores, I now pay close attention to INP, script execution cost, and whether a script actually earns its place on the page.
- Use defer for most theme and DOM-dependent files
- Use async for independent analytics and ad scripts
- Conditionally load scripts only on relevant templates
- Remove redundant apps and duplicate tracking tags
- Prefer modern themes like Dawn that already follow better loading patterns
- Reduce inline JavaScript where possible
- Bundle or split code intelligently rather than blindly adding plugins
If you are trying to optimise for both search and AI discovery, I also recommend reading how to optimise your Shopify store for AI shopping agents and how to get your Shopify store into ChatGPT. Technical performance and crawl-friendly rendering increasingly overlap.
Can I improve Shopify speed without editing code?
Yes, you can improve Shopify speed without touching code, but the gains are usually smaller and less precise. The easiest wins are often removing apps, switching to a leaner theme, and cutting unnecessary third-party scripts.
The original version of this article mentioned no-code tools, and that still holds up to a point. Some apps and optimisation services claim to automate async loading and dependency mapping, but I would be careful. As someone who builds apps, I have seen stores end up with another layer of JavaScript solving a JavaScript problem.
If you want a no-code path, start here:
- Audit installed apps and remove anything unused
- Disable app embeds you do not need site-wide
- Use a modern Shopify theme such as Dawn
- Review tracking scripts in Google Tag Manager or theme files
- Use Shopify's built-in reporting and web performance insights where available
For many stores, these changes produce more reliable gains than aggressively changing script attributes across the theme.
What about Shopify Plus stores?
Shopify Plus stores usually have more complexity, not less. They often run more scripts, more integrations, more localisation logic, and more custom front-end code, which makes dependency mapping even more important.
On Plus builds I have worked on, the biggest wins usually come from conditional loading by template or market, not from sprinkling async everywhere. If a script is only needed on product pages, gift card pages, or for specific regions, load it there and nowhere else.
- Use Theme App Extensions where possible to avoid destructive code edits
- Conditionally load scripts by template, product type, or locale
- Review CSP settings if you use strict security policies and inline initialisation
- Test market-specific scripts such as geolocation, currency, or translation tools carefully
If you are wondering whether your store is at the stage where more advanced technical optimisation makes sense, my post on when to upgrade to Shopify Plus gives a practical framework.
How do I know if async or defer actually improved performance?
You know async or defer helped when blocking time drops, JavaScript execution becomes less disruptive, and storefront functionality still works correctly. A Lighthouse score increase alone is not enough.
I always compare before-and-after results using both lab and real-world checks. A script change that improves PageSpeed by 5 points but breaks event tracking or add-to-cart is not a win.
What should I measure?
Measure user-facing speed and business-critical behaviour, not just synthetic scores.
- PageSpeed Insights for render-blocking and execution warnings
- GTmetrix for waterfall analysis
- Browser DevTools for console errors and network timing
- Theme preview testing for actual functionality
- Analytics validation to confirm events still fire
Shopify merchants often focus on the phrase "eliminate render-blocking resources", but in practice the better question is whether the change improves real browsing speed and conversion-critical interactions.
What is my recommended approach for most Shopify stores?
For most Shopify stores, my recommendation is simple: use defer for your own theme JavaScript, use async for independent tracking scripts, and avoid touching app-injected code unless you know exactly what it does.
That approach is conservative, practical, and far less likely to break your storefront. It also aligns with what I have seen across app development, speed audits, and theme troubleshooting.
- Start with low-risk scripts such as analytics and non-essential third-party tags
- Use defer as your default for theme assets
- Do not async jQuery or dependency-heavy libraries unless you are certain
- Test every important template before publishing
- Optimise script quantity, not just loading attributes
If your store also uses upsells, cart customisation, reviews, or delivery messaging, remember that these features often rely on front-end JavaScript. I see this all the time with apps in categories like upselling on Shopify or delivery UX. Performance work should support conversion, not accidentally remove it.
So yes, async and defer are worth understanding. Just do not treat them as a magic speed button. On Shopify, the best results come from applying them selectively, testing properly, and keeping your front end as lean as possible.