Shopify Essentials: Liquid Template Fundamentals

9 minute read Shopify Essentials · Part 3

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.
  • include is 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:

  • product
  • collection
  • cart
  • shop
  • settings

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 variables
  • capture: store string blocks
  • cycle: 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 render chains

Best Practices

  • Keep templates shallow and DRY
  • Use section.settings for flexibility
  • Test loops for performance with Shopify Theme Inspector
  • Use semantic, readable variable names
  • Comment your logic for others (and future you)

Need Shopify help? I work with retailers and agencies across Liverpool and Merseyside. Learn more about my Shopify services or get in touch.