Storefronts V2

Swell's Liquid implementation is based on LiquidJS, with the addition of several standard tags, filters and objects to support working with Themes.

The goal is a template language is to render static and dynamic content with a language that is easy to learn and widely supported. Liquid was originally created by Shopify for this purpose, but has since gained broad adoption among developers and users, in many different categories of business. In our effort to grow access to new capabilities for merchants, we believe that adopting the most widely known template language for themes serves everyone's interest.

The examples in this guide are in reference to Swell-native objects and properties. When using a Shopify theme with a compatible storefront app, you'll instead use equivalent Shopify objects and properties as noted in each section.

The following are logical and comparison operators used within conditional tags.

OperatorDescription
==equals
!=does not equal
>greater than
<less than
>=greater than or equal to
<=less than or equal to
ormatches condition A or B
andmatches condition A and B
containsmatches substrings or strings in arrays

Numerical operators such as + and - are not supported. Instead, you would use the mathematical filters such as {{ a | plus: b }} and {{ a | plus: b }}. See the Math filter section for more details.

Tags are surrounded by {% ... %} delimiters and are always closed with a matching end tag.

Example
{% if account %}
  Hello, {{ account.name }}
{% endif %}

Filters are used to modify output or assignment of a variable, separate by a pipe | character. They can take one or more positional or named arguments.

Example
{{ product.price | money }}

Liquid templates are formatted for readability, however it can affect the HTML output in undesirable ways. Use a hyphen - character on either or both sides of any tag to cause Liquid to strip whitespace on the left and right sides of the tag.

Example
{%- if category.products.size > 0 -%}
  ...
{%- endif -%}

Also note, each tag outputs a trailing newline \n character, however adding a hyphen to the end of the tag will strip the newline from output.

Example
{% assign author = "emmett" -%}
{{ author }}

The following are supported conditional tags for output control.

TagDescription
ifrender output if conditions match
elseifalternate `if` expression
elserender output if no previous conditions match
unlessrender output if conditions do not match
caseswitch output between one or more `when` tags

See the Conditional tags section for more details.

The following are tags used to iterate through array and collection values.

` and `
TagDescription
forrenders output for every item of an array
elsealternate output when `for` has zero length
breakstops a `for` loop from iterating
continuecauses a `for` loop to skip to the next iteration
cyclerenders an output from a list of strings for each `for` loop iteration
tablerowrender HTML `
tags for each item in an array
paginateiterates through a collection across multiple pages

See the Iteration tags section for more details.

The following are tags to control how Liquid is processed and rendered.

TagDescription
commentprevents an expression from being rendered
echooutputs an expression, usable inside `{% liquid %}` tags
liquida block of Liquid code without individual delimiters
rawouputs any Liquid code without rendering it

See the Syntax tags section for more details.

TagDescription
assigncreates or overwrites a variable with the assigned value
capturecapture a variable value as the expression output
decrementdecreases the value of a numeric variable by 1
incrementincreases the value of a numeric variable by 1

See the Variable tags section for more details.

Tags are logical code that control the output of theme templates.

Conditional tags control if and when expressions are rendered.

The if tag executes a block of code only if a specified condition evaluates to truthy. It allows for conditional rendering of content based on variables or expressions.

Syntax
{% if condition %}
  expression
{% endif %}
  • condition: The condition to evaluate.
  • expression: The expression to render when the condition is met.

The elsif tag adds additional conditions to an if or unless block, executing its code only if previous conditions are falsy and its own condition is truthy. This tag must follow an if or another elsif and precede any else.

Example
{% if product.sale %}
  On sale
{% elsif price < 10 %}
  Under $10
{% endif %}

The else tag provides a fallback block of code that executes if all preceding if and elsif conditions in the structure are falsy. This tag is optional and can only appear once at the end of an if or unless block.

Syntax
{% else %}
  expression

The unless tag executes a block of code only if a specified condition evaluates to falsy, acting as the inverse of the if tag. Like if, it can be combined with elsif and else for more complex flows.

Syntax
{% unless condition %}
  expression
{% endunless %}
  • condition: The condition to evaluate.
  • expression: The expression to render unless the condition is met.

The case tag creates a switch statement that compares a variable against multiple values, executing the corresponding when block for the first match. Each when can check one or more values, and an optional else handles unmatched cases.

Syntax
{% case variable %}
  {% when value_one %}
    expression
  {% when value_two %}
    expression
  {% else %}
    expression
{% endcase %}
  • variable: The variable used to evaluate the case statement.
  • value_one: A specific value to match against.
  • value_two: A specific value to match against.
  • expression: The expression to render when the value is matched.

HTML tags are used to output HTML with Swell-specific attributes.

Renders an HTML <form> tag to submit <input> and other form values to a specific endpoint. Forms are defined by each storefront app, such as Proxima, to coincide with their intended functionality. Refer to the app's documentation for specific forms that are available in its environment.

Syntax
{% form 'type' %}
  content
{% endform %}
  • type: The specific type of form to render.
  • content: Content rendered inside the <form> HTML tag.

Optional tag parameters

  • return_to: URL to redirect the page to after the form is successfully submitted.

HTML attributes

You may add additional named parameters to the form tag in order to attach HTML attributes to the rendered form.

Example
{% form 'type', id: 'custom-id', class: 'custom-class', data-example: 'value' %}
  <!-- content -->
{% endform %}

Renders a <style> tag with attributes required by the Swell Theme Editor.

You may reference theme color settings, and other global values within the style tag. If your theme includes plain <style> tags without this syntax, then Liquid values may not update as expected within the editor.

Syntax
{% style %}
  css_rules
{% endstyle %}
  • css_rules: The CSS rules to evaluate at run-time.

Iteration tags are used to repeatedly evaluate blocks of code.

The for tag iterates over an array or a range of numbers, executing the enclosed code block for each item. It supports parameters like limit, offset, reversed, and loop variables such as forloop.index.

Syntax
{% for variable in array %}
  expression
{% endfor %}
  • variable: A variable to assign for each item in the array.
  • array: The array or collection to iterate over.
  • expression: The expression to render for each iteration.

Optional tag parameters

  • limit: The maximum number of iterations.
  • offset: A number of iterations to start from.
  • reversed: Reverse the order of iteration.

Range iteration

Instead of iterating over array items, specify a numeric range in the format of (number..number).

Syntax
{% for num in (1..3) %}
  {{ num }}
{% endfor %}

forloop object

The forloop object contains information about the current for iteration, from within the expression.

Properties

  • first (boolean): Indicates the current iteration is the first one.
  • index (number): The 1-based index of the current iteration.
  • index0 (number): The 0-based index of the current iteration.
  • last (boolean): Indicates the current iteration is the last one.
  • length (number): The total number of iterations.
  • parentloop (forloop): The parent forloop object, if nested inside another for loop.
  • rindex (number): The 1-based index of the current iteration in reverse order.
  • rindex0 (number): The 0-based index of the current iteration in reverse order.
Example
{% for product in products %}
  Product #{{ forloop.index }}
  {% if forloop.last %}
    There are {{ forloop.length }} products
  {% endif %}
{% endfor %}

The else tag, when used within a for or tablerow loop, executes its code block if the iterated collection is empty. It provides a fallback for no results.

Syntax
{% for variable in array %}
  expression
{% else %}
  expression
{% endfor %}
  • variable: A variable to assign for each item in the array.
  • array: The array or collection to iterate over.
  • expression: The expression to render for each iteration.

The break tag terminates the enclosing for or tablerow loop immediately when encountered. It exits the loop without processing remaining iterations.

Syntax
{% break %}
Example
{% for num in (1..3) -%}
  {% if num > 1 %}
    {% break %}
  {% else %}
    {{ num }}
  {% endif %}
{% endfor %}

The continue tag skips the rest of the current iteration in a for or tablerow loop and proceeds to the next one. It jumps to the next loop cycle.

Syntax
{% continue %}
Example
{% for num in (1..3) -%}
  {% if num == 2 %}
    {% continue %}
  {% else %}
    {{ num }}
  {% endif %}
{% endfor %}

The cycle tag outputs values from a provided list in sequence, repeating as needed during iterations. It accepts a group name for independent cycling across multiple uses.

Syntax
{% cycle 'string', 'string', ... %}
Example
{% for num in (1..3) -%}
  {% cycle 'one', 'two', 'three' %}
{% endfor %}

The tablerow tag iterates over a collection like for, but formats output into an HTML table row with cells. It supports parameters like cols, limit, and uses tablerowloop variables.

A tablerow tag should be enclosed in a <table> HTML element.

Syntax
{% tablerow variable in array %}
  expression
{% endtablerow %}
  • variable: A variable to assign for each item in the array.
  • array: The array or collection to iterate over.
  • expression: The expression to render for each iteration.
Example
<table>
  {% tablerow product in products cols: 2 %}
    {{ product.name }}
  {% endtablerow %}
</table>

Optional tag parameters

  • cols: The number of columns the table should have.
  • limit: The maximum number of iterations.
  • offset: A number of iterations to start from.

Range iteration

Instead of iterating over array items, specify a numeric range in the format of (number..number).

Syntax
{% tablerow num in (1..3) %}
  {{ num }}
{% endtablerow %}

tablerowloop object

The tablerowloop object contains information about the current for iteration, from within the expression.

Properties

  • col (number): The 1-based index of the current column.
  • col0 (number): The 0-based index of the current column.
  • col_first (boolean): Indicates the current column is the first one.
  • col_last (boolean): Indicates the current column is the last one.
  • first (boolean): Indicates the current iteration is the first one.
  • index (number): The 1-based index of the current iteration.
  • index0 (number): The 0-based index of the current iteration.
  • last (boolean): Indicates the current iteration is the last one.
  • length (number): The total number of iterations.
  • rindex (number): The 1-based index of the current iteration in reverse order.
  • rindex0 (number): The 0-based index of the current iteration in reverse order.
  • row (number): The 1-based index of the current row.

The paginate tag splits a collection object into pages and provides information about the current page, items, and navigation links. Pagination is typically used with collections of records, such as products, categories, blogs, customer addresses, etc.

A for loop should be used inside a paginate tag to iterate over the collection's items.

Syntax
{% paginate collection by limit %}
  {% for item in collection %}
    for_content
  {% endfor %}
{% endpaginate %}
  • collection: The collection object or array to paginate with
  • limit: The maximum number of items to include per page, up to 1,000.
  • item: The the item of the for loop being iterated inside the paginate tag.
  • for_content: The content of each for loop iteration.
Example
{% paginate category.products by 15, window_size: 3 %}
  {% for product in category.products %}
    {{ product.name }}
  {% endfor %}

  {{ paginate | default_pagination }}
{% endpaginate %}

Optional tag parameters

  • window_size: The number of pages that should be displayed in pagination navigation.

Syntax tags effect how Liquid is processed and rendered.

The comment tag adds non-rendered notes to the code.

Syntax
{% comment %}
  content
{% endcomment %}
  • content: The content of the comment.

Inline comments

You may use a hash # character to prevent the following expression from being evaluated inside any tag.

Example
{% # a single line comment %}

{% # for num in (1..3) -%}
  {{ num }}
{% # endfor %}

Inline comments can also be used inside Liquid tags.

Example
{% liquid
  # this is an inline comment
  assign num_products = products.length
%}

The echo tag renders the value of an expression directly to the template. It functions similarly to the {{ }} output tag but in a procedural context.

Syntax
{% liquid
  echo expression
%}
  • expression: The expression to be rendered.

The liquid tag encloses a block of procedural Liquid code, allowing commands like echo, if, and assign on separate lines. It supports multi-line scripting without needing individual {% %} tags for each statement.

Syntax
{% liquid
  expression
%}
  • expression: The expression to be evaluated.

The raw tag prevents the enclosed content from being parsed as Liquid code, outputting it as plain text.

Syntax
{% raw %}
  expression
{% endraw %}
  • expression: The expression to output without being evaluated.

The content_for tag creates a designated area in a theme where blocks can be rendered.

Support for this tag is still in development.

The include tag renders a component (snippet) file, allowing access to parent template variables. The component has access to variables in the parent scope.

Note: include deprecated in favor of the render tag for better performance.

Syntax
{% include 'component' %}
  • file_name: The name of the component file (snippet) to render, without the .liquid extension.

The javascript tag encloses JavaScript code within layouts, sections, blocks, or components. It generates a <script> tag for execution in the theme.

Syntax
{% javascript %}
  code
{% endjavascript %}
  • code: The JavaScript code to be executed at run-time.

The layout tag specifies which layout file to use for the current template from the layouts/ folder. Without a name, it defaults to theme.liquid.

Syntax
{% layout 'name' %}
  • name: The name of the layout file to use, or none for no layout.

The render tag renders a snippet or app block, isolating variables from the parent template. It supports passing variables as parameters for controlled access.

Syntax
{% render 'file_name' %}
  • file_name: The name of the component file (snippet) to render, without the .liquid extension.

Passing variables

You may pass variables as named parameters to the component, which become available within its scope when rendered.

Example
{% render 'file_name', variable: value %}

Render for

Use the for parameter to render a component for every item in a collection or array.

Example
{% render 'file_name' for array as item %}

Render with

Use the with parameter to pass an entire object to the component, assigned as a variable with the name specified.

Example
{% render 'file_name' with object as name %}

The section tag renders a section file from the sections/ folder. It integrates customizable sections into templates. This renders a section statically, such that its settings are not editable in the Swell Theme Editor.

Syntax
{% section 'name' %}
  • name: The name of the section file to render.

The sections tag renders a group of sections as part of a theme's layout. It allows dynamic inclusion of multiple sections grouped by name in the layout.

Place the sections tag where you want the section group to be rendered.

Syntax
{% sections 'name' %}
  • name: The name of the section group file to render.

The stylesheet tag encloses CSS rules within sections, blocks, or components (snippets). Its contents are combined with other stylesheet output on a page and rendered as combined optimized output.

Liquid code is not rendered inside the {% stylesheet %} tag.

Syntax
{% stylesheet %}
  css_rules
{% endstylesheet %}
  • css_rules: The CSS styles to render for the section, block, or component.

The assign tag creates a new variable or updates an existing one with the result of an expression. It supports assigning values like strings, numbers, arrays, or outputs from filters.

Syntax
{% assign variable = value %}
  • variable: The name of the variable being created or updated.
  • value: The value to assign to the variable.
Example
{% assign product_name = product.name | upcase %}

{{ product_name }}

The capture tag assigns the rendered content between its tags to a variable, without outputting it directly. The captured variable can then be used or manipulated elsewhere in the template.

Syntax
{% capture variable %}
  value
{% endcapture %}
  • variable: The name of the variable being created or updated.
  • value: The value to assign to the variable.

The decrement tag decreases a named integer variable by 1 and outputs the new value. If the variable doesn't exist, it starts at -1 before decrementing.

Syntax
{% decrement variable %}
  • variable: The name of the variable being decremented.

The increment tag increases a named integer variable by 1 and outputs the new value. If the variable doesn't exist, it starts at -1 before incrementing.

Syntax
{% increment variable %}
  • variable: The name of the variable being incremented.

Filters are used to modify Liquid output.

Array filters are used to modify arrays.

The compact filter removes empty values from an array.

Example
{{ array | compact }}

The concat filter combines two arrays by concatenating them.

Example
{{ array1 | concat: array2 }}

The find filter returns the first object in an array for which the queried attribute has the given value or nil if no match.

Example
{{ array | find: 'property', 'value' }}

The find_exp filter returns the first object in an array for which the given expression evaluates to true or nil if no item satisfies the expression.

Example
{{ array | find_exp: 'item', 'item.property == value' }}

The find_index filter returns the 0-based index of the first object in an array for which the queried attribute has the given value or nil if no match.

Example
{{ array | find_index: 'property', 'value' }}

The find_index_exp filter returns the 0-based index of the first object in an array for which the given expression evaluates to true or nil if no item satisfies the expression.

Example
{{ array | find_index_exp: 'item', 'item.property == value' }}

The first filter returns the first element of an array.

Example
{{ array | first }}

Dot notation

You can use the first filter with dot notation inside a tag.

Example
{% assign first_item = array.first %}

The group_by filter groups array items by a common attribute.

Example
{{ array | group_by: 'property' }}

The group_by_exp filter groups an array's items using a Liquid expression.

Example
{{ array | group_by_exp: 'item', 'item.property == value' }}

The has filter returns true if an item exists in an array for which the queried attribute has the given value or false otherwise.

Example
{{ array | has: 'property', 'value' }}

The has_exp filter returns true if an item exists in an array for which the given expression evaluates to true or false if no item satisfies the expression.

Example
{{ array | has_exp: 'item', 'item.property == value' }}

The join filter joins elements of an array into a string with a separator.

Example
{{ array | join }}

You can also use a custom separator for joined items.

Example
{{ array | join: ', ' }}

The last filter returns the last element of an array.

Example
{{ array | last }}

Dot notation

You can use the last filter with dot notation inside a tag.

Example
{% assign last_item = array.last %}

The map filter creates an array of values by extracting the values of a named property from another object.

Example
{{ array | map: 'property' }}

The reject filter creates an array excluding objects with a given property value or excluding truthy values by default if no property is given.

Example
{{ array | reject: 'property', 'value' }}

The reject_exp filter creates an array excluding objects for which the given expression evaluates to true.

Example
{{ array | reject_exp: 'item', 'item.property == value' }}

The reverse filter reverses the order of an array.

Example
{{ array | reverse }}

The size filter returns the number of items in an array.

Example
{{ array | size }}

Dot notation

You can use the size filter with dot notation inside a tag.

Example
{% assign count = array.size %}

The sort filter sorts elements of an array.

Example
{{ array | sort }}

You can also sort the array by an item's property.

Example
{{ array | sort: 'property' }}

The sort_natural filter sorts elements of an array in a natural order.

Example
{{ array | sort_natural }}

You can also sort the array by an item's property.

Example
{{ array | sort_natural: 'property' }}

The sum filter returns the sum of all elements in an array.

Example
{{ array | sum }}

You can also specify a property to sum object values.

Example
{{ array | sum: 'property' }}

The uniq filter removes duplicate elements from an array.

Example
{{ array | uniq }}

The where filter filters an array based on a matching attribute value.

Example
{{ array | where: 'property', 'value' }}

Todo