Learn the core principles of Shopify's Liquid templating language, including output syntax, logic flow, objects, filters, and best practices.
Liquid is the backbone of every Shopify theme. Whether you’re editing a homepage or building a custom section, understanding how Liquid works is essential to writing clean, maintainable theme code.
This guide introduces the building blocks of Liquid for new Shopify developers or theme editors.
Why Fundamentals Matter Long-Term
Liquid fundamentals are easy to skip when copying snippets. The cost appears months later as:
- Hard-to-change templates
- Fragile logic chains
- Performance regressions from small edits
Clean fundamentals reduce maintenance cost more than any single optimisation.
Design Rationale and Trade-offs
Readability beats cleverness
Liquid is read far more often than it is written. Clear variable names and shallow logic win.
Templates are contracts
Templates define what data the frontend expects. Changing them casually breaks assumptions elsewhere.
Fact Checks and Clarifications
- Liquid logic always runs server-side.
- Filters execute sequentially and cost adds up inside loops.
includeis deprecated and should not be used in new work.
Key Takeaways
- Treat Liquid as declarative, not procedural.
- Keep loops tight and predictable.
- Future you is the primary audience.
What Is Liquid?
Liquid is a template language that renders dynamic content server-side. It was created by Shopify and is used to load product data, collections, settings, and more into HTML templates.
Basic Syntax
Liquid tags are wrapped in {% ... %} and outputs in {{ ... }}.
Output:
{{ product.title }}
Logic:
{% if product.available %}
In stock
{% else %}
Sold out
{% endif %}
Objects
Liquid objects contain store data. Examples:
productcollectioncartshopsettings
Access attributes using dot notation:
{{ product.price | money }}
Filters
Filters modify the output:
{{ product.title | upcase }}
{{ product.description | truncatewords: 20 }}
Chaining filters is common:
{{ shop.name | downcase | replace: " ", "-" }}
Loops
Use for to loop through arrays:
{% for product in collection.products %}
{{ product.title }}
{% endfor %}
Add limit, offset, reversed for control:
{% for item in cart.items limit: 3 %} ... {% endfor %}
Includes and Renders
Use {% render %} to include reusable snippets:
{% render 'product-card', product: product %}
Avoid {% include %} - it’s deprecated.
Built-in Helpers
assign: create variablescapture: store string blockscycle: rotate values (e.g. alternating row colours)section.settings: access schema-defined settings
{% assign sale = true %}
{% if sale %} <div>On Sale</div> {% endif %}
Common Pitfalls
- Forgetting
object.property(e.g.{{ collection.title }}not{{ collection }}) - Using logic inside loops unnecessarily
- Overusing deep nesting and
renderchains
Best Practices
- Keep templates shallow and DRY
- Use
section.settingsfor flexibility - Test loops for performance with Shopify Theme Inspector
- Use semantic, readable variable names
- Comment your logic for others (and future you)
Related Reading
Need Shopify help? I work with retailers and agencies across Liverpool and Merseyside. Learn more about my Shopify services or get in touch.