Defining dynamic segments¶
When using the the Engage API to create Dynamic Segments, You will have to provide your segment in the Engage Segment expression language.
There are many functions you can use to define your segment. Below you can find:
- The different functions and expressions available
- Information on special tabels with customer information
- Examples
The basics¶
First, some general basics on expressions:
- The SCOPE is the context in which you are looking at fields. This can be your audience list or related lists.
- To filter on fields on your main list, use MASTER as a scope for that list.
- To filter on a field in a specific scope,like the USER_NAME field on your MASTER list, use the [<LIST>.<FIELD>] syntax. Example: [MASTER.USER_NAME]
- To filter on fields from related list, use the name of the related list and specified in the relation section of your list, inside engage. For example, if the 1-1 list PREFERENCES is linked to your list with the name USER_PREFERENCE, use [USER_PREFERENCE.NEWSLETTERS]
Logical operations¶
These logical operations can be used inside fiters. They can be used in many variations and are often combined.
Logical Operator | Expression | Example | Description |
---|---|---|---|
Equal | eq(<FIELD>,<VALUE>) | eq([MASTER.ID], toint(5)) | ID is equal to 5 |
Not equal | ne(<FIELD>,<VALUE>) | ne([MASTER.ID], toint(5)) | ID is not equal to 5 |
Greater than | gt(<FIELD>,<VALUE>) | gt([MASTER.AGE], toint(18)) | Older than 18 |
Greater than or equal | ge(<FIELD>,<VALUE>) | ge([MASTER.AGE], toint(18)) | 18 or older |
Less than | lt(<FIELD>,<VALUE>) | lt([MASTER.AGE], toint(18)) | Younger than 18 |
Less than or equal | le(<FIELD>,<VALUE>) | le([MASTER.AGE], toint(18)) | 18 or younger |
And | all(<EXPRESSION>,<EXPRESSION>,...) | all(gt([MASTER.AGE], toint(18)),lt([MASTER.AGE], toint(25))) | Older than 18 and younger than 25 |
Or | any(<EXPRESSION>,<EXPRESSION>,...) | any(lt([MASTER.AGE], toint(18)),gt([MASTER.AGE], toint(25))) | younger than 18 or older than 25 |
One off | in(<FIELD>,<VALUES>,<SEPARATOR>) | all(in([MASTER.AGE],'18|20','|') | 18 or 20 years old |
Ends with | endswith(<FIELD>,<VALUE>) | endswith([MASTER.MAIL], 'gmail.com') | email ends with "gmail.com" |
Starts with | startswith(<FIELD>,<VALUE>) | startswith([MASTER.MAIL], 'bob') | email starts with "bob" |
Contains | contains(<FIELD>,<VALUE>) | contains([MASTER.NAME], 'Marigold') | Name contains "Marigold |
Field is empty or null | isempty(<FIELD>) | isempty([MASTER.AGE]) | Age is known |
Field is not empty or null | isnotempty(<FIELD>) | isnotempty([MASTER.AGE]) | Age is not known |
Date & time operations¶
The following functions are operations you can use throughout your constraints, to identify Absolute or Relative dates and times.
Note
When using relative, this is always compared to the timezone of your server, usually UTC.
Relative datetimes¶
Logical Operator | Expression | Example | Description |
---|---|---|---|
Current datetime subtract relative datetime | subrelativetonow(<WEEKS>,<DAYS>,<HOURS>,<MINUTES>) | subrelativetonow(0,24,0,0) | Now minus 24 days |
Current datetime add relative datetime | addrelativetonow(<WEEKS>,<DAYS>,<HOURS>,<MINUTES>) | addrelativetonow(1,0,0,0) | One week from now |
Current datetime add relative date | addrelativedateparttonow(<YEARS>,<MONTHS>,<DAYS>,<HOURS>) | addrelativedateparttonow(1,0,0,0) | One year from now |
Current date subtract relative datetime | subrelativetotoday(<WEEKS>,<DAYS>,<HOURS>,<MINUTES>) | subrelativetotoday(0,3,0,0) | Today (00:00:00) minus 3 days |
Current date add relative datetime | addrelativetotoday(<WEEKS>,<DAYS>,<HOURS>,<MINUTES>) | addrelativetotoday(0,3,0,0) | Today (00:00:00) plus 3 days |
Date comparisons¶
Logical Operator | Expression | Example | Description |
---|---|---|---|
Date of field is equal date | datepartisequal(<FIELD>,<DATE>,'') | datepartisequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is on 22st jan 2024 |
Date of field is not equal to date | datepartisnotequal(<FIELD>,<DATE>,'') | datepartisnotequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is not on 22st jan 2024 |
Date of field is after or equal date | datepartisbefore(<FIELD>,<DATE>,'') | datepartisbefore([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is before 22st jan 2024 |
Date of field is equal date | datepartisbeforeorequal (<FIELD>,<DATE>,'') | datepartisbeforeorequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is on, or before 22st jan 2024 |
Date of field is after or equal date | datepartisafter(<FIELD>,<DATE>,'') | datepartisafter([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is after 22st jan 2024 |
Date of field is after or equal date | datepartisafterorequal(<FIELD>,<DATE>,'') | datepartisafterorequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'') | Birthday is on, or after 22st jan 2024 |
Date of field is between 2 dates | datepartisbetween(<FIELD>,<DATE>,<DATE>,'') | datepartisbetween([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'), todatetime('2024-01-28 00:00:00', 'yyyy-MM-dd HH:mm:ss'), 'day') | Birthday is between 22st of jan 2024 and 28 of jan 2024 |
Date comparisons on part of a date¶
These operations allow you to compare to specific pieces of a date. the <DATE_FIELD>
can have the following values:
- hour
- day
- monthday
- month
- year
Logical Operator | Expression | Example | Description |
---|---|---|---|
Date of field is equal date field | datepartisequal(<FIELD>,<DATE>,<DATE_FIELD>) | datepartisequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'day') | Birthday is on the first of any month |
Date of field is not equal to date field | datepartisnotequal(<FIELD>,<DATE>,<DATE_FIELD>) | datepartisnotequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'month') | Birthday is not in Jan |
Date of field is after or equal date field | datepartisbefore(<FIELD>,<DATE>,<DATE_FIELD>) | datepartisbefore([MASTER.BIRTHDAY], todatetime('2024-03-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'month') | Birthday is before March |
Date of field is equal date field | datepartisbeforeorequal (<FIELD>,<DATE>,<DATE_FIELD>) | datepartisbeforeorequal([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'year') | Birthday is in, or before 2024 |
Date of field is after or equal date field | datepartisafter(<FIELD>,<DATE>,<DATE_FIELD>) | datepartisafter([MASTER.BIRTHDAY], todatetime('2024-02-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'monthday') | Birthday is after 22nd of Feb |
Date of field is after or equal date field | datepartisafterorequal(<FIELD>,<DATE>,<DATE_FIELD>) | datepartisafterorequal([MASTER.BIRTHDAY], todatetime('2024-10-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'),'month') | Birthday is in, or afterNnov 2024 |
Date of field is between 2 hours / days / months / month-day / years | datepartisbetween(<FIELD>,<DATE>,<DATE>,<DATE_FIELD>) | datepartisbetween([MASTER.BIRTHDAY], todatetime('2024-01-22 00:00:00', 'yyyy-MM-dd HH:mm:ss'), todatetime('2024-01-28 00:00:00', 'yyyy-MM-dd HH:mm:ss'), 'day') | Birthday is between day 22 and 28 of any month |
Casting¶
It is always important to use the correct types when doing comparisons on your tabels. For this, type conversion (casting) might be needed.
Logical Operator | Expression | Example |
---|---|---|
as Decimal | todecimal(<VALUE>) | todecimal('50') |
as Integer | toint(<VALUE>) | toint('5') |
As Boolean | tobool(<VALUE>) | tobool('true') |
as Datetime | todatetime(<VALUE>,<FORMAT>) | todatetime('2024-05-04 10:03:22','yyyy-MM-dd HH:mm:ss') |
Special operations¶
There are special operations available to do specific filtering, both on the main list and related lists.
Lookup¶
Lookup is used to find records on your main list, that have matching records in a related list. the syntax is as follows: lookup(<SCOPE>,<EXPRESSION>)
- SCOPE is the name of the relation
- EXPRESSION can be any valid expression build up of other expressions. When references fields on your SCOPE
For example, if you have a related list HOBBIES, containing details about the hobbies of the user, you can do the following:
lookup([HOBBIES],eq([HOBBY],'Runner'))
this will select all users that have a hobby Runner
.
You can also use lookup to create a one of
filter. Like so:
lookup([HOBBIES],all(in([HOBBY],'Runner|Swimmer')))
This will return all users with hobby either Runner or Swimmer.
Note
You might have noticed the all
function in the above expression. This is required for your segment to render correctly in the Engage segment editor. If a (valid) constraint is provided that is not available in the Segment Builder, the expression will be shown in plain text and will not be editable from the UI.
Content interactions¶
For adding engagment filters, a few similar operations exist. they generally follow the syntax: <operator>(<JOURNEY_ID>,<CONTENT_ID>,<LINK_ID>,...)
where JOURNEY_ID is the id of the journey, which you can find in the properties panel of any journey.
the CONTENT_ID can be found by selecting the configuration dropdown in a custom journey and highlighting the ID's of the different components.
Note
For recurring batch and Single batch journeys, the CONTENT_ID will always be 1. for A/B test journeys, they correspond to the letters of the alphabet. meaning A=1, B=2, etc..
the LINK_ID can be found in the link section of your content, and is always relative to the selected content.
Logical Operator | Expression | Example | Description |
---|---|---|---|
Content delivered | contentdelivered(<JOURNEY_ID>,<CONTENT_ID>) | contentdelivered('1924','5') | Received email 5 from journey 1924 |
Content delivered before time | contentdeliveredbefore(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentdeliveredbefore('1924','5',subrelativetonow(0,5,0,0)) | Received email 5 from journey 1924 more than 5 days ago |
Content delivered after time | contentdeliveredafter(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentdeliveredafter('1924','5',subrelativetonow(0,5,0,0)) | Received email 5 from journey 1924 less than 5 days ago |
Content delivered between time | contentdeliveredbetween(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>,<DATE_EXPRESSION>) | contentdeliveredbetween('1924','5',subrelativetonow(0,5,0,0),subrelativetonow(0,1,0,0)) | Received email 5 from journey 1924 between 5 and 1 day ago |
Content sent | contentsent(<JOURNEY_ID>,<CONTENT_ID>) | contentsent('1924','5') | Sent email 5 from journey 1924 |
Content sent before time | contentsentbefore(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentsentbefore('1924','5',subrelativetonow(0,5,0,0)) | Sent email 5 from journey 1924 more than 5 days ago |
Content sent after time | contentsentafter(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentsentafter('1924','5',subrelativetonow(0,5,0,0)) | Sent email 5 from journey 1924 less than 5 days ago |
Content sent between time | contentsentbetween(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>,<DATE_EXPRESSION>) | contentsentbetween('1924','5',subrelativetonow(0,5,0,0),subrelativetonow(0,1,0,0)) | Sent email 5 from journey 1924 between 5 and 1 day ago |
Content viewed | contentviewed(<JOURNEY_ID>,<CONTENT_ID>) | contentviewed('1924','5') | Viewed email 5 from journey 1924 |
Content viewed before time | contentviewedbefore(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentviewedbefore('1924','5',subrelativetonow(0,5,0,0)) | Viewed email 5 from journey 1924 more than 5 days ago |
Content viewed after time | contentviewedafter(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>) | contentviewedafter('1924','5',subrelativetonow(0,5,0,0)) | Viewed email 5 from journey 1924 less than 5 days ago |
Content viewed between time | contentviewedbetween(<JOURNEY_ID>,<CONTENT_ID>,<DATE_EXPRESSION>,<DATE_EXPRESSION>) | contentviewedbetween('1924','5',subrelativetonow(0,5,0,0),subrelativetonow(0,1,0,0)) | viewed email 5 from journey 1924 between 5 and 1 day ago |
Content clicked | contentlinkclicked(<JOURNEY_ID>,<CONTENT_ID>,<LINK_ID>) | contentlinkclicked('1924','5','100') | Clicked link 100 in email 5 from journey 1924 |
Content clicked before time | contentlinkclickedbefore(<JOURNEY_ID>,<CONTENT_ID>,<LINK_ID>,<DATE_EXPRESSION>) | contentlinkclickedbefore('1924','5','100',subrelativetonow(0,5,0,0)) | Clicked link 100 in email 5 from journey 1924 more than 5 days ago |
Content clicked after time | contentlinkclickedafter(<JOURNEY_ID>,<CONTENT_ID>,<LINK_ID>,<DATE_EXPRESSION>) | contentlinkclickedafter('1924','5','100',subrelativetonow(0,5,0,0)) | Clicked link 100 in email 5 from journey 1924 less than 5 days ago |
Content clicked between time | contentlinkclickedbetween(<JOURNEY_ID>,<CONTENT_ID>,<LINK_ID>,<DATE_EXPRESSION>,<DATE_EXPRESSION>) | contentlinkclickedbetween('1924','5','100',subrelativetonow(0,5,0,0),subrelativetonow(0,1,0,0)) | Clicked link 100 in email 5 from journey 1924 between 5 and 1 day ago |
Filter on other segments¶
You can filter inside a Segment, based on the users present in another segment.
you can retrieve the SEGMENT_ID from the link, when opening your segment:
Logical Operator | Expression | Example |
---|---|---|
Include segment | includesegments(<SEGMENT_ID>) | includesegments(50) |
Exclude segment | excludesegments(<SEGMENT_ID>) | excludesegments(50) |
STO (send time optimization) filters¶
You can filter on the existance of an STO profile for users.
This information is available through the SYS_AI_STO_DATA scope.
Logical Operator | Expression |
---|---|
Users with STO profile | isnotsempty([SYS_AI_STO_DATA.ID]) |
Users without STO profile | isempty([SYS_AI_STO_DATA.ID]) |
Filter engagment profile¶
The engagement Profile, which contains overall information on the user, can be accessed via the SYS_EMAIL_ENGAGEMENT scope. If you want to learn more about Engagement Metrics, visit our Knowledge portal. You can filter using all the above listed operators, and the profile contains a number of interesting fields you can use to further segment your users.
Field name | Field description | Example | Description |
---|---|---|---|
CLICK_RATE_CTR | % of emails clicked | lt([SYS_EMAIL_ENGAGEMENT.CLICK_RATE_CTR], todecimal('10')) | Percentage emails clicked is less than 10 % |
CTO_RATE | (Unique) Click to open rate (overall) | gt([SYS_EMAIL_ENGAGEMENT.CTO_RATE], todecimal('10')) | Click to open rate is greater than 10% |
CLICK_RATE_EVOLUTION | If the click rate of the user is better(1), the same(0) or worse(-1) in the last 5 mails, compaired to the 5 mails before that | eq([SYS_EMAIL_ENGAGEMENT.CLICK_RATE_EVOLUTION], '1') | Click rate has improved |
CLICKED | Number of emails clicked | gt([SYS_EMAIL_ENGAGEMENT.CLICKED], todecimal('10')) | Number of emails clicked is greater than 10 |
CLICKED_FIRSTDT | Date of first email clicked | datepartisafter([SYS_EMAIL_ENGAGEMENT.CLICKED_FIRSTDT],subrelativetonow(0,5,0,0),'') | First email click was less than 5 days ago |
CLICKED_LASTDT | Date of last email clicked | datepartisbefore([SYS_EMAIL_ENGAGEMENT.CLICKED_FIRSTDT],subrelativetonow(3,0,0,0),'') | Last email click was more than 3 weeks ago |
DELIVERED | Number of emails delivered | gt([SYS_EMAIL_ENGAGEMENT.DELIVERED], todecimal('10')) | Number of emails delivered is greater than 10 |
DELIVERED_FIRSTDT | Date of first email delivered | datepartisequal([SYS_EMAIL_ENGAGEMENT.DELIVERED_FIRSTDT], subrelativedateparttonow(0,0,0,0), 'year') | First delivered email was this year |
DELIVERED_LASTDT | Date of last email delivered | datepartisbefore([SYS_EMAIL_ENGAGEMENT.DELIVERED_LASTDT], subrelativedateparttonow(0,0,0,0), 'year') | First delivered email was not this year |
DELIVERY_FREQUENCY | Average number of emails delivered per week | lt([SYS_EMAIL_ENGAGEMENT.DELIVERY_FREQUENCY], todecimal('3')) | Less than 3 emails delivered per week, on average |
DELIVERY_FREQUENCY_EVOLUTION | The delivery rate of the user is better(1), the same(0) or worse(-1) in the last 5 mails, compaired to the 5 mails before that | eq([SYS_EMAIL_ENGAGEMENT.DELIVERY_FREQUENCY_EVOLUTION], '-1') | Number of emails received per week on average has decreased |
DELIVERY_RATE | % of emails delivered | ge([SYS_EMAIL_ENGAGEMENT.DELIVERY_RATE], todecimal('95')) | Delivery rate is higher than 95% |
LAST_SERIES_UNOPENED | Longests streak of unopened emails | le([SYS_EMAIL_ENGAGEMENT.LAST_SERIES_UNOPENED], toint('5')) | Unopened streak is smaller than 5 |
DESKTOP_ENGAGEMENTS | Number of email views and clicks on desktop | le([SYS_EMAIL_ENGAGEMENT.DESKTOP_ENGAGEMENTS], toint('100')) | Total Desktop views/clicks is less than 100 |
MOBILE_ENGAGEMENTS | Number of email views and clicks on mobile | ge([SYS_EMAIL_ENGAGEMENT.MOBILE_ENGAGEMENTS], [SYS_EMAIL_ENGAGEMENT.DESKTOP_ENGAGEMENTS]) | Total mobile views/clicks is greater than the number of desktop views/clicks |
TABLET_ENGAGEMENTS | Number of email views and clicks on tablet | le([SYS_EMAIL_ENGAGEMENT.TABLET_ENGAGEMENTS], toint('100')) | Total Tablet views is less than 100 |
MOBILE_USAGE_RATE | Number of email views and clicks on mobile compaired to the total | gt([SYS_EMAIL_ENGAGEMENT.MOBILE_USAGE_RATE], todecimal('10')) | Mobile views are more than 10% of total |
TABLET_USAGE_RATE | Number of email views and clicks on tablet compaired to the total | le([SYS_EMAIL_ENGAGEMENT.TABLET_USAGE_RATE], todecimal('10')) | Tablet views are less than or equal to 10% of total |
OPEN_RATE | (Unique) Email open to delivered rate (overall) | gt([SYS_EMAIL_ENGAGEMENT.OPEN_RATE], todecimal('50')) | Email open to delivered rate is great than 50% |
OPEN_RATE_EVOLUTION | The open rate of the user is better(1), the same(0) or worse(-1) in the last 5 mails, compaired to the 5 mails before that | eq([SYS_EMAIL_ENGAGEMENT.OPEN_RATE_EVOLUTION], '1') | Open rate has improved |
OPENED | Number of email opened | gt([SYS_EMAIL_ENGAGEMENT.OPENED], toint('1')) | Opened at least 1 email |
OPENED_FIRSTDT | Date of first opened email | datepartisequal([SYS_EMAIL_ENGAGEMENT.OPENED_FIRSTDT], subrelativedateparttonow(0,0,0,0), 'year') | First opened email was this year |
OPENED_LASTDT | Date of last opened email | datepartisbefore([SYS_EMAIL_ENGAGEMENT.OPENED_LASTDT], subrelativedateparttonow(0,0,0,0), 'year') | Last delivered email was not this year |
SENT | Number of email sent | eq([SYS_EMAIL_ENGAGEMENT.SENT], toint('0')) | No email was sent |
VIEW_RATE | Rate of emails viewed | gt([SYS_EMAIL_ENGAGEMENT.VIEW_RATE], todecimal('50')) | Email view rate is great than 50% |
VIEWED | Total number of emails viewed | eq([SYS_EMAIL_ENGAGEMENT.VIEWED], toint('0')) | No email was viewed |
VIEWED_LASTDT | datepartisbefore([SYS_EMAIL_ENGAGEMENT.OPENED_LASTDT], subrelativedateparttonow(0,0,0,0), 'year') | last viewed email was not this year |
Examples¶
A few (complex) examples to help you understand how to structure your constraints.
All users that speak English or French
any(eq([MASTER.LANGUAGE], 'EN'), eq([MASTER.LANGUAGE], 'FR'))
All users that speak either English or French and that have a hobby that is either 'BEEKEEPER' or 'RUNNER'
all(in([MASTER.LANGUAGE], 'EN|FR', '|'), lookup([HOBBIES],all(in([HOBBY], 'BEEKEEPER|RUNNER', '|'))))
All users that have a male sibling
lookup([SIBLINGS],all(eq([GENDER], 'Male')))
Every user that has an ID greater than 1 and is named 'Tom' OR Every user for whom the email open rate evolution is going up
any(all(gt([MASTER.ID], toint('1')), eq([MASTER.NAME], 'Tom')), all(eq([SYS_EMAIL_ENGAGEMENT.OPEN_RATE_EVOLUTION], '1')))
All users that have a an STO profile, AND who want to receive the Monthly Newsletter, AND who joined after 1 of june 2024, AND live in Belgium AND Who have opened 50% of the received emails OR who have a click to open rate greater than 50%.
all(isnotempty([SYS_AI_STO_DATA.ID]), eq([PREFERENCES.MONTHLY_NEWSLETTER], tobool('true')), eq([MASTER.COUNTRY], 'BE'), datepartisbefore([MASTER.CREATED_DT], todatetime('2024-06-01 00:00:00', 'yyyy-MM-dd HH:mm:ss'), ''), any(gt([SYS_EMAIL_ENGAGEMENT.OPEN_RATE], todecimal('50')), gt([SYS_EMAIL_ENGAGEMENT.CTO_RATE], todecimal('50'))))