What is Liquid?
Liquid is Shopify's open-source templating language created by Tobi Lütke. It was built because web programming languages like PHP were too complex and potentially unsafe for third-party theme developers. Today, Liquid powers every single Shopify storefront in the world — over 4 million stores.
If you want to build or customize Shopify themes professionally, mastering Liquid is non-negotiable. This guide will take you from zero to confident with Liquid syntax, filters, and logic tags.
The Three Types of Liquid Delimiters
Liquid uses three types of delimiters to distinguish template code from plain HTML:
{{ }}— Output tags: render a variable or expression to the page{% %}— Logic tags: perform operations like loops, conditionals, and assignments{%- -%}— Whitespace control: strips extra whitespace around the tag
Output Tags — Displaying Data
Output tags are the most common thing you will write. They print the value of a variable onto the page:
{{ product.title }}
{{ product.price | money }}
{{ shop.name }}
{{ customer.first_name }}
If the variable is empty or does not exist, Liquid outputs nothing — it never throws an error to your visitors.
Filters — Transforming Output
Filters are one of Liquid's most powerful features. They let you transform data before displaying it. Filters are separated from the variable by a pipe | character:
{{ product.price | money }}
{{ product.title | upcase }}
{{ product.title | downcase }}
{{ product.description | truncate: 150 }}
{{ product.created_at | date: "%B %d, %Y" }}
{{ 'style.css' | asset_url | stylesheet_tag }}
{{ 'logo.png' | asset_url | img_tag: 'Store Logo' }}
Chaining Filters
You can chain multiple filters together. They execute left to right:
{{ product.title | upcase | truncate: 20 }}
Control Flow Tags
if / elsif / else / endif
The most fundamental logic in any template language:
{% if product.available %}
<button type="submit">Add to Cart</button>
{% elsif product.variants.size > 1 %}
<p>Please select a variant</p>
{% else %}
<button disabled>Sold Out</button>
{% endif %}
unless
unless is the opposite of if — it runs when the condition is false:
{% unless customer %}
<a href="/account/login">Log in</a>
{% endunless %}
case / when
Use case to match a variable against multiple values:
{% case product.type %}
{% when 'Shirt' %}
<p>This is a shirt.</p>
{% when 'Shoes' %}
<p>This is footwear.</p>
{% else %}
<p>This is something else.</p>
{% endcase %}
Iteration Tags — Loops
for loop
Loop over arrays like collections, products, or images:
{% for product in collection.products %}
<div class="product-card">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</div>
{% endfor %}
Useful Loop Variables
{% for product in collection.products %}
{% if forloop.first %}<div class="first">{% endif %}
{{ forloop.index }} — {{ product.title }}
{% if forloop.last %}</div>{% endif %}
{% endfor %}
limit and offset
{% for product in collection.products limit: 4 %}
{{ product.title }}
{% endfor %}
{% for product in collection.products limit: 4 offset: 4 %}
{{ product.title }}
{% endfor %}
Variable Tags
assign
{% assign sale_price = product.price | times: 0.8 %}
<p>Sale Price: {{ sale_price | money }}</p>
capture
capture lets you store a block of text in a variable:
{% capture product_url %}
/products/{{ product.handle }}
{% endcapture %}
<a href="{{ product_url }}">View Product</a>
Shopify-Specific Objects
Shopify gives you access to global objects in every template:
shop— store settings, name, currency, emailproduct— current product data (on product pages)collection— current collection (on collection pages)cart— the current cart contentscustomer— logged-in customer datapage— current page contentsettings— your theme's customization settings
Practical Example — Product Card
Here is a real-world example combining everything you have learned:
{% for product in collection.products limit: 8 %}
<div class="card">
{% if product.featured_image %}
<img src="{{ product.featured_image | img_url: '400x400' }}" alt="{{ product.title }}">
{% endif %}
<h3>{{ product.title }}</h3>
{% if product.compare_at_price > product.price %}
<span class="sale-badge">Sale</span>
<s>{{ product.compare_at_price | money }}</s>
{% endif %}
<p>{{ product.price | money }}</p>
{% if product.available %}
<a href="{{ product.url }}">Shop Now</a>
{% else %}
<span>Sold Out</span>
{% endif %}
</div>
{% endfor %}
Conclusion
Liquid is the foundation of every Shopify theme. Once you understand output tags, filters, control flow, and loops, you can build virtually any storefront layout you can imagine. The best way to learn is by doing — open a development store, create a new template file, and start experimenting.
Pro tip: Install the Shopify CLI and use a local development environment with Theme Check to catch Liquid errors before you publish.

