Useful Jinja snippets

This article provides reusable Jinja code snippets for common tasks in Bloomreach. Copy and paste these snippets into your own templates.

Format numbers and prices

Display price with 2 decimal places

Use this snippet to force prices to display with 2 decimal places.

{{ "%0.2f" | format(item.price | float) }}

Format price with custom separators

Use this macro to format prices with custom thousand and decimal separators.

{%- macro format_price(price, thousand_separator=',', decimal_separator='.', decimal_places=2) -%}
{%- set price_as_string = price | string -%}
{%- set price_split = price_as_string.split('.') -%}
{%- set price_integer = price_split[0] -%}
{%- if price_split | count > 1 -%}
{%- set price_fraction = price_split[1] -%}
{%- if price_fraction | length < decimal_places -%}
{%- set price_fraction = price_fraction.ljust(decimal_places, '0') -%} 
{%- else -%}
{%- set price_fraction = price_fraction[:decimal_places] -%}
{%- endif -%}
{%- else -%}
{%- set price_fraction = '' -%}
{%- endif -%}
{%- set formatted_price_integer = price_integer | reverse | batch(3) | map('join', '') | join(thousand_separator) | reverse -%}
{%- if price_fraction != '' -%}
{%- set formatted_price = formatted_price_integer ~ decimal_separator ~ price_fraction -%}
{%- else -%}
{%- set formatted_price = formatted_price_integer-%}
{%- endif -%}
{{- formatted_price -}} {%- endmacro -%}

Sample outputs

{{ format_price(1.2) }}

Returns: 1.20 (2 decimal places)

{{ format_price(1234.5) }}

Returns: 1,234.50 (comma and 2 decimal places)

{{ format_price(1234) }}

Returns: 1,234 (comma only)

Round number down with precision

{{ 42.55 | round(1, 'floor') }}

Returns: 42.5

Format phone numbers

Format phone number with separators

Phone numbers tracked as integers (for example, 9652508952) can be formatted as +7 (965) 250-89-52.

+7
(
{{ customer.mobile_phone[:3] }}
)
{{ customer.mobile_phone[3:6] }}
-
{{ customer.mobile_phone[6:8] }}
-
{{ customer.mobile_phone[8:10] }}

Replace the country code 7 with your desired country code. You can also replace hyphens with spaces if preferred.

Remove symbols and leading zeros from phone number

Use this filter to convert any phone number format to raw format by removing symbols, spaces, and leading zeros.

{{ customer.phone | replace(' ','') | replace('+','') | replace('(','')| replace(')','') | replace('-','') | int }}

Work with customer attributes

Display customer attribute with fallback value

Use a fallback value when a customer attribute might be empty.

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

Calculate customer age

Use this snippet to calculate a customer's age from their date of birth. This calculation has a 1-year tolerance because it doesn't account for months and days.

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

📘

Note

The customer.date_of_birth value must be a string in YYYY-MM-DD format (for example, 2017-01-31).

Work with email addresses

Get email domain

Use this snippet to extract the domain from an email address.

{{ customer.email.split('@') | last }}

Convert email to lowercase

Use this snippet to convert an email address to lowercase. This is useful for REST API requests.

"email_id": {{ customer.email | lower | json }}

Work with timestamps

Format UNIX timestamp after adding or subtracting time

{{ (time + 604800) | from_timestamp('%d-%m-%y') }}

📘

Note

Timestamp values must always be in seconds. The system doesn't automatically recognize milliseconds based on character count.

Calculate time 2 days before departure

Use these snippets to calculate timestamps and time differences.

Calculate timestamp 2 days before departure_time:

{{ event.departure_time - 2 * 86400 }}

Calculate time difference (time to wait from now):

{{ event.departure_time - 2 * 86400 - time }}

Calculate time difference in hours (for use in wait nodes in scenarios):

{{ (event.departure_time - 2 * 86400 - time) / 3600 }}

Calculate optimal sending time

Use this snippet to calculate optimal sending time based on an On Event trigger.

{% set hour = event.timestamp | from_timestamp('%-H') | int %}
{% set minute = event.timestamp | from_timestamp('%-M') | int %}
{% set minutes = hour * 60 + minute | int %}
{% set optimal = customer.hour * 60 | int %}
{% if optimal < minutes %}
  {{ 1440 - minutes + optimal }}
{% elif optimal > minutes %}
  {{ optimal - minutes }}
{% else %}
  0
{% endif %}

Adjust time from UTC for daylight saving time

Use this snippet to adjust time from UTC according to winter and summer time.

{% set timestamp = time %}
{% set month = timestamp | from_timestamp('%-m') | int %}
{% set weekday = timestamp | from_timestamp('%w') | int %}
{% set dayofmonth = timestamp | from_timestamp('%-d') | int %}
{% if month < 3 or (month == 3 and dayofmonth < 25) %}
  {% set timezone_difference = 3600 %}
{% elif (month == 3 and weekday < (dayofmonth - 24)) %}
  {% set timezone_difference = 7200 | int %}
{% elif month == 3 %}
  {% set timezone_difference = 3600 | int %}
{% elif month < 10 %}
  {% set timezone_difference = 7200 | int %}
{% elif (month == 10 and weekday < (dayofmonth - 24)) %}
  {% set timezone_difference = 3600 | int %}
{% elif month == 10 %}
  {% set timezone_difference = 7200 | int %}
{% else %}
  {% set timezone_difference = 3600 | int %}
{% endif %}

Output time in correct time zone

{% set timezone = 'Europe/Bratislava' %}
{% set offset = (timeValue - timeValue | from_timestamp('%x %X %Y') | to_timestamp('%x %X %Y', timezone=timezone)) | round %}
{% set calculated_time = time + offset %}
{{ calculated_time | from_timestamp('%x %X') }}

Use conditional logic

Create conditional content based on segmentation

Use this snippet to display different content based on customer segmentation.

{% if segmentations['segmentationId'] == "Group Name" %}
  your HTML content for subscribers from "Group Name" segment
{% else %}
  your HTML content for the rest of the customers
{% endif %}

Stop execution for specific customers

Use the {% abort %} command to stop code execution for customers who meet specific conditions.

For example, using {% abort %} in an email node prevents the email from sending and stops the scenario from continuing to subsequent nodes for that customer. You can view abort runs in the scenario's test tab by hovering over the email node.

{% abort %}

To abort an action and track the reason, use:

{% abort: "Custom message" %}

This adds a campaign event with status aborted and includes the custom message in the message property. The custom message can be any Jinja expression, allowing you to specify why the action was aborted for a particular customer.

📘

Note

The abort tag is available in non-action nodes (conditions, wait nodes, and limits), but no event is added even if a reason is provided.

Work with catalogs

Select single item by ID

Use this snippet to select one item from a catalog using its ID.

{% set item = catalogs.myCatalog.item_by_id('item_id_1') %}

Select multiple items by ID list

Use this snippet to select multiple items using a list of IDs.

{% set items = catalogs.myCatalog.items_by_id(['item_id_1', 'item_id_2', 'item_id_3']) %}

Output multiple catalog values for item IDs

Use this snippet for cart abandonment emails when you have a list of items from the customer's last cart update.

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

If you work with JSON instead of a simple list, specify the product when setting the item.

Access catalog information efficiently

Use a single catalog call instead of multiple calls to avoid template rendering timeout errors.

{%- set cart_item_ids = ['id_1', 'id_2', 'id_3', 'id_4', 'id_5'] -%}
{%- set items = [] -%}
{%- set catalog_items = catalogs['cat_name'].items_by_id(cart_item_ids) -%}
{%- for item in catalog_items if item['active'] in [true, 'True', 'yes'] -%}
  {%- append item to items -%}
{%- endfor -%}

To reference the item_id in the loop (for example, to check if the item is not in an exclusion list):

{%- set excluded_product_ids = ['id_3', 'id_4', 'id_5'] -%}
{%- set cart_item_ids = ['id_1', 'id_2', 'id_3', 'id_4', 'id_5'] -%}
{%- set items = [] -%}
{%- set catalog_items = catalogs['cat_name'].items_by_id(cart_item_ids) -%}
{%- for item in catalog_items if item['active'] in [true, 'True', 'yes'] -%}
  {%- set item_id = cart_item_ids[loop.index0] -%}
  {%- if item_id not in excluded_product_ids -%}
    {%- append item to items -%}
  {%- endif -%}
{%- endfor -%}

Parse item ID from cart update

Use this snippet to parse item_id from an object in a cart update aggregate.

{% for product in aggregates['AGGREGATE_ID'] %}
  {% set item = catalogs.CATALOG_NAME.item_by_id(product.VARIANT_ID) %}
  <img src="{{ item.image_url }}">
  {{ item.product_title }}<br>
  {{ item.price }}
{% endfor %}

Work with reports

Get all items from a report

Use this snippet to retrieve and sort all items from a report.

{% set x = reports[reportId].rows | sort(attribute=attrNumber, reverse=True) %}
actionToDoWithItem("{{ x[itemNumber][attrNumber] }}");

Get specific items from a report with catalog lookup

Use this snippet to take items 2–4 from a report and look them up in a catalog based on the first column (item_id). This is useful for displaying best-selling products without using recommendations.

{% set report_list = reports['Report ID'].rows | sort(attribute=1, reverse=True) %}
{% for item in report_list %}
  {% if (not loop.first) and (loop.index < 5) %}
    {% set product = catalogs['Catalog name'].item_by_id(item[0]) %}
    {{ item[0] }} = {{ product.name }}<be>
  {% endif%}
{%endfor%}

Configure wait times in scenarios

Create random dynamic wait time

Spread email sending over 3 hours:

{{ range(0, 180) | random }}

Create 60 chunks, 10 minutes apart:

{{ (range(0, 60) | random) * 10 }}

Calculate wait time in business days

Use this snippet to set wait time in business days. The example sets 9 business days—change this by replacing 9 in {% for counter in range(0, 9) %}.

{% set calculated_time = time %}
{% for counter in range(0, 9) %}
  {% set calculated_time = calculated_time + 86400 %}
  {% if (calculated_time | from_timestamp('%w')) | int == 6 %}
    {% set calculated_time = calculated_time + 172800 %}
  {% elif (calculated_time | from_timestamp('%w')) | int == 0 %}
    {% set calculated_time = calculated_time + 86400 %}
  {% endif %}
  {% if loop.last %}
    {{ (calculated_time - time) / 86400 }}
  {% endif %}
{% endfor %}

Work with customer IDs

Use multiple IDs for webhooks

Use this snippet to handle multiple customer ID types in REST API requests.

"customer_ids": {
  {% if customer_ids.registered %}
    "registered": {{ customer_ids.registered | json }}
  {% elif customer_ids.email_id %}
    "email_id": {{ customer_ids.email_id | json if customer_ids.email_id is string else customer_ids.email_id | first | json }}
  {% elif customer_ids.phone_id %}
    "phone_id": {{ customer_ids.phone_id | json if customer_ids.phone_id is string else customer_ids.phone_id | first | json }}
  {% else %}
    "cookie": {{ customer_ids.cookie | json if customer_ids.cookie is string else customer_ids.cookie | first | json }}
  {% endif %}
}

Select first cookie of a customer

{{ customer_ids.cookie if customer_ids.cookie is string else customer_ids.cookie | first }}

Count cookies

Use this snippet to count the number of cookies associated with a customer.

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

Check if registered identity matches lowercase email

{{ customer_ids.registered == (customer.email | lower) }}

Work with lists and arrays

Remove duplicates from multiple arrays

Use this snippet to combine multiple recommendation arrays and remove duplicates.

{% set reco_1 = recommendations('59df6b8bfb60098bb6f21188', 10) %}
{% set reco_2 = recommendations('59e0cc81fb600959f3898f53', 10) %}
{% set all_item_ids = [] %}
{% for item in reco_1 %}
  {% append item.item_id to all_item_ids %}
{% endfor %}
{% for item in reco_2 %}
  {% append item.item_id to all_item_ids %}
{% endfor %}
{% set unique_item_ids = (all_item_ids | unique) %}
{% set final = [] %}
{% for item in unique_item_ids %}
  {% set item_final = catalogs.products.item_by_id(item) %}
  {% append item_final to final %}
{% endfor %}
{% for item in final %}
  ...
{% endfor %}

Remove items from list

Use the list.pop() method to remove an item from a list. If you don't know the item's index, use list.index() to find it.

{% set x = [10, 20, 30] %}
{% set indx = x.index(20) %}
{% set dummyVar = x.pop(indx) %}
{{ x }}

Returns: [10, 30]

Get mode (item with highest occurrence)

Use this snippet to find the item with the highest occurrence in a list.

Arguments:

  • list_to_count (required) — list of items whose values you want to count.
  • sorting_type (optional) — order for the resulting list (asc, desc, or unsorted).
  • size (optional) — number of items to return in the list.
{%- set list_to_count = [3, 5, 5, 7, 3, 5, 8, 5] -%}
{%- set sorting_type = 'asc' -%}
{%- set size = 3 -%}
{%- set unique_values = list_to_count | unique -%}
{%- set unique_values_count = [] -%}
{%- for value in unique_values -%}
  {%- append {"value": value, "count": list_to_count.count(value)} to unique_values_count -%}
{%- endfor -%}
{%- if sorting_type == 'desc' -%}
  {%- set reverse = True -%}
{%- elif sorting_type == 'asc' -%}
  {%- set reverse = False -%}
{%- else -%}
  {%- set reverse = None -%}
{%- endif -%}
{%- if reverse is not none -%}
  {%- set unique_values_count = unique_values_count | sort(attribute="count", reverse=reverse) | list -%}
{%- endif -%}
{%- if unique_values_count | length > 0 -%}
  {%- if (size is number) and (size >= 0) -%}
    {%- set unique_values_count = unique_values_count | batch(size) | list -%}
    {%- set unique_values_count = unique_values_count[0] -%}
  {%- endif -%}
{%- endif -%}

Usage examples:

{{ unique_values_count }}

Returns the whole array.

{{ unique_values_count[0] }}

Returns the first item (for example, {'count': 12, value: 'Hello'}).

{{ unique_values_count[0].value }}

Returns the value of the first item (for example, Hello).

{{ unique_values_count[0].count }}

Returns the occurrences of the first item (for example, 12).

Use advanced techniques

Convert string from JSON

Use this filter to convert a string from JSON format.

item.str | from_json

Detect gender from last name (Slovak/Czech)

Use this snippet to detect gender based on Slovak or Czech naming conventions.

{{ "female" if (customer.last_name | reverse)[:3] | reverse | replace('á', 'a') == "ova" else "male" }}

Hash emails with key and time

{{ (customer.email ~ 'some secret key' ~ (time | from_timestamp('%m')) ~ (time | from_timestamp('%Y'))) | hash('sha1') | b64encode }}

Hash a string

Use these snippets to hash a string using SHA1 or MD5.

Get the SHA1 hash:

{{ 'test1' | hash('sha1') }}

Get the MD5 hash:

{{{ 'test1' | hash('md5') }}

Generate random unsigned

Use this snippet to generate a random unsigned long integer.long number

{%- set requestId = 0 -%}
{%- for index in range(0, 8) -%}
  {%- set randomByte = range(0, 256) | random -%}
  {%- set requestId = requestId * 256 + randomByte -%}
  {%- if loop.last -%}
    {{- requestId -}}
  {%- endif -%}
{%- endfor -%}

Build JSON for API requests

When making JSON API requests, build the request as a dictionary in Jinja and serialize the entire object.

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