Skip to main content
Skip table of contents

Look-Ups

Lookups in applications are used to represent a set of codes and their translated meanings. Let’s have a look at the available lookup tags within ZML:

Resource Lookups

To add details from specific resources to your content instead of relying on recommendations, you can use the resource look-up merge tags. Resources can be retrieved with either a single resource lookup or by querying for multiple resources.

Resource Filters

Resources are defined at the site level using custom schema, so this documentation will rely on sample concepts that you can apply to your account’s actual data set.

There are two ways to apply filters to resources:

  1. ZML tags ({% recommendation %}, {% resources %}) — written on the fly inside campaigns, templates, and snippets by ZMP users. Filters are expressed inline as simple name, operator, value triplets.

  2. Resource Groups UI — where users visually build filter rules in the ZMP. These saved groups can then be referenced by uid inside specialized ZML tags.

When a ZML tag runs, inline filters are sent to the API as simple JSON arrays ([{name, operator, values}]). Resource Groups created through the UI are stored as structured filter expressions on the backend and referenced by their unique ID.

Group filters created in the UI can be referenced inside ZML tags via the group_filters: option, bridging both approaches.

ZML Tag: {% resources %}

The full syntax of the {% resources %} tag can be used in various permutations to fetch resources (content items) directly, without personalization. It is recommended to add the resource type as an additional parameter for faster lookup performance during campaign delivery.

CODE
{% resources <variable_name>
  | count: <number>
  | filter: '<field_name>', '<operator>', '<value1>|<value2>|...' --cannot be mixed
  | sort_field: '<field_name>'
  | sort_order: '<asc|desc>'
  | group_filters: '<group_filter_uid1>', '<group_filter_uid2>', ... --cannot be mixed
  | expression: (OR, (AND, '<group_filter_uid1>', '<group_filter_uid2>'), '<group_filter_uid3>') --cannot be mixed, given top priority if other filter types are also used in a single tag
%}

Options:

A {% resources %} tag can only filter on one of the following types at a time: expression, group_filters, filter. If all are present, only the expression will be used to return resources.

Option

Required

Multiple

Description

<variable_name>

Yes

Variable name to store results in.

count

No

Last wins

Number of items to return. Max 10 (best practice).

filter

No

Append

Inline filters using name, operator, value triplets.

Filters are case-sensitive and should be in ALL CAPS.

Multiple filter: options are AND'd together.

sort_field

No

Last wins

Field to sort by. Special values: bt_updated_at, recency, bt_statistics.viewed.cumulative.P7D, bt_statistics.viewed.cumulative.P1D.

sort_order

No

Last wins

'asc' or 'desc'. Only applies when sort_field is a custom field in the account-level schema.

group_filters

No

Append

Named filter UIDs. Multiple group filters can be named with an implicit OR operator.

expression

No

Last wins. Use operators to call more than one resource group.

CODE
AND, '<group_filter_uid1>', '<group_filter_uid2>'

Complex logical combination of group filter UIDs. Accepts AND/OR operators at the beginning of the expression.

In this example, the user is pulling the 3 resources where the resource type is an article or product that was published in the last 1 day. You can then print the resources using the adrec variable, including data that’s nested inside the resource.

CODE
{% resources adrec
  | count: 3
  | filter: 'resource-type', '=', 'article|product'
  | filter: 'pubDate', 'AFTER', '-P1D'
  | sort_field: 'pubDate'
  | sort_order: 'desc'
%}

Filter Syntax

Each filter: option follows a pattern of three parts, comma-separated:

CODE
filter: '<field_name>', '<operator>', '<value1>|<value2>|...'

Position

Name

Required

Description

1st

Field name

Yes

Schema field name (e.g. 'resource-type', 'pubDate', 'category').

2nd

Operator

No

Can be omitted entirely (see examples below).

3rd

Value(s)

Yes

One or more values. Multiple values separated by pipe |.

Parsing details:

  • Quotes (' or ") around field names, operators, and values are stripped during parsing.

  • Values are always split on pipe (|) into an array.

How the operator position works:

There are three cases — with an operator, without an operator, and with an explicitly empty operator. They behave differently:

With an operator (3 comma-separated parts):

CODE
| filter: 'category', '=', 'shoes|boots'

All three parts are present: field name category, operator =, values shoes and boots.

Without an operator (2 comma-separated parts):

CODE
| filter: 'category', 'shoes|boots'

Only two parts: field name category and values shoes and boots. No operator is sent in the payload.

With an explicitly empty operator (3 parts, the middle one is ''):

CODE
| filter: 'category', '', 'shoes|boots'

Three parts, but the middle one is an empty string. In {% resources %}, this is normalized to =. In {% recommendation %}, no operator is sent.

Important: filter: 'resource-type', 'article' has two comma-separated parts — resource-type is the field name and article is the value. This is the "without an operator" case, not the "empty operator" case.

More examples:

CODE
| filter: 'pubDate', 'AFTER', '-P7D'               → operator: AFTER, values: ["-P7D"]
| filter: 'price', 'BETWEEN', '10|99.99'           → operator: BETWEEN, values: ["10", "99.99"]
| filter: 'title', 'CONTAINS', 'sale|clearance'    → operator: CONTAINS, values: ["sale", "clearance"]
| filter: 'title', 'NOT', 'draft|archived'         → operator: NOT, values: ["draft", "archived"]
| filter: 'featured', '=', 'true'                  → operator: =, values: ["true"]

Resources vs Recommendations ZML Tag Comparison

There are some slight differences in the ZML tag syntax for resources and recommendations, specifically around operator case.

Operator

{% resources %}

{% recommendation %}

Notes

=

Yes

Yes (any string passes)

EQUAL

No (not in allowlist)

Yes (passed through)

Use = instead in {% resources %}

OR

No (not in allowlist)

Yes (passed through)

Not in the {% resources %} allowlist

NOT

Yes

Yes

CONTAINS

Yes

Yes

AFTER

Yes

Yes

BEFORE

Yes

Yes

BETWEEN

No (not in allowlist)

Yes (passed through)

Silently dropped in {% resources %}

EXISTS

Yes

Yes (passed through)

Case-sensitivity

Operator must be UPPERCASE to pass validation: CONTAINS, AFTER, BEFORE, NOT, EXISTS, =. Lowercase like after will be silently dropped.

No validation — any string passes through. The API is similarly case-insensitive.

 

Specific Resource Lookup

To return an individual resource, use the resource ID. It is recommended to add the resource type as an additional parameter for faster lookup performance during campaign delivery.

CODE
{% resource product
  | id: sku
  | resource_type: 'item'
 %}

This tag creates the object {{product}}and assigns the contents of the resource object to it.

If you want to populate the title of the resource in the content, use {{product.title}}.

Resource Query Parameters

Parameters

Description

id

Specify the resource ID you’re trying to retrieve.

resource_type

Specify the resource type.

Multiple Resource Query

Retrieving multiple resources without the personalization help of our Recommendations engine is done with a resource query. Here is an example of a resources tag:

CODE
{% resources products
| count: 3
| filter: 'resource-type', '=', 'article|product'
| filter: 'pubDate', 'AFTER', '-P1D'
| filter: 'category', 'CONTAINS', 'baseball'
| sort_field: 'start_date'
| sort_order: 'asc'
%}

Resources Query Parameters

To evaluate a parameter, the value must be part of the resources schema and not a property passed by the user.

Parameters

Description

count

Specify the number of resources to be returned in your query.

filter

The one or more resource fields to query against.

sort_field

The timestamp field to sort the returned array on. No other data type is supported.

CODE
recency,
bt_updated_at, 
field, 
bt_statistics.viewed.cumulative.P7D,
bt_statistics.viewed.cumulative.P1D

field requires field_name in the query

sort_order

The order in which the array of resources will be returned.

Points to Remember

CODE
{% resources my_product
| count: 3
| filter: 'resource-type', 'CONTAINS', 'product'
| sort_field: 'bt_updated_at'
| sort_order: 'desc'
%}
  • Operator names should be in uppercase. In this example, use 'CONTAINS' instead of 'contains.'

  • Variable names should be unique and differentiated from other variables and values within the tag. In this example, since ‘product’ is used as a value, do not use that as a variable name elsewhere.

  • v=Variable names should not conflict with property names that may be available on the profile.

  • Filters have very specific formats that must be respected when building your query. For example, sku_last_updated GREATER THAN 13 hours ago won’t return any results because it’s not a valid format; instead, use  'sku_last_updated', 'BEFORE', '-PT13H'.

  • Filters for bt_created_at and bt_updated_at are only supported for resources uploaded after .

Resources

Resources, also known as feeds/catalogs, are product listings of a client’s domain like e-commerce, arts, banking, and more. This list is synced to ZMP daily.

Variants

Variants are sub-products, or child nodes, of the same product.

Default Product

Variant Product: (Blue Highlight)

ZMP will result in only very few products in the resources' graphical UI. So, to identify and analyze all the data available in resources, we are using the following liquid syntax as a solution:

Results in Resources UI

Resource Lookup Syntax

CODE
{% resource product | id: "9097" %}
<br>product=>{{product}}}<br>

Resource with Variant Lookup Syntax

CODE
{% resource product | id: "9097" %}
{% assign get_v_p = product["variants"]["100083508"] %}
<br>Variant=>{{get_v_p}}<br>

Event Lookups

Trigger Event Object

For content being sent from a triggered campaign, an event object is available to populate information in content from the event that triggered the campaign. The properties available in the event are the same properties passed in the payload of the event. Take the following purchased event as an example:

Purchased Event Payload

{

"session": "afb35e24-37a9-40b4-96e5-7eb937c064e5",

"last_purchased":

{ "items": [

{

"productsku": "J9834RHJ",

"productname": "Some Cool Pants",

"quantity": 1,

"price": 45.68

}

],

"total": 45.68,

"cartuserdata": {

"first_name": "Ryan",

"last_name": "Malone",

"email": "rmalone@zetaglobal.com"

}

}

}

To populate the productname information from the first item in this purchased event, we can use the following event object:

Input

You bought: {{event.purchased.last_purchased.items[0].productname}}

Output

You bought: Some Cool Pants

Event Lookup Tag

Multiple past events can also be used in content using an event lookup tag.

The following example creates a variable called purchases as an array of the last three purchase events for the given user_id the message is being created for. The full contents of the array can be viewed in content using {{purchases}} or a for loop to iterate over the array to find the details you need.

Input

CODE
{% event purchases | event_type: 'purchase' | count: 3 %}
{% for purchase in purchases %}
    {{purchase}}<br/>
{% endfor %}

The event_type parameter can be changed to retrieve events of the specified name. The count parameter sets the limit on the number of past events to be retrieved.

Event Lookup Tag Query Parameters

Parameters

Description

event_type

The exact name of the account event to look up.

count

Specify the number of past events to be retrieved.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.