Shopify Liquid Tutorial for Beginners

Is there something you want to change about your Shopify theme? 

There might be a design element you want to add, or maybe you have an idea for a new feature that you think would improve user experience.  

In either case, the only way to get what you want may be to manually edit the code of your theme. To do that, you’ll need to know how Shopify Liquid works.

Shopify Liquid logo
Image Source: Shopify

No coding experience? No problem! This Shopify Liquid tutorial was written with beginners in mind. We’ll avoid technical jargon as much as we can, and whenever an industry term pops up we’ll quickly define it for you. 

Shopify Liquid Basics

Shopify Liquid is a template language that was created by Shopify co-founder and CEO Tobias Lütke. It serves as the framework for all Shopify themes. 

Liquid is written in Ruby. It’s sometimes referred to as a syntax or engine rather than a language, as it’s more limited than general-purpose programming languages like Ruby and PHP. 

Static Content vs. Dynamic Content

Template languages are used by web designers and developers to combine static content with dynamic content. 

Static content stays the same from page to page; dynamic content changes from page to page. Static elements are written in HTML; dynamic elements are written in Liquid. 

The Liquid code is essentially a placeholder. It’s used to retrieve specific data from your Shopify store (such as the name of your store, product descriptions, images, etc.) when the code is compiled and sent to the browser. This allows Shopify themes to be agnostic, which means the same code can work for many different stores without any adjustments. 


Shopify Liquid dynamic
Image Source: Shopify Partners

Delimiters 

Liquid is easy to recognize. In addition to its .liquid file extension, Liquid can be identified by its two delimiters (characters used to separate independent parts in a piece of code):

  • Output is indicated by double curly braces: {{ }}
  • Logic is indicated by percentage signs within curly braces: {% %}

Objects, Tags and Filters

Liquid is characterized by three features: objects, tags and filters. 

Objects (also known as variables) are representative of one or more values. They can stand in for anything from titles to numbers to calculation results to database query results.

In Liquid, objects output (generate for display) pieces of data, so they are wrapped in double curly braces. A single object can support many different properties, and a dot syntax system is used to separate the object from its property. For example, in the object {{ page.content }}, the term before the dot (period) is the object, and the term after the dot is the property. 

Tags are used to create logic for templates, so they are wrapped in percentage signs within curly braces. While tags are not displayed on the page, they determine how objects are displayed on the page or if objects are displayed at all. 

One use for tags is that they can tell your store to display the price of an item if it’s available or display a “sorry, this item is currently not available” message instead if it is not available. 

Filters are used to modify output. They are indicated by the pipe character: |

Liquid in Action

To bring all these concepts together, let’s take a look at the Liquid code for the pre-formatted contact page of Shopify’s Debut theme:

<div class="page-width">
  <div class="grid">
    <div class="grid__item medium-up--five-sixths medium-up--push-one-twelfth">
      <div class="section-header text-center">
        <h1>{{ page.title }}</h1>
      </div>
      {% if page.content.size > 0 %}
        <div class="rte">
          {{ page.content }}
        </div>
      {% endif %}
      <div class="contact-form form-vertical">
        {%- assign formId = 'ContactForm' -%}
        {% form 'contact', id: formId %}
          {% include 'form-status', form_id: formId %}
          <div class="grid grid--half-gutters">
            <div class="grid__item medium-up--one-half">
              <label for="{{ formId }}-name">{{ 'contact.form.name' | t }}</label>
              <input type="text" id="{{ formId }}-name" name="contact[name]" value="{% if form[name] %}{{ form[name] }}{% elsif customer %}{{ customer.name }}{% endif %}">
            </div>
            <div class="grid__item medium-up--one-half">
              <label for="{{ formId }}-email">{{ 'contact.form.email' | t }} <span aria-hidden="true">*</span></label>
              <input
                type="email"
                id="{{ formId }}-email"
                name="contact[email]"
                autocorrect="off"
                autocapitalize="off"
                value="{% if form.email %}{{ form.email }}{% elsif customer %}{{ customer.email }}{% endif %}"
                aria-required="true"
                {%- if form.errors contains 'email' -%}
                  class="input--error"
                  aria-invalid="true"
                  aria-describedby="{{ formId }}-email-error"
                {%- endif -%}
                >
              {%- if form.errors contains 'email' -%}
                <span id="{{ formId}}-email-error" class="input-error-message">{% include 'icon-error' %} {{ form.errors.translated_fields['email'] | capitalize }} {{ form.errors.messages['email'] }}.</span>
              {%- endif -%}
            </div>
          </div>
          <label for="{{ formId }}-phone">{{ 'contact.form.phone' | t }}</label>
          <input type="tel" id="{{ formId }}-phone" name="contact[phone]" pattern="[0-9\-]*" value="{% if form[phone] %}{{ form[phone] }}{% elsif customer %}{{ customer.phone }}{% endif %}">
          <label for="{{ formId }}-message">{{ 'contact.form.message' | t }}</label>
          <textarea rows="10" id="{{ formId }}-message" name="contact[body]">{% if form.body %}{{ form.body }}{% endif %}</textarea>
          <input type="submit" class="btn" value="{{ 'contact.form.submit' | t }}">
        {% endform %}
      </div>
    </div>
  </div>
</div>

We can see examples of the three Liquid features throughout this piece of code:

  • Object: The {{ page.content }} object is a stand-in for the page’s body content, which is defined in the Shopify user interface.
  • Tag: The {% form %} tag is used to insert a form into the page, and the {% endform %} tag is used to close it out (this structure for opening and closing is used for all tags). 
  • Filter: A filter is used for capitalization in the object {{ form.errors.translated_fields['email'] | capitalize }}

This is what the code translates to on the front end:

Contact Us page
Image source: Shopify

To demonstrate how the front end of your store works with the Liquid code of your theme, let’s replace the form on your contact page with text:

1. Before you make any edits to the code of your theme, we recommend that you duplicate your theme and work out of the duplicate. That way, any mistakes you make can be easily reversed:

Duplicate your theme
Image source: Shopify

2. Open the “Actions” menu next to the duplicate of your theme. Select “Edit Code” to open the Shopify code editor. 

Select "Edit Code"
Image source: Shopify

3. Open the page.contact.liquid file.

Open the page.contact.liquid file
Image source: Shopify

4. Highlight and delete the code associated with the form in the Liquid file. 

Highlight and delete the code associated with the form in the Liquid file
Image source: Shopify

5. Save your changes.

Save your changes
Image source: Shopify

6. Select “Themes” to back out of the Liquid code editor.

Select “Themes” to back out of the Liquid code editor
Image source: Shopify

7. Select “Pages."

Select “Pages”
Image source: Shopify

8. Open the contact page. 

Open the contact page
Image source: Shopify

9. Add the text that you want to display (this is what the page.contact.liquid file will retrieve with its {{ page.content }} object) and select “Save."

Select “Save”
Image source: Shopify

10. Your changes will be published.

Your changes will be published
Image source: Shopify

A Closer Look at Objects

Objects are the foundation of Liquid. After all, they are the feature that determines what visitors to your store can actually see. 

Content Objects

Content objects are necessary for Shopify to output content. 

  • {{ content_for_header }} - This object must be included in theme.liquid, which functions as the master template file in Shopify (all themes are rendered in theme.liquid). It’s located inside the HTML <head> tag and loads all the scripts required for Shopify apps, including Shopify analytics and Google Analytics. 
  • {{ content_for_layout }} - This is another object that must be included in theme.liquid. It retrieves content from other templates. 
  • {{ content_for_index }} - This object must be included in templates/index.liquid. It retrieves the sections that are to be rendered on your homepage. 

Global Objects

Global objects can be added to any Liquid file within your theme and used to retrieve the following pieces of data:

  • {{ all_products }} - A list of all the products in your store (up to 20). 
  • {{ articles }} - A list of all the articles on your site.
  • {{ blogs }} - A list of all the blogs on your site.
  • {{ canonical_url }} - The URL of the current page with all parameters removed. 
  • {{ cart }} - Your store’s cart.
  • {{ collections }} - A list of all the collections in your store. 
  • {{ current_page }} - The number of the current page (used for paginated content).
  • {{ current_tags }} - A list of tags (the specific tags retrieved depends on the template you’re using). 
  • {{ customer }} - The customer that is logged in (if the customer is not logged in, nothing is retrieved). 
  • {{ linklists }} - The menus and links in your store.
  • {{ handle }} - The title (also known as a handle) of the current page. 
  • {{ images }} - Access an image with its filename. 
  • {{ pages }} - A list of all the pages in your store. 
  • {{ page_ description }} - The description of the current page.
  • {{ page_title }} - The title of the current page. 
  • {{ recommendations }} - Product recommendations.
  • {{ shop }} - Information about your store. 
  • {{ scripts }} - Information about all active scripts. To access information about a particular script, add the type of script to this object as a property in dot syntax (script.type). 
  • {{ settings }} - A list of the settings in your current theme.
  • {{ template }} - The name of your current theme. 
  • {{ theme }} - Your current theme. 

Remember that all of these objects have up to dozens of properties, which each have a function of their own. Also, there are many objects that don’t fall into the categories of content object or global object. 

A Closer Look at Tags and Filters

There are four types of tags:

  • Theme tags: Output template-specific HTML markup, tell your theme which layouts and snippets (files containing chunks of reusable code) to use, and break up arrays (lists of variables) into more than one page. Example: the {% form %} tag can be used to add a form to a page. 
  • Variable tags: Create new variables. Example: the {% assign %} tag allows you to create and name a new variable. 
  • Iteration tags: Repeat blocks of code. Example: the {% for %} tag will repeatedly execute a block of code. This is useful for when you want to display a collection of products on a page, as it saves you from having to add code for each individual item. Note that these loops are limited to 50 results, so if you have more than 50 products you’ll need to use pagination. 
  • Control flow tags: Determine whether blocks of code are executed or not depending on the situation. Example: the {% if %} tag will only execute a piece of code if certain conditions are met. 

The different types of filters include:

  • Color filters: Change, lighten, darken, saturate or desaturate the color of objects.  
  • Font filters: Change text style (normal or italic/oblique) or text weight (light, normal, bold and anything in between). With the font_face filter, you can add custom fonts to your theme as well. 
  • HTML filters: Add HTML elements to objects, such as payment buttons and timestamps. 
  • Math filters: Incorporate math equations into your objects. One application of this filter is showing a visitor how much they could save (list price multiplied by percentage discount) by taking advantage of a certain deal. 
  • Money filters: Format currency as specified in your Shopify store’s settings. 
  • Date filters: Determine the date format used within objects. 
  • Highlight filters: Highlight text that matches search terms to improve the functionality of your search feature. 

Learn More About Liquid

By now, you have surely gained a strong understanding of what Liquid is and how it works from this Shopify Liquid tutorial. If you would like to learn more about this subject, we recommend the following resources:

  • GitHub: This page contains more Liquid code and information.
  • Learning Liquid: This series of articles published by Shopify covers a number of topics related to Liquid. 

By understanding the code behind your Shopify theme, you’ll be able to turn your ideas for pages into a reality. 

Build Shopify pages that convert.

Create professional-quality pages for your ecommerce store with a powerful drag and drop page builder for Shopify designed with ecommerce teams and agencies in mind.
Learn More

Adam Ritchie

Adam Ritchie is a writer based in Silver Spring, Maryland. He writes about ecommerce trends and best practices for Shogun. His previous clients include Groupon, Clutch and New Theory.