For basic overview of content templates, please refer to the Creative Template Overview document. Our templating language is based on the Shopify Liquid templating language; the reference material can be found on Liquid Website.

There are four paths to access data from templates in Zaius.

  • Customer data: Can be accessed using
    {{ customer.first_name }}
  • Event data from the segment behaviors: Can be accessed using
    {{ step1.product.name }}
  • Lookup data: Can be accessed using
    {% assign top_products = lookup.products(name, price).top(price) %}
  • Custom SQL Lookup: Can be accessed using
    {% assign top_custom_sort_products = custom_lookup(my_custom_product_sql_sorter) %}

This guide will walk through these four access paths.

Customer Data

All customer data can be access in any template using the field names on the customer object directly.

  • Hello {{ customer.name | default: "there" }}
  • {{ customer.custom_field }} - for any custom fields you have created for customers

If you have a custom dimension created with references to the customer (such as metros you have attributes on), you can reference them by linking table names together

  • {{ customer.metro.name }} The name of the metro associated with the customer

Segment Behavior data

Steps defined in the segment can have any of their attributes referenced in templates.

Behavioral steps 1 & 2 in the segment builder

Some examples of how to use a single attribute from these steps:

  • {{ behavior_name.step1.action }} returns the value 'add_to_cart' from the first step
  • {{ behavior_name.step1.product.name}} returns the name of the product abandoned
  • {{ behavior_name.step1.product.category.path }} returns the category path for the abandoned product

More advanced usage

{% assign recent_product_categories_with_ts = behavior_name.step1.list(product.category.path, ts).newest %}
{% for c in recent_product_categories_with_ts %}
  You browsed {{ c.product.category.path }} on {{ c.ts | date: '%B %-d, %Y' }}
{% endfor %}

Lookups

Lookups are a great way to access information not associated directly with an event from the segment or an attribute of the customer.

Example: List of the most expensive products

{% assign most_expensive_products = lookup.products(name, price).top(price) %}
{% for p in most_expensive_products %}
  {{ p.name }} - {{ p.price }}
{% endfor %}

You can also use Lookups to summarize events of all customers.

Example: most popular products:

{% assign popular_products = lookup.events(product.name, product.url, product.category.path).where(event_type = 'order' and action = 'purchase').top %}Everybody seems to like:
{% for p in popular_products %}
  {{ p.product.name }} ({{ p.product.category.path }}) - {{ p.product.url }}
{% endfor %}

Example: The most popular products in the category you browsed

{% assign popular_products_by_category = lookup.events(product.name, product.url).by(product.category.path).where(event_type = 'order' and action = 'purchase').top %}Because you browsed {{ behavior_name.step1.category.path }}, here are some things you might like:
{% for p in popular_products_by_category[behavior_name.step1.category.path] %}
  {{ p.product.name }} - {{ p.product.url }}
{% endfor %}

Requesting External Data

If you need to fetch data from an external source or API, you can use the curl() function to perform HTTP requests that return JSON responses. Curl supports GET and POST requests and will cache the response for each unique requests for up to 10 minutes by default unless otherwise specified.

{% assign result = curl('https://httpbin.org/post').post.body('{"example": {"ids": [1,2,3]} }').headers(content-type: 'application/json').cache(3600) %}
{{ result.origin }}

Bear in mind that Shopify Liquid does not allow }} or %} inside a quoted string, so if you are sending a json payload in the body, you have to put a space between pairs of closing braces. It also does not support string escaping so there is no need to escape a single backslash.

Cache TTL (time to live) can be specified in seconds. For example, adding .cache(3600) will cache a response for up to 1 hour. Because we render email messages in parallel you can expect to see multiple requests even if you specify a long cache TTL.

You can insert liquid variables inside a request body, url, or header value. To insert liquid into a string value, surround it with {$ and $}:

{% assign my_ids = '[1,2,3]' %}
{% assign result = curl('https://httpbin.org/post').post.body('{"example": {"ids": {$ my_ids $} } }').headers(content-type: 'application/json') %}
{{ result.data }}OUTPUT: {"example": {"ids": [1,2,3] } }

It's important to note that when sending messages to a large audience there can be hundreds of thousands of messages rendered per minute. If your API requests are all unique or you reduce the cache time, your API will need to be able to handle the volume or it will slow down email sending.

If your API returns and error, the liquid response object will be an empty object. It is recommended to check for the existence of your response data and choose to abort the email if the data is required.

Custom SQL Lookups

For those that want to go crazy! (please contact your customer success manager) - for use in places where you have your own scoring, results filtering or something you think may be a good idea but can't figure out how it could be done.

Example: Top products within a metro and a custom scoring/filtering applied

{% assign products_of_interest_by_metro = custom_lookup(products_of_interest_by_metro) %}
{% for product : products_of_interest_by_metro[customer.metro_id] %}
  {{ product.name }}
{% endfor %}

Syntax Reference

Customer Data

customer.
column_name

Behavior Data

step[n].
[ list ].
[ customer | product | event |  { ( column_list,... ) } ].
[ top | bottom | newest | oldest ].
[ limit(#) ]

Lookups

lookup.
[ customers | products | events |  { ( column_list,... ) } ].
[ by ( column_list,... ) ].
[ where ( expression [ AND|OR expression ] ) ].
[ top | bottom | newest | oldest ].
[ limit(#) ]

Operators supported in where clauses

( =~ | !=~ | = | != | >= | <= | <> | > | < | is | is not )

=~ (matches) use '*' for wildcards '*foo*'


Time in expressions can be represented in these different ways:

.where(ts > now())
.where(ts > now(-3600))
.where(ts > 1475602497)
Did this answer your question?