Personalization in Jinja

Lot of features in Exponea enable the use of personalization via jinja. This enables to replace text in various parts by calling customer attributes, catalog items, etc. Full jinja documentation can be found at and this guide summarizes some of the common examples. Some of the examples can also be found in personalization in e.g. email templates.


Jinja can be used for different use-cases, including:

  • calling user attributes and inserting these values to text. This enables to easily start the emails, etc. with customer's first name.
  • referencing catalogs, aggregates, reports or other features of Exponea in e.g. weblayers
  • creating scripts including conditions, cycles, filters, changing the format of displayed data, etc.


In Exponea, most common Jinja uses include Jinja expressions, that are called using {{ .... }} tags, and statements, that are called using {% ... %} tags

Global variables in Jinja

Campaigns and Project have variables. Variables such as ID and name can be used for personalization in campaigns.

Project variables are accessible through all campaigns (Scenario, Banner, Experiments, Tags)
{{ }} - id of the project
{{ }} - name of the project
{{ }} - id of thescenario
{{ }} - name of the scenario
{{ }} - id of the action node in Scenario where the Jinja was executed
{{ }} - name of the action node in Scenario where the Jinja was execute
{{ }} - id of the banner
{{ }} - name of the banner
{{ }} - id of the variant
{{ }} - name of the variant
{{ }} - id of the experiment
{{ }} - name of the experiment
{{ }} - variant id of the experiment
{{ }} - variant name of experiment
Tag manager
{{ }} - id of the tag
{{ }} - name of the tag


Usually, statements are used when simply referrencing some parts of Exponea, with uses below. Basic syntax is usually {{ reference.attribute }}, however when the attribute consists of more words, the syntax has to be {{ reference["reference attribute"] }}

  • customer attributes - customer attributes will return the value that is stored in the customer profile for the specified attribute. Basic syntax is {{ customer.attribute }}
  • event trigger attributes - When a scenario is triggered by an event, you can refer to its attributes using {{ event.attribute }}. Please note that always "event." has to be used, not actual name of the event.
  • webhook response - Basic syntax is {{ }} or {{ webhook["JSON object key"] }}
  • metrics - referenced by {{ metrics("metric ID") }}
  • reports - it is possible to return a value from a report based on rows and columns. The syntax is {{ report_value_by_key("Report ID", "row value", "column value", metric order) }} . If you don't have columns or rows, you can skip the value. Metrics start counting from 0, and when you don't imput any value, it will get first metric by default.
  • Catalog items are referenced by {{ item["catalog attribute]" }}. Please note that for this to work, you need to define item first, please see below in statements
  • Recommendation items are referenced by {{ item["catalog attribute]" }}. Please note that for this to work, you need to define "item" first, please see below in statements
  • Surveys are referenced by {{ survey["survey name"] }}. This will generate a hyperlink
  • Unsubscribe link is generated by {{ email.unsubscribe }}. This will bring customers to the unsubscribe page where they can unsubscribe from separate campaign groups
  • Link that will display the email in browser is generated by {{ email.view }}.
  • Other than that, it is possible to output some variables that were defined previously {{ variable }}
  • It is possible to use Math operators as well, such as +,-,*,/, however the expression has to be within one tag, such as {{ 1+1 }}

It is also possible to modify the output of the statement using filters that are defined after pipe | separator. Below are possible uses of the  filters

  • first, last, length
  • lower, upper
  • trim
  • json, from_json
  • from_timestamp('%y-%m-%d')
  • hash
  • b64encode, b64decode, urldecode, urlencode
  • round(value, precision=0, method='common')
    • common rounds either up or down
    • ceil always rounds up
    • floor always rounds down

These filters enable you to e.g. set an ID to lowercase email every time, ensuring that you will not generate multiple IDs (which are case sensitive) when customer decides to identify once with lowercase email and once with uppercase.


Statements in Jinja are operators that can work with data in multiple ways. It allows you to, for example:

  • use conditions with following syntax (If, else if, else) {% if condition %}value{% elif condition2 %}value2{% else %}value3{% endif %} This will enable you to have e.g. call back values if someone has empty attribute.
  • use cycles, enabling you to repeat an action several times. This is useful when working with list attributes or JSONs. Syntax is {% for variable in array %} action {% endfor %}
  • using variables using {% set variable = value %}, which is used when referencing a catalog item.

Use case examples

Don't execute an action for a specific customer

You can use the {% abort %} command which will stop executing code for a specific customer who meets the given conditions. For example, using {% abort %} in an email node in a scenario will prevent the email from sending and the scenario will not continue to consequent nodes (only for the specific customer). If used in an email, you will be able to see the abort runs in the scenarios test tab (when you hover over the email node). No event is tracked for abort for now.


Lowercase email_id (in REST API request)

"email_id": {{ | lower | json }}

If doing JSON API requests, it may actually make more sense to build the request as a dictionary in jinja and serialize the whole thing.

{{ {"customer": {"email_id": | lower}, "other_key": 42} | json }}

Get email domain

{{'@') | last }}

Calculate age of customer

when customer.date_of_birth is string in format 2017-01-31
calculated age has 1 year tolerance (does not count with months and days)

age = {{ time | from_timestamp('%Y') -  customer.date_of_birth.split('-')[0] }}

Count cookies

cookie_cnt = {{ (1 if customer_ids.cookie is string else customer_ids.cookie | length) if customer_ids.cookie else 0 }}

Having a fallback if a customer attribute doesn't have a value

{% if customer.first_name %} {{customer.first_name}} {% else%}Sir/madam{% endif %}

Outputting multiple catalog values for a list of item IDs

This is usually used in cart abandonment, when you have a list of items in a customer aggregate, where it is taken from last cart update of customer. If you work with JSON and not a simple list, you need to further specify product when setting item.

{% set items = catalogs["catalog name"].items_by_id(list_of_ids) %}
{% for item in items %}
  {{ }} {{item.price}} 
  <img src="{{item.image_source}}"/> 
{% endfor %}