Key takeaways
- Liquid is Shopify’s templating language — it controls what content is rendered based on data from your store.
- Common use cases: show content based on product tags, customer tags, cart contents, metafields, or the current date.
- Basic Liquid syntax:
{% if %},{% unless %},{% for %},{{ variable | filter }}.- Add custom Liquid logic to section files or snippets in the code editor. Fudge can write it for you.
To add custom Liquid logic in Shopify, open the code editor and add {% if %}, {% unless %} or {% for %} tags to a section or snippet file, using store data such as product tags, customer tags, metafields, the cart or the date. Liquid is Shopify’s templating language: it connects your store’s products, collections, customers and cart to the HTML that visitors see.
Liquid basics — what you need to know
Liquid has two types of tags:
Output tags {{ }} — display a value:
{{ product.title }}
{{ product.price | money }}
{{ customer.first_name }}
Logic tags {% %} — control the flow, not displayed directly:
{% if product.available %}
{% for item in cart.items %}
{% assign sale_price = product.price | times: 0.9 %}
Filters — transform output values using the | pipe:
{{ product.price | money }}
{{ product.description | strip_html | truncatewords: 30 }}
{{ 'base.css' | asset_url }}
Show content based on product tags
Product tags are a flexible way to mark products with attributes and then conditionally display content.
{% if product.tags contains 'new-arrival' %}
<span class="product-badge">New Arrival</span>
{% endif %}
{% if product.tags contains 'sale' %}
<span class="sale-badge">On Sale</span>
{% elsif product.tags contains 'clearance' %}
<span class="clearance-badge">Clearance</span>
{% else %}
<!-- No badge shown -->
{% endif %}
Use cases: badges for new arrivals, sale items, limited editions; showing or hiding sections based on product category; displaying care instructions only for specific product types.
For labels built this way, see Add Custom Labels on Shopify Product Pages.
Show content based on customer tags
Customer tags work the same way — you tag customer accounts in Shopify (Customers → select customer → Tags), then conditionally show content.
{% if customer %}
{% if customer.tags contains 'wholesale' %}
<p>Wholesale pricing: {{ product.price | times: 0.7 | money }}</p>
{% else %}
<p>{{ product.price | money }}</p>
{% endif %}
{% else %}
<p>{{ product.price | money }}</p>
{% endif %}
This changes the price shown, not the price charged. To charge wholesale prices, use Shopify B2B catalogues or an automatic discount for tagged customers.
Use cases: different pricing for B2B vs retail customers, unlocking hidden content for VIP customers, showing loyalty points balance for members.
Show content based on metafields
Metafields store custom data attached to products, collections, customers, or your store. Once created (via the Shopify admin or an app), you can output them in Liquid.
{% if product.metafields.custom.ingredients %}
<div class="ingredients-section">
<h2>Ingredients</h2>
{{ product.metafields.custom.ingredients.value }}
</div>
{% endif %}
Creating metafields: Settings → Custom data → Products → Add definition. Set the namespace (e.g., custom) and key (e.g., ingredients).
Show content based on cart contents
You can access the current cart in any theme file:
{% if cart.item_count == 0 %}
<p>Your cart is empty.</p>
{% endif %}
{% if cart.total_price >= 5000 %}
<!-- Cart is $50+ (prices are in cents) -->
<p>You qualify for free shipping!</p>
{% else %}
{% assign remaining = 5000 | minus: cart.total_price %}
<p>Add {{ remaining | money }} more for free shipping.</p>
{% endif %}
Note: Shopify stores prices in cents (integers). 5000 = $50.00.
Show content based on date
{% assign now = 'now' | date: '%s' | plus: 0 %}
{% assign sale_end = '2026-12-31' | date: '%s' | plus: 0 %}
{% if now < sale_end %}
<div class="sale-banner">Holiday sale ends December 31!</div>
{% endif %}
date: '%s' converts a date to a Unix timestamp (seconds since 1970), making date comparisons straightforward.
Shopify caches pages, so now is the time the page was rendered, not the time the visitor sees it. For exact cut-offs, check the date in JavaScript.
For loops — iterating over collections or arrays
{% for product in collection.products limit: 4 %}
<div class="product-card">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</div>
{% endfor %}
Useful parameters:
limit: 4— only render 4 itemsoffset: 2— skip the first 2 itemsreversed— iterate in reverse order
Where to add custom Liquid logic
Section files (sections/your-section.liquid) — the right place for page-specific logic. Changes are scoped to that section.
Snippets (snippets/your-snippet.liquid) — reusable logic that can be included via {% render 'your-snippet' %} in multiple sections.
theme.liquid — for logic that needs to run on every page (like customer tag checks that affect site-wide behavior). Use sparingly.
Always work on a duplicate theme, and test after any Liquid change — a Liquid syntax error can render your entire page blank.
To put this logic in a section of its own, see Build a Custom Section in Shopify.
Unless — the opposite of if
{% unless %} is shorthand for “if not”:
{% unless customer %}
<a href="/account/login">Log in for member pricing</a>
{% endunless %}
Equivalent to {% if customer == blank %} but more readable.
Assign and capture — creating variables
assign creates a simple variable:
{% assign discount_price = product.price | times: 0.8 %}
{{ discount_price | money }}
capture creates a variable from a block of content (can include HTML and Liquid):
{% capture size_label %}
{{ product.variants.first.option1 }} / {{ product.variants.first.option2 }}
{% endcapture %}
<span>{{ size_label }}</span>
FAQ
What's the difference between Liquid and JavaScript in Shopify?
Liquid runs server-side when Shopify renders the page — by the time the browser receives HTML, all Liquid is already resolved. JavaScript runs in the browser after the page loads. Use Liquid for data that's known at render time (product info, customer tags, page templates). Use JavaScript for anything that needs to react to user actions (cart updates, dynamic filters). If you'd rather not write either by hand, describe the behaviour you want to Fudge, the AI operator for Shopify stores, and it drafts the right mix of Liquid and JS in your theme for you to preview.
Can I use Liquid inside JavaScript blocks?
Inside <script> tags in your section's HTML - yes, Liquid is rendered before JS runs. Inside the section's {% javascript %} block - no, that block is bundled separately and Liquid is not processed there. To pass Liquid data to a {% javascript %} block, output it in the HTML as a data- attribute and read it from JS.
How do I debug a Liquid error that breaks the page?
Open the page in an incognito tab to bypass theme cache. Check the file you most recently edited for unclosed tags ({% if %} without {% endif %}), missing quotes in tag arguments, or typos in object names. Liquid errors usually print inline on the page as "Liquid error: ...". Shopify's Theme Inspector for Chrome helps find slow Liquid.
Can Liquid do math?
Yes, with filters: | plus: 5, | minus: 5, | times: 0.9, | divided_by: 2, | modulo: 3. There's no built-in expression syntax (you can't write {{ 5 + 3 }} directly), so chain filters or use assign for intermediate values.
Can I make Liquid call an external API?
No - Liquid is purely template logic and has no network primitives. To fetch data from an external source, use JavaScript on the front end (fetch) or do the fetching server-side in a Shopify app and store the result in a metafield Liquid can read.