Targeting Engine

By admin , 29 March 2026

How the Targeting Engine Works

The targeting engine lets you define segments — named groups of customers — by writing rules against customer, account, journey, and place data. Segments can then be assigned to features (campaigns, recommendations, items, etc.) to control visibility and personalisation.

Core Concepts

Segment

A segment is a named, reusable group definition. It holds metadata (name, description, active) and a list of rules that determine who belongs to it. A segment with no rules matches everyone.

Rule

A rule is a single condition on a customer attribute. Every rule has:

  • attribute — the data point to inspect (e.g. account.points)
  • operator — how to compare (e.g. gte)
  • value — the comparison value, stored as JSON
  • ruleGroup — an integer (0, 1, 2 …) that controls AND/OR grouping
  • negate — when true, inverts the rule result

Assignment

An assignment links a segment to a target entity (e.g. a campaign or product item). Each assignment has a mode:

  • include — the target is visible only to customers who match this segment
  • exclude — the target is hidden from customers who match this segment

Evaluation Logic

AND / OR Rule Grouping

Rules inside a segment are evaluated in groups. The ruleGroup field controls this:

  • Rules in the same group are combined with OR — the group passes if any rule matches
  • Rules in different groups are combined with AND — the segment passes only if every group passes
Example: Group 0 has two rules (account.tier eq Gold OR account.tier eq Platinum), and Group 1 has one rule (account.orders gte 5). A customer must be in Gold OR Platinum and have at least 5 orders.

Include / Exclude Precedence

The engine always evaluates exclusions first:

  1. If the customer matches any exclude assignment → result is false (hidden), regardless of includes
  2. If there are no include assignments → result is true (visible to all)
  3. If the customer matches any include assignment → result is true
  4. Otherwise → false
Excludes always win. If a customer is in both an included and an excluded segment for the same target, they will not see it.

The negate Flag

Setting negate: true on a rule inverts its outcome. A rule that would normally pass will fail, and vice versa. This avoids needing to create an extra segment just to express "not in this tier".

Operators

OperatorDescriptionValue format
eqEqual toScalar: "Gold", 100
neNot equal toScalar
gtGreater thanNumber or date timestamp
gteGreater than or equal toNumber or date timestamp
ltLess thanNumber or date timestamp
lteLess than or equal toNumber or date timestamp
inActual value is in the provided listArray: ["Gold","Platinum"]
containsString contains substringString: "gmail"
existsValue is not null / undefinedNo value needed
betweenValue is between two bounds (inclusive)Object: {"from": 10, "to": 50}

Available Attributes

Account namespace

Data scoped to the customer's loyalty account at a specific place.

AttributeTypeOperatorsDescription
account.classificationstringeq ne in existsAccount classification label
account.cltvnumbereq ne gt gte lt lte betweenCustomer lifetime value for this account
account.daysSinceLastOrdernumbereq ne gt gte lt lte betweenWhole days elapsed since the account's last order
account.lastOrderDatedateeq ne gt gte lt lte betweenDate of the account's most recent order (YYYY-MM-DD)
account.ordersnumbereq ne gt gte lt lte betweenTotal number of orders placed on this account
account.pointsnumbereq ne gt gte lt lte betweenCurrent point balance on this account
account.savingsnumbereq ne gt gte lt lte betweenTotal savings accumulated on this account
account.spendnumbereq ne gt gte lt lte betweenTotal spend recorded on this account
account.tierstringeq ne in existsCurrent tier name (e.g. Bronze, Silver, Gold)

Customer namespace

Data from the customer's global profile.

AttributeTypeOperatorsDescription
customer.cltvnumbereq ne gt gte lt lte betweenCustomer lifetime value across all places
customer.countrystringeq ne in containsCountry code on the customer's profile
customer.dobdateeq ne gt gte lt lte betweenDate of birth (YYYY-MM-DD)
customer.earnedPointsnumbereq ne gt gte lt lte betweenLifetime points earned across all accounts
customer.emaileq ne in contains existsCustomer email address
customer.firstNamestringeq ne in contains existsCustomer first name
customer.genderstringeq ne in existsGender value on the customer's profile
customer.lastNamestringeq ne in contains existsCustomer last name
customer.mobilePhonephoneeq ne in contains existsCustomer mobile phone number
customer.ordersnumbereq ne gt gte lt lte betweenTotal orders placed across all places
customer.redeemedPointsnumbereq ne gt gte lt lte betweenLifetime points redeemed across all accounts
customer.savingsnumbereq ne gt gte lt lte betweenTotal savings across all places

Journey namespace

Data about an active journey execution for the customer.

AttributeTypeOperatorsDescription
journey.daysSinceStartednumbereq ne gt gte lt lte betweenWhole days elapsed since the journey execution started
journey.starteddateeq ne gt gte lt lte betweenDate the journey execution was created (YYYY-MM-DD)

Place namespace

AttributeTypeOperatorsDescription
place.namestringeq ne in contains existsTitle of the current place

Date Values

Date attributes expect values as YYYY-MM-DD strings in rule definitions. Internally the engine converts them to UTC midnight millisecond timestamps for comparison, so the time component is ignored. For between, pass {"from": "2024-01-01", "to": "2024-12-31"}.

Practical Examples

1. High-value VIP customers

Customers in the Gold or Platinum tier who have spent more than 5,000.

// Rule Group 0 — tier must be Gold OR Platinum
{ attribute: "account.tier", operator: "in",  value: ["Gold", "Platinum"], ruleGroup: 0 }

// Rule Group 1 — AND spend must be over 5000
{ attribute: "account.spend", operator: "gt", value: 5000, ruleGroup: 1 }

2. At-risk lapsed customers

Customers who haven't ordered in over 60 days.

{ attribute: "account.daysSinceLastOrder", operator: "gt", value: 60, ruleGroup: 0 }

3. Birthday month promotion

Customers born in a specific month. Use between with the month's date range.

{ attribute: "customer.dob", operator: "between", value: { from: "1900-07-01", to: "1900-07-31" }, ruleGroup: 0 }
Because only the month/day is compared (year is stripped), using year 1900 as a placeholder works reliably for all customers.

4. New customers (first 3 orders)

{ attribute: "account.orders", operator: "lte", value: 3, ruleGroup: 0 }

5. Customers with a points balance to redeem

{ attribute: "account.points", operator: "gte", value: 100, ruleGroup: 0 }

6. Exclude employees / test accounts

Create a segment matching a specific email domain, then assign it as mode: "exclude".

{ attribute: "customer.email", operator: "contains", value: "@yourcompany.com", ruleGroup: 0 }

7. Customers active in a specific journey for over 7 days

{ attribute: "journey.daysSinceStarted", operator: "gt", value: 7, ruleGroup: 0 }

8. Customers in a specific country who have never ordered

// Group 0
{ attribute: "customer.country", operator: "eq", value: "DK", ruleGroup: 0 }

// Group 1 — AND no orders yet
{ attribute: "account.orders", operator: "eq", value: 0, ruleGroup: 1 }

API Quick Reference

All endpoints are under /places/{placeId}/targeting/ and require a valid Api-Key header.

MethodPathDescription
GET/targeting/attributesList all available attributes and their allowed operators
GET/targeting/segmentsList segments (paginated)
POST/targeting/segmentsCreate a segment
PUT/targeting/segments/{id}Update a segment
DELETE/targeting/segments/{id}Delete a segment
GET/targeting/segments/{id}/rulesList rules for a segment
POST/targeting/segments/{id}/rulesAdd a rule to a segment
PUT/targeting/segments/{id}/rules/{ruleId}Update a rule
DELETE/targeting/segments/{id}/rules/{ruleId}Delete a rule
GET/targeting/segments/{id}/assignmentsList assignments for a segment
POST/targeting/segments/{id}/assignmentsCreate an assignment
PUT/targeting/segments/{id}/assignments/{aId}Update an assignment
DELETE/targeting/segments/{id}/assignments/{aId}Delete an assignment

Evaluation Summary

ScenarioResult
No assignments exist for the target✅ Visible to everyone
Only include assignments, customer matches one✅ Visible
Only include assignments, customer matches none❌ Hidden
Customer matches an exclude assignment❌ Hidden (even if also in an include segment)
Segment has no rules✅ Matches everyone
Rule has negate: true and condition passesRule treated as failed

Comments