Why Do You Use JavaScript instead of a Liquid Snippet?
We tried using Liquid for this feature but found it wasn't the best fit.
We cannot provide a "custom snippet" and instead have to offer "theme app extensions" like app embeds and app blocks. For an example of what we've done with Liquid, try out our "Discounted Price" app block. This was the first implementation of this feature, but we had to move away from this quickly. It shows why simpler app blocks don't work well for complex features, leading us to switch to a JavaScript (JS) implementation.
Here’s why implementing this purely in Liquid didn’t work well:
- Doesn't Work On Collection/Search/Etc. Pages: Most themes treat product grid cards as "snippets" not designed to support app blocks. Adding an app block here would need big changes to the theme code to support app blocks, requiring a deeper understanding of Liquid than most users have.
- Liquid Doesn't Support the Complexity of Discount Logic: Our discount rules are complicated and would need to be completely rebuilt in Liquid. Liquid isn’t really cut out for this—it doesn’t support basic data structures like dictionaries/maps, and it can’t define reusable functions that are robust enough for our needs. Our Rust-based engine, which includes 220 unit tests to ensure calculations work in various scenrios, illustrates the level of complexity we’re dealing with, which Liquid can't handle effectively.
- Theme App Block Limitations: Theme app blocks work well for adding new elements to a page (like a shipping progress bar) but not for changing existing ones. Previously, users needed to hide their theme’s built-in "Price" block and replace it with ours. If the app was uninstalled, the price display would vanish, which was far from ideal. We found that many users struggled with the technical steps required.
- Variability of Themes: Every Shopify store has its own theme, and merchants expect price elements to look a certain way. Theme app blocks offer limited customization options, and while we do provide tools like CSS for further customization, they’re rarely used because most merchants prefer solutions that work right away without extra setup.
- Lack of Dynamic Interaction: Liquid alone doesn’t support dynamic interactions on the client side. For example, if you change product variants, a Liquid snippet won’t automatically update, which means you'd need to use JavaScript anyway. Some themes behave in ways that could break a purely Liquid solution.
- Rigidity and Upgrade Challenges: Theme app extensions are quite strict. They allow only a limited number of settings and make it hard to update or remove settings without disrupting existing setups. This rigidity makes it difficult to adapt and improve components as needed.
- A JS-based solution will also make it easier to integrate our app into Online Store 1.0 themes, enabling more stores to get value from the app.
Due to these issues, we opted for a JavaScript solution, which provides more flexibility, works better across different Shopify themes, and performs better overall. This approach lets us adapt more effectively to Shopify's platform and meet our merchants' needs better.
Frequently Asked Questions
Why Does the App Load Multiple JavaScript Files in Parallel?
This is due to how Shopify handles theme app extensions, not a per-page choice we make.
The Regios Discounts app uses a Shopify theme app extension to deliver its storefront features. Whenever a theme app extension exposes multiple app embeds or app blocks, Shopify automatically injects a separate <script> tag for each one that the merchant has enabled in their theme. Each embed/block has its own webpack bundle, which means each enabled feature corresponds to its own JavaScript file on the storefront.
Here's why you'll typically see multiple scripts loading on a product page:
- Different features are delivered as separate embeds/blocks: On most product pages, three separate features are usually enabled —
Discounts Embed,Auto add to cart embed, andProduct page discounts app block. Each of these is its own theme app extension component, so Shopify injects a dedicated<script>tag for each. That's where the three parallel scripts come from.
- Shopify bundles each embed/block independently: Shopify's theme app extension architecture compiles each app embed and app block as its own bundle. Even where there is some shared logic between them, Shopify does not merge them into a single combined script on the storefront — this is a platform-level behaviour, not something the app controls.
- The scripts load asynchronously: All scripts injected by theme app extensions load asynchronously, so they do not block other elements of the page (images, text, the add-to-cart button, etc.) from rendering.
- Unused features can be disabled: If a particular feature isn't relevant to your store, you can disable that specific embed/block from your Shopify theme editor. Once disabled, Shopify stops injecting that script entirely.
Are there plans to reduce the number of scripts?
Yes. We have long-term plans to reduce code duplication across these bundles and bring down the overall JavaScript footprint (the Discounts Embed would remain as the main one). We don't have an ETA to share at this time, but it is on our roadmap.
If you'd like help identifying which embeds/blocks are essential for your specific discount setup, please reach out — we're happy to review your configuration.
We’re here to help if you have any more questions or need further clarification.
Updated on: 20/05/2026
Thank you!