Render-Blocking Resources on Shopify: Six Fixes Compared
PSI flagged render-blocking resources on your Shopify store. Here are the six fixes you will see recommended and which ones actually move the score.

Quick Answer: Six fixes for render-blocking resources on Shopify get passed around in community threads, and only two reliably move the PSI score for a non-developer. The rest break something, require a developer whose work gets erased by the next theme update, or shave noise.
You have run your store through PageSpeed Insights. The red bar in the Opportunities panel reads "Eliminate render-blocking resources" with somewhere between four hundred milliseconds and a second and a half of estimated savings. You have already tried the obvious things. You added defer to every <script> tag you could find in theme.liquid. You read a blog recommending you inline critical CSS, you opened the code editor, and you backed away. You tried the rel="alternate stylesheet" trick from a 2023 Shopify Community thread, your homepage flashed unstyled for half a second on the next load, and you reverted the change. The warning did not move.
That is where this post picks up. The warning is older than Shopify's current theme architecture. Threads about this exact PSI message on the Shopify Community go back to 2015, and the advice has barely shifted in a decade. You get sent defer and async. You get sent "inline critical CSS." You get sent a preload trick. None of them come with a confirmed-success merchant follow-up in the threads I pulled for this piece. Across eighteen Shopify Community and r/shopify threads examined on this warning, zero had the green "Solved" marker.
What follows is the six fixes you will keep running into, compared side by side, scored by what each actually buys you on a real Shopify store. If you only have ten minutes, skip to the last section.
The warning is actually three warnings
Before a fix can land, you have to sort the list PSI gives you. Opportunities > Eliminate render-blocking resources is a flat column of URLs. On a Shopify store those URLs fall into three buckets, and each bucket has a different ceiling on what a merchant can touch.
- Compiled theme CSS. URLs ending in
base.css,compiled_assets/styles.css, or (on Horizon) astyles.cssthat does not exist as any file you can open. These are generated by Shopify's build pipeline from.scsssources, or on Horizon from{% stylesheet %}blocks spread across the theme's section files. A browser cannot paint a styled page without them. Deferring them produces a flash of unstyled content for the length of the CSS download, which on throttled mobile is one to three seconds of plain HTML. - Shopify platform scripts. URLs on
cdn.shopify.com/shopifycloud/orcheckout.shopifycs.com. The admin bar, the pixel bridge, the checkout connector, and a handful of other things Shopify needs to put on the page. You cannot touch any of it. - App-injected scripts. URLs on third-party CDN domains:
cdn.klaviyo.com,connect.facebook.net,static.gorgias.io,cdn.judge.me, and so on. These arrive throughcontent_for_headerbecause the app installed an App Embed or (until March 2027) a ScriptTag. The app vendor chose not to passdeferon the way in. You cannot add it from the outside.
There is a fourth slice hiding inside the second bucket: <script> tags somebody added by hand to theme.liquid or to a snippet during store setup. Those were put there by a human, usually you or whoever built the store, and a human can edit them. The common examples are a Google Tag Manager snippet pasted into <head> and a Meta pixel installed before Shopify shipped first-party pixel support.
Keep that split in your head. Four of the six fixes below only apply to the fourth slice. The remaining two are what you reach for when the rest of the list is where your time has been going.
The six fixes, side by side
| Fix | Who it works for | Setup time | What breaks | Realistic score gain |
|---|---|---|---|---|
Add defer to a custom head script | GTM, Meta pixel, pasted snippets in theme.liquid | 15 min | Analytics events that fire before DOMContentLoaded | 5 to 15 PSI points |
| Inline critical CSS | Developer only, non-Horizon | 1 to 2 days | Every theme update erases the work | 2 to 8 PSI points |
rel="alternate stylesheet" + onload swap | Nobody, honestly | 20 min | FOUC on every page load until JS runs | None, or a flash of unstyled content |
| Preload the compiled CSS | Nobody, measured | 10 min | Nothing, and nothing improves either | 0 to 2 PSI points |
| Remove the offending app | Any app you can live without | 5 min | Whatever the app was doing for you | 10 to 30 PSI points |
| Facade pattern for a widget | Chat widgets, review tabs, size charts | 2 to 4 hours (developer) | Proactive triggers that fire before interaction | 10 to 25 PSI points |
The point ranges are rough. Your mobile score lives in a Moto G Power simulation on throttled 4G, so one app removal can move the number more than the saved milliseconds would suggest, and sometimes less. Treat the ranges as the shape of what each fix buys, not a promise.
What setup each one actually requires
Three of the six are short enough that the time is mostly reading. Three are not.
Add defer to a custom head script. Open the theme code editor, open theme.liquid, find your pasted script tag, and add the attribute. The edit itself is one word. The cost is figuring out whether the script tolerates it. GTM is the frequent one; the container itself fires fine with defer for most pageview use cases. The exceptions are custom tags inside GTM that need to run before DOMContentLoaded. If you have a saved-cart snippet, a session-replay tool, or any script that reads cookies or dispatches events during the initial parse, do not add defer without checking what fires downstream.
Inline critical CSS. This is the fix a developer will suggest if they do not know Shopify. The idea is sound in a vacuum: extract the CSS needed to paint above the fold, inline it into <head>, and load the rest asynchronously. On a static site it works. On a Shopify theme it does not survive the next time a merchant drags a section around in the theme editor, because above-the-fold content varies per page template and sometimes per customization. PageFly-Richard and oscprofessional both recommend this in older community threads. Neither thread has a confirmed success story attached. Budget one to two days for a developer, and plan to redo the work every time your theme updates.
The rel="alternate stylesheet" trick. This one has lived in enough blog posts that it keeps surfacing in community threads. The pattern replaces a stylesheet link with rel="alternate stylesheet" and an onload handler that switches it back to rel="stylesheet" after it has loaded. In theory, the browser treats the stylesheet as non-blocking during download. In practice on Shopify, a 2023 Community thread documents the Stockholm theme merchant AnnaSleep1997 attempting this with base.css and bootstrap-grid.css, and the result was "css not load in few milisecond then, also Eliminate Render-Blocking Resources issue still there." FOUC without a score change. Twenty minutes to implement, same amount to revert.
Preload the compiled CSS. Shopify's own Liquid filter stylesheet_tag: preload: true adds a <link rel="preload"> tag for the stylesheet. It tells the browser to start the fetch earlier in the page load pipeline. What it does not do is remove the stylesheet from the render-blocking list. The page still cannot paint until the CSS is parsed. The PSI warning does not disappear. Several experts recommend this on community threads, and the recommendation is harmless, but it does almost nothing on a store that is actually slow for other reasons.
Remove the offending app. This is five minutes in the Shopify admin. The time cost is deciding which apps to drop, which is a separate problem. One useful shortcut comes from bkocdur's August 2026 r/shopify analysis of 269 stores: on a Shopify store flagged for render-blocking scripts, the biggest contributor is almost always app scripts, and the biggest subset of those is apps that are "nice to have." Chat widgets you have never once answered a message on. Review platforms that show two reviews on a product that has sold forty units. Popup apps you installed during a Black Friday rush and forgot about. Each has an uninstall button; the time is in your willingness to use it.
Facade pattern for a widget. This is the one Shopify officially recommends and the one that requires actual work. The pattern replaces an app's script with a lightweight HTML placeholder styled to look like the widget's closed state. When a user interacts with the placeholder, your code loads the real widget. Shopify's developer documentation on removing render-blocking apps cites roughly 320 milliseconds of blocking saved on an Intercom chat facade, and roughly 180 milliseconds on a size-chart app restricted to product pages. The implementation is a developer afternoon for one widget, longer if you also want to support the widget's proactive triggers. For a solo merchant without a developer on retainer, this is the fix I would pay for if the app in question is otherwise unremovable.
What each one breaks when it fails
The failure modes matter more than the success modes, because the success modes are rarely the complete picture.
The defer fix breaks analytics in a specific way. If your GTM container has a tag that fires on gtm.js ready instead of DOMContentLoaded, deferring the container will drop the earliest page view events for sessions that interact in the first few hundred milliseconds. Most merchants will not notice this on a weekly dashboard; a few will see it in Meta Ads Manager as a mysterious attribution gap. Test with the GTM preview tool before shipping.
Inline critical CSS fails quietly. The theme update that erases your inlined CSS does not throw an error; it just reverts the file. Three months in, your developer has moved on, the inlined block is gone, and the PSI score is back where it started. If you are going to do this, make your developer document the exact above-the-fold CSS they inlined and the exact asset load path they used to defer the rest. Otherwise you are rebuilding on vibes.
The alternate stylesheet trick fails loudly, in the one way that matters: the visitor sees unstyled HTML for the half second it takes JavaScript to swap the stylesheet back active. On a slow connection or a flaky JS execution path, that window stretches. For a visitor who has not loaded your site before, a flash of unstyled content reads as a broken site, not a slow site. The PSI "fix" turns into a conversion rate drop at the same keystroke.
Preloading the CSS does not break anything. It is on this list mostly because it is on every other list, and because merchants spend time implementing it believing it will remove the warning. It will not. The time cost is small; the opportunity cost is big. Time you spent on this is time you did not spend removing an app.
App removal breaks whatever the app was doing. The honest version is that most apps on a $1K to $50K per month store were installed to solve a problem that is no longer a problem, or to run an experiment that nobody is running anymore. The remainder genuinely earn their keep, and those should stay. If a chat widget converts ten chats a month into sales, the 320 milliseconds it costs is probably worth it. If it converts zero chats a month, the chat widget is dragging your score down for nothing.
The facade pattern breaks the "proactive" side of chat widgets. If your Intercom or Shopify Inbox fires a message after 30 seconds on page, that message cannot fire if the widget never loaded. Most merchants I have talked to on help1 chat do not know their chat widget has proactive triggers until they turn the widget off and the sales they used to track to proactive conversation stop. Audit the trigger analytics before you facade.
What each one actually buys you
Measured against the PSI score, not against the warning disappearing.
defer on a hand-pasted head script is the only fix in this list that reliably moves the warning without side effects on most stores. If your warning list has a GTM entry at the top and GTM lives in your theme code, this is a 10 to 15 point mobile score improvement on a merchant-controlled script. I have watched a store go from a 38 mobile to a 52 on this alone, with no code change beyond adding the attribute.
Inlining critical CSS buys 2 to 8 points if executed perfectly, and 0 points two months later when the theme updates. On a store where app scripts are the dominant blocker, inlining buys even less, because the app scripts stay in the render path regardless of what the CSS is doing.
The alternate stylesheet trick buys you nothing except the chance to introduce FOUC. I would not try this on a live Shopify store. The one place I have seen it work is a non-Shopify static site with hand-authored CSS. It is not compatible with Shopify's compiled CSS architecture.
Preloading the compiled CSS buys 0 to 2 points. It is a legitimate browser hint; it is not a fix. The warning stays.
Removing the offending app is the biggest single-day win available to a non-developer. One chat widget removal can shift mobile scores by 10 to 20 points on a store that was previously below 50. On a store already at 70, the ceiling is lower, maybe 3 to 5. Pair app removal with the orphaned-code cleanup pattern from the main-thread work report (see our main-thread work walkthrough for the specific list order I was following) and you get a free second swing on the same afternoon.
The facade pattern is the heavy artillery. Shopify's documented savings of 320 ms on chat and 180 ms on template-restricted widgets translate roughly to 10 to 25 PSI points, depending on where you started. The number is bigger than defer because the saved main-thread time is bigger. The cost is developer hours and the opportunity cost of giving up proactive widget behaviors.
What I would pick, in order
If a solo merchant handed me a PSI report with "Eliminate render-blocking resources" flagged, I would walk through this list in exactly this order.
First, sort the warning's URL list into the four buckets described above. Mark compiled CSS and Shopify platform scripts as untouchable. Mark app CDN scripts as "remove the app, or facade it." Mark <script> tags you find in theme.liquid as "edit this."
Second, add defer to anything in the fourth bucket that tolerates it. This is a fifteen-minute edit per script. If a script does not tolerate defer, note the reason and leave it alone.
Third, open the Apps list and look for the "nice to haves." Any app you have not opened the admin for in three months is a candidate for removal. Any app whose analytics show fewer than one conversion a week is a candidate. You will know; a solo merchant always knows which apps are earning. Uninstall two. Rerun PSI.
Fourth, for the apps that are earning but still have third-party scripts in your render-blocking list, read Shopify's documented facade recommendation. If you have a developer available, this is the project to send them. The chat widget first; it is almost always the biggest cross-page blocker.
Fifth, do not inline critical CSS unless you are on a stable theme with a long-term developer relationship. Mark it as "revisit if everything else is done and the score still matters."
Sixth, do nothing with preloading or the alternate-stylesheet trick. They are time traps.
If you want a second pair of eyes on the sort - specifically whether a given CDN URL belongs to an app you can afford to drop - that is what help1's expert chat is for. The first fifteen minutes are free, which is usually enough for one PSI report.
Ten minutes with your PSI report
Open PageSpeed Insights. Paste your store URL. Scroll to Opportunities, click Eliminate render-blocking resources, and copy the list of URLs into a plain text note. Then do this:
- Group the URLs by domain. Everything on
cdn.shopify.com/s/files/.../assets/is compiled CSS. Set those aside as untouchable. Everything oncdn.shopify.com/shopifycloud/is a Shopify platform script. Set those aside too. - For each remaining domain, check your installed apps. If the domain matches an app you can live without, uninstall it from the Shopify admin. Rerun PSI and record the new mobile score.
- In your theme code editor, open
theme.liquidand search for<script src=. For every tag you find whose src references a third-party domain you no longer use (an app you uninstalled months ago, a tag manager you replaced), delete the line. These are orphan scripts and they are the one piece of leftover code almost always safe for a non-developer to clean up. - For each hand-pasted script in
<head>that stays (GTM, Meta pixel, custom tracking), adddeferto the tag. Test it on a duplicated staging theme first; GTM in particular wants a preview check. - If you still see third-party scripts in the warning after steps 2 and 3 and you cannot remove the app, the next step is the facade pattern. That is a developer task. help1's diagnostic app flags which of your remaining scripts are the biggest blockers, so you have the brief ready before you spend the hours.
Ten minutes is enough for steps one through three on most stores. Steps four and five are the next session.
Still stuck? Talk to an expert.
Our vetted Shopify experts can fix this issue for you in a live session. $39 per session. Your first 15 minutes are free.