Overview
Related data sets store additional records for your contacts, for example purchases, bookings, or store locations. You can use this data in messages in three ways:
Insert a value: A placeholder inserts the value of a column, for example the name of a product.
List several records: A
ForEachloop inserts content for each record, for example all products of an order.Show content conditionally: A personalization rule checks the records of a contact and shows content only if a condition is met, for example an offer for customers who bought shoes.
For placeholders and loops, see Use Related Data in a Message. This page explains how the data is referenced and how you use it in conditions.
How the Data Is Referenced
The notation depends on whether the related data set is linked to a contact attribute:
Linked data set:
user.relatedAttribute['Purchases']returns the records whose key matches the attribute value of the contact.Unlinked data set:
ecx:related('Purchases', key)returns the records for a key that you specify, for example a fixed value or an attribute.
In a unique data set, each key has exactly one record. You add the column to the reference, for example user.relatedAttribute['Purchases']['Article']. In a non-unique data set, a key can have several records. You process them with a ForEach loop or with functions.
The name of the data set is not case-sensitive. Values that you compare in filters are case-sensitive.
Conditions with Related Data
A condition in a personalization rule must return true or false. Filter functions such as ecx:filter return records, not a Boolean value. To use them in a condition, count the records with ecm:countMapElements and compare the result with > 0.
Conditions with functions are written in code. See Code View for Personalization Rules.
Example: Customers who bought shoes
The linked data set Purchases has a column ArticleType. Customers who bought shoes get an offer for shoe accessories. All other customers get a general offer:
<%InsertIf expression="${ecm:countMapElements(ecx:filter(user.relatedAttribute['Purchases'], 'ArticleType', '==', 'Shoes')) > 0}"%>
Special offer on shoe accessories!
<%/InsertIf%>
<%InsertElse%>
Check out our latest deals!
<%/InsertElse%>The value Shoes must match the stored value exactly. To ignore upper and lower case, use the operator containsignorecase instead of ==. It also matches values that only contain the term, for example Running shoes.
Example: Purchases in the last 30 days
Customers who bought something in the last 30 days get an exclusive offer. ecm:addInterval calculates the date 30 days ago, and ecx:formatDate converts it into the format that the filter compares with:
<%InsertIf expression="${ecm:countMapElements(ecx:filter(user.relatedAttribute['Purchases'], 'Date', '>=', ecx:formatDate(ecm:addInterval(date.Today, '-30d'), 'yyyy-MM-dd', ecm:timeZone('Europe/Berlin'), '', false))) > 0}"%>
Exclusive deal for recent buyers!
<%/InsertIf%>Replace the time zone with the one of your system. For the date functions, see Extract and Format Dates and Times. For all filter functions, see Sort or Filter Data Records.
Best Practices
Keep conditions as simple as possible. Each condition is evaluated for every recipient at sendout.
Add a default
InsertElseblock so that contacts without matching records also get content.Save rules that you use often and reuse them in other messages. See Personalization Rules.
Test the rule in the message preview with contacts that have matching records, other records, and no records at all. See Message Preview (Email).