Skip to main content
Version: 8.8.x

Selling Context

A selling context defines the shopper, time, geography, or other conditions under which a Price List Assignment or a Promotion applies. In the Import-Export XML format, the <selling_context> node is embedded inside the parent object (a price list assignment or a promotion) and contains one or more <condition> elements whose condition_string is evaluated at runtime against the shopper's traits.

The same condition_string syntax is also used by Saved Conditions.

Sample XML:

<selling_context>
<guid>2054C56D-250F-E515-CA69-AC097DA371D5</guid>
<name>Senior Shopper</name>
<description>PLA SellingContext for Senior Shopper</description>
<priority>1</priority>
<conditions>
<condition>
<guid>394CEAE8-F46A-2633-4208-9F38600176FD</guid>
<name>name_PLA_SHOPPER</name>
<description>desc_PLA_SHOPPER</description>
<condition_string>{ AND { AND { CUSTOMER_AGE_YEARS.greaterThanOrEqualTo (65i) } } }</condition_string>
<dictionary_guid>PLA_SHOPPER</dictionary_guid>
</condition>
</conditions>
</selling_context>

Selling Context Fields​

FieldDescription
guidUnique identifier for the selling context.
nameDisplay name for the selling context.
descriptionOptional description.
priorityUsed to break ties between selling contexts of the same parent type. Lower numbers indicate higher priority.
conditionsA container for one or more <condition> elements.

Condition Fields​

FieldDescription
guidUnique identifier for the condition.
nameDisplay name for the condition.
descriptionOptional description.
condition_stringThe expression evaluated against shopper traits at runtime. See Condition String Syntax.
dictionary_guidThe tag dictionary the condition belongs to. Typical values are PLA_SHOPPER for price list assignments, PROMOTIONS_SHOPPER for shopper-targeted promotions, TIME for time-based conditions, and STORES for store-scoped saved conditions.

Condition String Syntax​

The condition_string uses a Groovy-like domain-specific language that wraps one or more atomic conditions inside logical operator blocks.

Logical Structure​

Atomic conditions are nested inside AND or OR blocks, with a single outermost block:

{ AND { <atomicCondition> <atomicCondition> ... } }
{ OR { <atomicCondition> <atomicCondition> ... } }

Blocks can be nested to express compound logic:

{ AND { CUSTOMER_AGE_YEARS.greaterThanOrEqualTo (18i) { OR { GEOIP_COUNTRY_CODE.equalTo 'CA' GEOIP_COUNTRY_CODE.equalTo 'US' } } } }

Atomic Conditions​

Each atomic condition takes the form:

TRAIT_NAME.operator value

TRAIT_NAME is any supported trait (see Supported Traits). operator is one of the operators listed in Available Operators. value is a literal whose form depends on the trait's data type:

Data TypeLiteral FormExample
StringSingle- or double-quoted text'Segment1'
IntegerNumber with i suffix, optionally parenthesised(65i) or 65i
LongNumber with l suffix, optionally parenthesised(100l)
FloatNumber with f suffix, optionally parenthesised(1.5f)
BigDecimalNumber with g suffix, optionally parenthesised(99.99g)
Booleantrue or falsetrue

Some operators (inList, notInList, moduloEquals) accept a string literal whose content encodes a comma-separated list rather than a single value of the trait's native type. See the operator descriptions below.

Supported Traits​

Any supported trait can be referenced in a condition_string. The trait's data type determines which operators are valid. For the full list of out-of-the-box traits, their data types, and how each is populated, see Supported Traits in the Cortex Personalization documentation.

Available Operators​

The following operators are registered with the condition evaluation service. The data types listed below indicate the trait types for which each operator is meaningful.

String Traits​

OperatorDescription
equalToTrue if the trait value equals the literal.
notEqualToTrue if the trait value does not equal the literal.
equalsIgnoreCaseCase-insensitive string equality.
notEqualsIgnoreCaseNegation of equalsIgnoreCase.
includesTrue if the trait value (a string or a collection) contains the literal. For strings this is a substring match; for collections it is element membership.
notIncludesNegation of includes.
includesIgnoreCaseCase-insensitive variant of includes for substring matching.
notIncludesIgnoreCaseNegation of includesIgnoreCase.
containsAlias for includes.
inListTrue if the trait value matches any entry in a comma-separated list supplied as a quoted string. Example: GEOIP_COUNTRY_CODE.inList 'CA,US,MX'.
notInListNegation of inList.

Numeric Traits (Integer, Long, Float, BigDecimal)​

OperatorDescription
equalToTrue if the trait value equals the literal.
notEqualToTrue if the trait value does not equal the literal.
lessThanTrue if the trait value is strictly less than the literal.
lessThanOrEqualToTrue if the trait value is less than or equal to the literal.
greaterThanTrue if the trait value is strictly greater than the literal.
greaterThanOrEqualToTrue if the trait value is greater than or equal to the literal.
inListTrue if the trait value's string form matches any entry in a quoted comma-separated list. Example: SHOPPING_DAY_OF_WEEK.inList '1,2,3,4,5' (weekdays).
notInListNegation of inList.
moduloEqualsRecurring-interval match for SHOPPING_DAY_NUMBER. The literal is a quoted string 'interval,startReference', where interval is the recurrence in days and startReference is either a SHOPPING_DAY_NUMBER value or an ISO date (such as 2025-01-01) used as the anchor. Example: SHOPPING_DAY_NUMBER.moduloEquals '7,2025-01-01' matches every seventh day from January 1, 2025 onward.

Boolean Traits​

OperatorDescription
equalToTrue if the trait value equals the literal.
notEqualToTrue if the trait value does not equal the literal.

Date Traits​

Date-valued traits (such as SHOPPING_CONTEXT_DATE_OVERRIDE) are comparable, so the numeric ordering operators (lessThan, lessThanOrEqualTo, greaterThan, greaterThanOrEqualTo) plus equalTo and notEqualTo apply.

Examples​

Shoppers aged 65 or older:

<condition_string>{ AND { CUSTOMER_AGE_YEARS.greaterThanOrEqualTo (65i) } }</condition_string>

Shoppers in a named segment:

<condition_string>{ AND { CUSTOMER_SEGMENT.includes 'Segment1' } }</condition_string>

Active only on weekdays between 9am and 5pm:

<condition_string>{ AND { SHOPPING_DAY_OF_WEEK.inList '1,2,3,4,5' SHOPPING_HOUR_OF_DAY.greaterThanOrEqualTo (9i) SHOPPING_HOUR_OF_DAY.lessThan (17i) } }</condition_string>

Shoppers in Canada or the United States who are registered:

<condition_string>{ AND { REGISTERED_CUSTOMER.equalTo true { OR { GEOIP_COUNTRY_CODE.equalTo 'CA' GEOIP_COUNTRY_CODE.equalTo 'US' } } } }</condition_string>

Every seventh day starting January 1, 2025:

<condition_string>{ AND { SHOPPING_DAY_NUMBER.moduloEquals '7,2025-01-01' } }</condition_string>