Advanced Liquid capabilities in ODP

  • Updated

Optimizely Data Platform (ODP) lets you add dynamic content to your emails through personalization tags and configure dynamic grids to inform content based on the actions customers are taking. You can also script additional complexities into your dynamic content when you need options outside of the provided configurations. 

The ODP templating and personalization language is based on the Shopify Liquid templating language.

Behaviors

Dynamic grids automatically configure the Liquid required to pull the necessary content. To see a quick example, drag a dynamic grid into an email, choose any behavior and click Convert to Liquid.

convert-to-Liquid.png 

Liquid-conversion.png

  • behavior – This tells ODP that the message is querying for a behavior.
  • cart_abandonment – The identifier for the behavior. To find this manually, go to Behaviors and see if the checkbox for Make available for use in content templates is checked. The identifier, called the Content Reference Key, will be displayed.
  • range_start – The dynamic timestamp to use as the earliest timestamp a customer could have performed the first step of the behavior. Use auto to let ODP determine this automatically based on the campaign configuration. Otherwise, specify an offset from now in seconds. For example, now(-604800) would be 604800 seconds (1 week) before the customer sees the message.
  • range_end – The dynamic timestamp to use as the latest timestamp a customer must have performed the first step of the behavior. Using now(0) is most common because it indicates that a user must have performed the first step of the behavior before the campaign  was sent. Otherwise, specify an offset from now in seconds.
  • required – Further filter the audience by requiring that customers must have completed the behavior at least once to be able to qualify for the campaign. Use true if the behavior is important for the content (such as when showing cart abandoned products in a cart abandonment campaign). Use false if it is not required that a customer completed the behavior.
  • filters: array('z_content_shield_filter') – A comma-separated list that further filters down the users to only those that match the behavior for products that match the additional filter(s). By default, this includes the z_content_shield_filter, which indicates that the Content Shield Filter is being applied. It can also use other product filters. Note: you can only use filters with product-based dynamic grids.
  • step1 – Pulling content from a specific step of the behavior. If a browse abandonment behavior is defined by users who PDP View (step1) and then do not Order that product (step2), specifying step1 tells ODP to pull data from the PDP View event. Always use a step with a positive match. ODP has no event to pull data from if the step is a negative match.
  • list.product(image_url, name, price) – A list of all matching behaviors, as well as which fields to pull. Typically this data is pulled from the product dimension. If data is needed at the event level, place the fields directly after list (e.g., list(event_type, action)).
  • top – This specifies the sort order for the data returned. Use top to sort by frequency of match (e.g., to show the products that were viewed the most). Use newest to sort by recency of match (e.g., to show the most recently cart abandoned products first).
  • limit(4) – This provides the maximum number of results to return. The highest value this can be is 20.

You cannot use behaviors in the first touchpoint of event-triggered behavior or transactional campaigns. Since the first touchpoint is sent to customers immediately upon being triggered, there is no time to pull additional complex datasets from the database.

Lookups

You can use Lookups to pull data directly from objects (tables) in the Optimizely database.

For example, you could pull the most expensive products:

Liquid-conversion-ex2.png

  • lookup: This tells ODP that the message is querying for a lookup.
  • products(name, price): This specifies the object from which the data is being pulled, and also the fields which are being requested.
  • where(name =~ "*shirt*" and price < 300): This filters down the matches as specified. In this example, only products with "shirt" in the name, that have a price under $300, will match the lookup. If filtering on timestamp fields, the match can be based off of now (e.g., ts > now(-3600) would match timestamps in the last hour), unix timestamps (e.g., ts > 1234567890 would match timestamps after 2009-02-13 at 11:31pm UTC), or user-friendly dates (e.g., ts > '2016-09-01T00:00:00' would match timestamps after 2016-09-01 at midnight UTC).
  • top(price): This specifies the sort order for the data returned. Use top or bottom to sort by the highest or lowest values of a given field. Note: If the object being queried is events, additional sort options are available by using newest (most recent events are returned first) or oldest (oldest events are matched first).
  • limit(3): This provides the maximum number of results to return. The highest value this can be is 20.

You cannot use Lookups in the first touchpoint of event-triggered behavior or transactional campaigns. Since the first touchpoint is sent to customers immediately upon being triggered, there is no time to pull additional complex datasets from the database.

cURL

cURL calls let you make API calls inside a message's content. This helps you to call data from a Google spreadsheet or send a customer update to a third-party system. Optimizely offers the API and Optimizely channels to make API calls even easier (for example, see Update customers’ SMS consent status, which outlines how to use the Optimizely channel to update a customer's consent when customers send a specific SMS message). If the API needs to occur within the content itself, you will need to use cURL.

Take a look at the following example.

Liquid-conversion-ex3.png

The goal is to update a customer attribute based on the dynamic content they were shown in an email. 

  • curl('https://api.zaius.com/v3/profiles'): This tells ODP that it is preparing an API call directed at a specified endpoint.
  • post: This is the type of API request; typically post or get.
  • body('{"attributes": {"email":"{$ customer.email $}","last_shown_product_id": "{$ product.product_id $}"}}'): This is the body of the request. In this case, the customer fields that are being updated. Note that in this example, last_shown_product_id would need to be added as a custom field on the customer object (see this doc on creating custom fields), and that product is a variable assigned in Liquid that, separately, was supplied with a product_id (e.g., via a behavior or lookup call).
  • headers(content-type: 'application/json',x-api-key: 'my_api_key'): This tells ODP the headers to use on the Optimizely call. In particular, make sure to specify the content-type and any necessary API keys.
  • cache(0): This is the amount of time to cache the returned data. If you need to always receive perfectly fresh data, use 0.

Other Optimizely-specific data

Optimizely makes several additional fields available. For instance, you can use a field for your company address in an email footer based on the value you provided in the Admin area. This ensures that all your footers are automatically updated if the information changes in the Admin area.

Message-related information:

  • {{campaign.id}}
  • {{campaign.name}}
  • {{content.id}}
  • {{content.name}}

Account-level (these are the account values specified on the Admin > Company Info page):

  • {{zaius.account.site_url}}
  • {{zaius.account.company_address}}
  • {{zaius.account.company_name}}