What Is Liquid and How Does It Work?

Liquid is a template language — a system that combines static HTML with dynamic data to generate web pages. When a customer visits your Shopify store, Liquid templates are processed on Shopify's servers, the dynamic data (product names, prices, images, cart contents) is inserted into the HTML, and the resulting page is delivered to the customer's browser.

Unlike general-purpose programming languages like JavaScript or Python, Liquid is intentionally limited in scope. It cannot access the filesystem, make network requests, or execute arbitrary code. This makes it secure — even if a theme developer makes a mistake, Liquid's constraints prevent it from causing security vulnerabilities or crashing the server. Shopify chose this design deliberately to ensure that all themes on their platform are safe and performant.

Liquid consists of three fundamental components that every Shopify developer needs to understand: objects (which output data), tags (which control logic), and filters (which modify output). With just these three building blocks, you can create any storefront layout, display any product data, implement conditional logic, and build complex theme functionality.

You do not need to learn Liquid to run a successful Shopify store. Shopify's visual theme editor handles most customization needs. However, understanding Liquid unlocks deeper customization: conditional product badges, custom promotional banners, personalized content based on customer tags, and advanced layout modifications that go beyond what the theme editor offers.

Liquid Objects: Accessing Store Data

Objects are the data layer of Liquid. They represent store data — products, collections, cart items, customer information — and are accessed using double curly braces: {{ object.property }}. When Shopify processes a template, it replaces objects with their actual values.

The Most Important Liquid Objects

product — Represents a single product. Available on product pages.

collection — Represents a group of products. Available on collection pages.

cart — Represents the current shopping cart. Available globally.

customer — Represents the logged-in customer. Available when authenticated.

shop — Represents the entire store. Available globally.

Liquid Tags: Logic and Control Flow

Tags control the logic of templates. They are enclosed in curly-brace-percent delimiters: {% %}. Tags do not produce visible output — they control what content is rendered and how.

Conditional Tags

The if, elsif, else, and unless tags control conditional rendering:

Show a "Sale" badge only when a product has a compare-at price: {% if product.compare_at_price > product.price %} <span class="sale-badge">Sale</span> {% endif %}

Show different messages based on cart value: {% if cart.total_price >= 7500 %} You qualify for free shipping! {% elsif cart.total_price >= 5000 %} Add {{ 7500 | minus: cart.total_price | money }} more for free shipping {% else %} Free shipping on orders over $75 {% endif %} (Note: Liquid prices are in cents, so 7500 = $75.00)

Iteration Tags

The for loop iterates over arrays:

Loop through products in a collection: {% for product in collection.products %} <h2>{{ product.title }}</h2> <p>{{ product.price | money }}</p> {% endfor %}

The limit and offset parameters control pagination: {% for product in collection.products limit: 4 %} shows only the first 4 products.

Variable Tags

assign creates a new variable: {% assign sale_price = product.price | times: 0.8 %}

capture captures a block of content into a variable: {% capture greeting %}Hello, {{ customer.first_name }}!{% endcapture %}

Theme Tags

section renders a reusable theme section: {% section 'header' %}

render includes a snippet (partial template): {% render 'product-card', product: product %}

layout specifies which layout file to use: {% layout 'alternate' %}

Liquid Filters: Transforming Output

Filters modify the output of objects and literals. They are applied using the pipe character | and can be chained for multiple transformations.

Money Filters

String Filters

Image Filters

Math Filters

Shopify Theme File Structure

Every Shopify theme follows a standard directory structure. Understanding this structure is essential for making Liquid modifications.

Directory Purpose Key Files
layout/Base HTML wrapper for all pagestheme.liquid (main layout), password.liquid
templates/Page-type templatesindex.json, product.json, collection.json, cart.json, page.json
sections/Reusable content blocksheader.liquid, footer.liquid, product-template.liquid, hero.liquid
snippets/Small reusable code fragmentsproduct-card.liquid, price.liquid, social-icons.liquid
assets/Static files (CSS, JS, images)theme.css, theme.js, logo.svg
config/Theme settingssettings_schema.json, settings_data.json
locales/Translation stringsen.default.json, fr.json, de.json

Online Store 2.0 and Sections

Online Store 2.0 (OS 2.0) is Shopify's modern theme architecture, introduced in 2021. It replaced the rigid template system with a flexible, section-based approach that gives merchants much more control over page layout without touching code.

In OS 2.0, templates are JSON files that define which sections appear on a page and in what order. Sections are self-contained Liquid files that include their own HTML, CSS, JavaScript, and schema (configuration options). Merchants can add, remove, reorder, and configure sections through the visual theme editor.

For Liquid developers, OS 2.0 means building sections with rich {% schema %} blocks that expose settings to the theme editor. A well-built section lets merchants customize colors, text, layout, and behavior without editing code — while the Liquid template underneath handles the dynamic rendering.

Practical Liquid Examples

Display a Sale Badge

Show a percentage-off badge when a product is on sale:

{% if product.compare_at_price > product.price %} {% assign discount = product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price | round %} <span class="sale-badge">-{{ discount }}%</span> {% endif %}

Free Shipping Progress Message

Show how much more the customer needs to spend for free shipping:

{% assign threshold = 7500 %} {% if cart.total_price >= threshold %} <p>You have earned free shipping!</p> {% else %} {% assign remaining = threshold | minus: cart.total_price %} <p>Add {{ remaining | money }} more for free shipping</p> {% endif %}

For a more polished implementation, the EA Free Shipping Bar provides an animated progress bar with geolocation and multi-currency support — no Liquid coding required.

Personalized Welcome Message

Greet logged-in customers by name:

{% if customer %} <p>Welcome back, {{ customer.first_name }}!</p> {% else %} <p>Welcome! <a href="/account/login">Sign in</a> for a personalized experience.</p> {% endif %}

Conditional Content Based on Product Tags

Show special messaging for products tagged with specific labels:

{% if product.tags contains 'new-arrival' %} <span class="badge new">New Arrival</span> {% endif %} {% if product.tags contains 'bestseller' %} <span class="badge best">Bestseller</span> {% endif %} {% if product.tags contains 'limited-edition' %} <span class="badge limited">Limited Edition</span> {% endif %}

Liquid Performance Best Practices

Minimize Liquid Loops

Every for loop adds server processing time. Avoid nesting loops (a loop inside a loop) whenever possible. Use limit to reduce iterations when you only need a subset of items. For product-heavy pages, lazy loading and pagination are more performant than rendering all products in a single loop.

Use render Instead of include

The {% render %} tag is faster than the deprecated {% include %} tag because it creates an isolated scope. It also prevents variable leaking between snippets, making templates more predictable and maintainable.

Optimize Image Loading

Always use the image_url filter with a specific width to serve appropriately sized images: {{ product.featured_image | image_url: width: 400 }}. For additional image optimization and performance improvements, the EA Page Speed Booster handles lazy loading, compression, and script deferral automatically.

Cache Expensive Operations

If you need the same calculated value multiple times in a template, assign it to a variable once rather than recalculating: {% assign sale_percentage = product.compare_at_price | minus: product.price | times: 100 | divided_by: product.compare_at_price | round %} — then reference {{ sale_percentage }} wherever needed.

How to Customize Your Shopify Theme with Liquid

Getting Started Safely

Common Customizations

When to Use Apps Instead of Custom Liquid

Not every customization needs custom Liquid code. Shopify apps handle common functionality with polished UI, ongoing maintenance, and zero code required. For email capture, the EA Email Popup & Spin Wheel provides sophisticated popup functionality. For conversion optimization, tools like EA Sticky Add to Cart and EA Countdown Timer add proven conversion elements without theme modifications. For upselling and cross-selling, EA Upsell & Cross-Sell manages recommendation logic automatically. Apps are preferable when functionality requires ongoing updates, complex logic, or integrations with external services.

Frequently Asked Questions

What is Shopify Liquid?

Shopify Liquid is an open-source template language created by Shopify and written in Ruby. It is the backbone of every Shopify storefront, controlling how dynamic store data — products, collections, customer information, and cart contents — is rendered as HTML. Liquid uses objects (data), tags (logic), and filters (output modification) to generate pages.

Do I need to know Liquid to run a Shopify store?

No. Shopify's theme editor and Online Store 2.0 allow extensive customization without code. You can change layouts, add sections, modify colors and fonts, and configure apps visually. Learning basic Liquid unlocks deeper customization, but it is not required for running a successful store.

What is the difference between Liquid objects, tags, and filters?

Objects ({{ }}) output dynamic content like product titles and prices. Tags ({% %}) control logic and flow — conditionals, loops, and variable assignments. Filters (|) modify output — formatting currency, truncating text, or transforming images. Together, these three components make up the entire Liquid language.

What are the most commonly used Liquid objects?

The most commonly used Liquid objects are: product (title, price, images, variants), collection (products, title), cart (items, total_price, item_count), customer (name, email, orders), and shop (name, url, currency). These objects are available in their respective template contexts.

Where can I learn more about Shopify Liquid?

The best resources are: Shopify's official Liquid documentation at shopify.dev, the Dawn theme source code on GitHub, Shopify's free "Liquid Essentials" course on Shopify Learn, and community forums. For hands-on practice, use a free Shopify Partners development store to experiment with Liquid.

Skip the Code — Get Results with Free Apps

The EasyApps Ecommerce suite gives you conversion optimization, email capture, upselling, and speed optimization — no Liquid coding required. 10 free apps that work with any Shopify theme out of the box.

Browse All Free Apps