Template Language

How to style the results from Clerk.io.

Clerk.js's template language is a subset of the Liquid template language.

Here is a simple example of a template:

<h1>{{ headline }}</h1>
  
<ul class="product-list">
  {% for product in products %}
    <li class="product">
      <h2 class="product-name">{{ product.name }}</h2>
 
      <img src="{{ product.image }}" title="{{ product.name }}" />
 
      {% if product.price < product.list_price %}
        <div class="list-price">${{ product.list_price | money }}</div>
        <div class="price">${{ product.price | money }}</div>
        <div class="discount">You Save: {{ product.price / product.list_price * 100 | round }}%</div>
      {% else %}
      	<div class="price">${{ product.price | money }}</div>
      {% endif %}
        
      <a href="{{ product.url }}">Buy Now</a>
    </li>
  {% endfor %}
</ul>

Inserting Values

Everything within {{ and }} is processed by the template engine as a variable to be inserted into the page eg. {{ headline }}.

If a variable contains a deeper structure, like a dictionary, it can be accessed by dot syntax like so
{{ product.price }}.

A value can also be a expression such as {{ 100 - product.price / product.list_price * 100}}.

<h1>{{ headline }}</h1>

<div class="price">{{ product.price }}</div>

<div class="list-price">{{ 100 - product.price / product.list_price * 100}}</div>

If-else statements

Flow control if supported via if-else statements denoted by curly braces and percent signs: {% and %}.

If-statements can be used to check simple booleans, numerical values and strings.

Some examples:

{% if product.on_sale %}
  On Sale
{% endif %}
{% if product.stock_count < 10 %}
  Only few in stock!
{% else %}
  Lots in stock.
{% endif %}
{% if product.vendor == "Awesome Shoes" %}
  These shoes are awesome!
{% endif %}
{% if product.title contains 'Pack' %}
  This product's title contains the word Pack.
{% endif %}

Statements can also be combined for more advanced logics:

{% if product.type == "Shirt" or product.type == "Shoes" %}
  This is a shirt or a pair of shoes.
{% endif %}

The available operators in Liquid are these:

OperatorDescription
==equals
!=does not equal
>greater than
<less than
>=greater than or equal to
<=less than or equal to
orShow if if x OR y is valid
andShow if x AND y is valid
containsShow if attribute contains a specific value

For-loops

Iterating over an array of values is done as follows:

{% for product in products %}
  {{ product.name }}
{% endfor %}

To make looping over a loop easier each loop has an associated loop object only available within the loop body with the following fields:

NameValue
loop.indexThe index of the loop iteration starting from 0.
loop.lengthThe total length of the loop ie. number of elements in the list there is iterated over.
loop.firsttrue if this is the first iteration of the loop else false.
loop.lasttrue if this is the last iteration of the loop else false.

Here is an example of using the loop object to write a comma-separated list of sizes for each product.

{% for size in product.sizes %}
 {{ size }}{% if not loop.last %}, {% endif %}
{% endfor %}
Small, Medium, Large, X-Large

Assigning Variables

You can assign variables in the template language assign keyword like this {% assign myvar = 123 + 456 %}.

Assigned variables will be available in the current scope (and all sub.-scopes) after the assign statement.

{% for product in products %}
  {% assign is_on_sale = product.price < product.list_price %}
  <h1>{{ product.name }}</h1>
  {% if is_on_sale %}
    <div class="on-sale-badge">On Sale</div>
  {% endif %}
{% endfor %}

Comments

Besides HTML comments (which will be inserted into the generated HTML) you can also use comments build into the template language that will only be visible in the template.

Comments are started with {% comment %} and ended with {% endcomment %}.

Formatters

Formatters can be used to format values before they are inserted into the page. Formatters are applied to a value by using |.

{{ product.price | money }}

Formatters can even be used with several arguments, if needed:

{{ product.price | cost product.list_price }}

Multiple formatters can be used by being chained after each other. They will be applied in the order they are listed reading from left to right.

{{ product.price | round | money }}

Clerk.js comes with these built-in formatters:

FormatterFunction
roundRounds to the nearest integer, like so {{ x | round }}.
pctGives you the difference in percentage between two numbers. Usage: {{ x | pct y }}.
moneyFormats a decimal number as currency using the US formatting rules.
Optional: The amount of decimals to be displayed can be altered by adding a number to the function.
Usage: {{ price | money 2 }}

Can also be configured for custom price-formatting with this syntax:
{{price | money 2 "," "."}}
money_euFormats a decimal number as currency using the EU formatting rules.
Optional: The amount of decimals to be displayed can be altered by adding a number to the function.
Usage: {{ price | money_eu 2 }}

Can also be configured for custom price-formatting with this syntax:
{{price | money_eu 2 "," "."}}
replaceReplaces a string with another eg {{ product.image | replace 'http://' 'https://'}}.
highlightHighlights part of a text by wrapping it in a span with a specified class. If no class is given then clerk-highlight will be used as the default class.

{{ name | highlight query 'my-query-highlight-class' }}
firstReturns the first element of a list {{ xs | first }}
lastReturns the last element of a list {{ xs | last }}
nthReturns a value from a list xs, based on the index given n, like so {{ xs | nth n }}
minReturns the lowest value from a list
maxReturns the highest value from a list

You can add you own formatter functions in two ways:

A formatter function takes one or more arguments and returns a string or number. Here is an example of our round formatter:

Clerk('config', {
  formatters: {
    round: function(x) {
      return Math.round(x).toString();
    },
    cost: function(price, price2) {
      if (price > price2) {
        return "This is a premium product on sale";
      }
      else {
        return "This is is a regular product";
      }
    }
});

Content Variables

When rendering the main template of a Content the following variables are always available:

VariableData
productsThe resulting products to be rendered in the content including all requested metadata.
responseThe full response object from the content API call.
contentAny values associated with the specific Content such as parameters or other data added later.
formattersAll formatters available for the content. To add custom formatters see Configuration.
globalsAll global variables avaliable for the Content. To add custom globals see Configuration.

To simplify the template language all the sub-keys of response, content, formatters and globals are merged into the root scope such that {{ globals.is_mobile }} can be accessed directly as {{ is_mobile }} or {{ response.count | formatters.round }} can be access directly as {{ count | round }}.

Thus response, content, formatters and globals can be considered namespaces that are only explicitly needed in terms of a name clash.

Global Variables

Any template will always have the globals configured under Configuration available as the value globals.

Clerk.js comes with these built-in Globals:

FormatterFunction
is_desktopEvaluates to true if the user browses using a screen size of 1024px or more
is_tabletEvaluates to true if the user browses using a screen size of between 768px - 1024px
is_mobileEvaluates to true if the user browses using a screen size of 768px or less

UI Component Variables

Each UI Component may add more variables to the root scope. If so this will be documented under the specific UI component.

JavaScript Methods

Some specific JavaScript methods are available directly in your Designs.

The following are currently supported:

MethodFunction
.split()Splits a string into an array based on the string given as an argument.

Usage: {{ product.name.split("-")}}

A specific index from the list can be returned by adding the index to the line:
{{ product.name.split("-")[0]}}