Exploring the Liquid Templating Language

Abstract image used to represent Exploring the Liquid Templating Language

Liquid is a Rubybased, opensource templating language developed by Shopify and released in 2006. Its inception was driven by the need for Shopify to offer a flexible and safe environment for both developers and users on the Shopify platform, the need to provide a way for users to develop customised ecommerce storefronts without compromising on the security or performance of the platform itself.

If you're building a custom Shopify theme, Liquid is the language you'll use to put the storefront's data into its templates. It gives us a useful separation between the HTML the server renders and the JavaScript that adds interaction in the browser.


Understanding Liquid

For me, my first introduction to the syntax Liquid uses felt very similar to Handlebars. However, the deeper you get into the development process, the larger the separation you see between the two.

Running Liquid Locally

The original Liquid implementation is written in Ruby, but that doesn't make Ruby a requirement for editing a Shopify theme. Shopify renders the templates. In May 2019, Theme Kit gives us a way to work on local theme files and send them to the store; it is a Gobased tool, separate from the Ruby template engine.

Use Shopify's Theme Kit

On a Mac with Homebrew installed, Theme Kit can be installed with:

brew tap shopify/shopify
brew install themekit

Some Basic Code Examples

There are a lot of features in Liquid, so trying to cover much more than an overview in my examples would lead to a very long (and very dull) article. So, I'm including a few basics below, but encourage you to go and take a look at the documentation to get a firmer grasp of just how much Liquid is capable of.

For now, some simple code examples:

Outputting a Variable

I've mentioned the similarities to Handlebars before, so this might feel familiar. If the template context supplies a product object with a title, we can output it as HTML text using the escape filter:

{{ product.title | escape }}

Using a Filter

Liquid comes with quite a few filters out of the box, all of which are applied in the same way using the pipe (|). So, for example, to use the date filter to format the current date:

{{ 'now' | date: "%Y-%m-%d" }}

This will output the current date in the format YYYY-MM-DD, i.e.: 2019-05-02.

Iterating Over Data

On a Shopify collection page, collection.products gives us products to loop over. Escape each title when putting it into HTML text:

{% for product in collection.products %}
  {{ product.title | escape }} - {{ product.price | money_with_currency }}
{% endfor %}

Compatibility with JavaScript Frameworks and CSS Preprocessors

When I use Sass or React alongside a theme, the useful question is where the build step belongs. Liquid renders the template; separate tools can turn the source styles and JavaScript into assets that the theme can serve.

Sass and Less

In 2019, Shopify supports Sass compilation for theme assets, including .scss.liquid files. Less needs a separate compiler. You can also choose to compile either preprocessor locally with tools such as webpack or Gulp, then upload the resulting CSS with the theme. Include that CSS asset in Liquid like this:

{{ 'styles.css' | asset_url | stylesheet_tag }}

React

Really, it is a similar story when it comes to using frontend JavaScript frameworks like React in conjunction with Liquid. To incorporate React into a Shopify theme, you would typically include a new build step in your development process, which involves setting up a separate React application and then bundling it using a build tool like webpack or Create React App.

The React app can then be mounted into a specific element within your Shopify pages, which means you can leverage the componentbased architecture of React for dynamic/interactive features in particular, like the image carousels and product configurators you would commonly find on a Product Details Page.

A fairly simplified workflow might then look something like this:

  1. Develop your React app separately, focusing on the interactive UI elements you want to enhance within your Shopify theme.
  2. Compile your React app into static JavaScript files.
  3. Include the compiled JavaScript file within your Shopify theme assets.
  4. Use Liquid to reference your compiled JavaScript file in your theme, and initialise the React app within the desired page elements.

Load the compiled bundle with defer, so it runs after the document has been parsed and #react-app exists. The bundle still needs to initialise React against that element:

<head>
  ...
  <script src="{{ 'bundle.js' | asset_url | escape }}" defer></script>
</head>
<body>
  <div id="react-app"></div>
</body>

Using this sort of approach means that you get the best of both worlds: Liquid's serverside rendering capabilities and SEO advantages, combined with React's clientside interactivity.


Features of Liquid in More Depth

I've already gone into some basic code and syntax examples above, so here let's explore some of the core features of Liquid in a little more detail...

Objects and Filters

Objects

In Liquid, objects are placeholders which output dynamic content. They are denoted by double curly braces {{ }} and can represent moreorless anything from strings and numbers to much more complex data structures.

Filters

We use filters to modify the output of objects; these are applied to variables using the pipe character |. There are quite a few filters available; these can be used to transform text, adjust dates, manipulate arrays, and more. This allows us to manipulate and present data without needing to leave the template.

Object and Filter Code Example

Here, upcase changes product.title to uppercase, and escape prepares the result for an HTML text context:

{{ product.title | upcase | escape }}

Tags for Logic and Control Flow

In Liquid, tags perform logical and control operations directly within the template. They are enclosed with curly braces and percentage signs {% %} and support conditions, loops, variable assignments, and more.

If Statements

As you will be familiar with in other languages, if statements allow us to use conditional logic to decide whether to display content or not.

Loops

Again, as a developer, you will undoubtedly be familiar with loops. These iterate over collections (arrays or objects) and then output in a repeated operation.

If and Loop Code Example

This next example uses a custom Liquid context supplied by a host application: user.logged_in, user.name and user.products are fields that application provides. They are not builtin Shopify theme objects. It demonstrates a condition and a loop, with display values escaped for HTML:

{% if user.logged_in %}
  Welcome, {{ user.name | escape }}!
  Here are your products:
  <ul>
    {% for product in user.products %}
      <li>{{ product.name | escape }}</li>
    {% endfor %}
  </ul>
{% else %}
  Please log in to see your products.
{% endif %}

Drops

In the Ruby implementation of Liquid, a Drop is a class the host application can use to expose selected data and methods to templates. Implementing one means working in that application, with Ruby; it does not mean adding Ruby code to a merchant's Shopify theme.

Shopify supplies its own objects to themes. Use those documented objects there; explore custom Drop classes when you control the application that hosts Liquid.


Honorary Mention: Jekyll

As a very brief aside and because I can't find anywhere better within this article to share this tidbit of information I found whilst researching this article; although Shopify developed Liquid for its ecommerce platform, it has been adopted by any number of other applications and platforms since.

The most wellknown adopter is Jekyll, the popular opensource static site generator. Underneath the hood, it is the Liquid templating engine that is powering Jekyll and allowing developers to create blogaware static websites.


Wrapping Up

As is so often the case, this article has taken a bit of a meander as it progressed. So just to wrap things up: if you want to develop with Shopify, then Liquid is the templating engine you will need to become familiar with. Like any other templating language, it is relatively straightforward to get to grips with, and can be added into an existing (or new) CI pipeline alongside CSS preprocessors like Sass, or JavaScript frameworks like React.

If you've been in web development as long as I have, you might even find that you are already familiar with it already due to its use in Jekyll.

Postscript

June 2021: Shopify added theme development to Shopify CLI with Online Store 2.0. That recommendation belongs after this article's original May 2019 publication, when Theme Kit was the appropriate route. Shopify had also announced native Sass deprecation in November 2020; compiling Sass locally and uploading CSS lets you keep it in your own workflow.

September 2026: For new theme work, follow the current Shopify CLI installation requirements: a supported Node.js version, a compatible Node.js package manager and Git. Shopify's account of the move from Ruby to Node explains the toolchain change. Liquid's Ruby origins are not a universal instruction to install Ruby before editing a theme.

Need a senior engineer involved?

I can work directly in the codebase, review the architecture, or support the team through delivery when the work needs more than extra hands.