1. Ordering

Rules-based promotion expressions

Custom rule-based expressions for order promotions provide extensive flexibility to meet diverse business requirements. This implementation of Flexibility over Features enables developers to create customized if-then statements that solve more scenarios than fixed promotion types.

Promotion structure

Core components

Every promotion requires two expressions:

  1. EligibleExpression: Evaluates order state

    • Returns true/false
    • Determines promotion applicability
  2. ValueExpression: Calculates discount

    • Returns monetary value
    • Subtracts from order subtotal

Available properties

  • order: Matches Order model from v1/orders
  • Includes extended properties (xp)
  • items: Provides collection functions

Collection functions

Line item operations

  • items.any(): True if any item matches filter
  • items.all(): True if all items match filter
  • items.quantity(): Sum of matching quantities
  • items.count(): Number of matching line items
  • items.total(): Dollar amount comparison

Product categorization

  • product.incategory(): Direct category assignment
  • product.inparentcategory(): Category or child assignment

Array operations

  • contains(): Value exists in array
  • count(): Matching array items
  • any(): Any array item matches
  • all(): All array items match

Property operations

  • in(): Value exists in list
  • Supports comma-delimited lists

Implementation examples

Array operations

javascript
// Check array content
order.xp.myarray.contains('value2')

// Count array items
order.xp.myarray.count() = 3

// Check specific value
order.xp.myarray.any(item = 'four')

// Pattern matching
order.xp.Tags.all(item = 'tag*') = true

// Product tag check
items.any(Product.xp.Tags.contains('value2')

// Numeric array check
item.Product.xp.NumberArray.contains(23)

// Array value match
item.product.xp.myarray.any(item = 20)

// Pattern count
item.product.xp.Tags.count(item = 'tag*') = 3

Expression operators

Comparison operators

  • Equal: =
  • Less than: <
  • Greater than: >
  • Less/equal: <=
  • Greater/equal: >=

Logical operators

  • And: and
  • Or: or
  • Not: not

Mathematical operators

  • Addition: +
  • Subtraction: -
  • Multiplication: *
  • Division: /
  • Modulo: %

Helper functions

Minimum value

javascript
min(200, order.Total)
  • Returns smaller argument
  • Type conversion rules apply
  • Integer vs decimal handling

Maximum value

javascript
max(200, order.Total)
  • Returns larger argument
  • Type conversion rules apply
  • Integer vs decimal handling

Conditional logic

javascript
ifs(condition1, value1, condition2, value2, default)
  • Evaluates multiple conditions
  • Returns matching value
  • Last parameter is default

Rounding

javascript
round((order.Total * .1), 0)
  • Rounds to specified decimals
  • Supports expressions
  • Precise control

Promotion limits

Line item promotions

Requires LineItemLevel: true

Item limit

  • ItemLimitPerOrder: Maximum items
  • Applies discount per item
  • Excludes quantity limit

Quantity limit

  • QuantityLimitPerOrder: Maximum quantity
  • Applies discount per unit
  • Excludes item limit

Sort order

  • ItemSortBy: Property-based sorting
  • Supports descending with !
  • Includes extended properties
  • Default: DateAdded ascending

Example configuration

30% off least expensive 3 items over $50:

json
{
  "Code": "30OFF",
  "LineItemLevel": true,
  "ItemLimitPerOrder": 3,
  "ItemSortBy": "LineSubtotal",
  "EligibleExpression": "order.Subtotal >= 50",
  "ValueExpression": "item.LineSubtotal * .3"
}

Common scenarios

Order-level discounts

javascript
// $10 off over $50
EligibleExpression: "order.Subtotal > 50"
ValueExpression: "10"

// Free shipping over $60
EligibleExpression: "order.Subtotal >= 60"
ValueExpression: "order.ShippingCost"

Product-specific discounts

javascript
// BOGO (one free)
EligibleExpression: "items.quantity(ProductID = 'ABC') > 1"
ValueExpression: "items.total(ProductID = 'ABC') / items.quantity(ProductID = 'ABC')"

// $5 off with specific product
EligibleExpression: "items.any(ProductID = '123')"
ValueExpression: "5"

Category discounts

javascript
// 15% off category items
EligibleExpression: "item.product.incategory('Bikes')"
ValueExpression: "item.LineSubtotal * .15"

// 10% off sale items (max $20)
EligibleExpression: "items.all(Product.xp.OnSale = true)"
ValueExpression: "min(order.Subtotal * .1, 20)"

Quantity-based discounts

javascript
// 30% off 10+ accessories
EligibleExpression: "items.quantity(product.incategory('GuitarAccessories')) >= 10"
ValueExpression: "items.total(product.incategory('GuitarAccessories')) * .3"

// 20% off product combination
EligibleExpression: "items.any(ProductID = 'ABC') and items.any(ProductID = 'XYZ')"
ValueExpression: "(items.total(ProductID = 'ABC') + items.total(ProductID = 'XYZ')) * .2"

BOGO (scales with quantity)

javascript
EligibleExpression: "items.quantity(ProductID = 'XYZ') > 1"

ValueExpression: "((items.quantity(ProductID='XYZ')/2) - (items.quantity(ProductID='XYZ') % 2 * .5)) * items.total (ProductID='XYZ') / items.quantity(ProductID='XYZ')"

User-based discounts

javascript
// 25% off first order
EligibleExpression: "order.FromUser.xp.FirstOrder = true"
ValueExpression: "order.Subtotal * .25"

// 10% off for registered users
EligibleExpression: "not (order.FromUser.ID = 'myDefaultAnonUserID') and order.Subtotal > 0"
ValueExpression: "order.Subtotal * .10"

Advanced scenarios

javascript
// Multi-tier category discount
EligibleExpression: "items.total(product.incategory('A') >= 10 and item.product.incategory('A')"
ValueExpression: "ifs(items.total(product.incategory('A')) >= 50, item.LineSubtotal .15, items.total(product.incategory('A')) >= 30, item.LineSubtotal * .10, item.LineSubtotal * .05)"

// Order history discount
EligibleExpression: "orderhist.count('1Y') > 4"
ValueExpression: "5"

// Product history discount
EligibleExpression: "itemhist.quantity('6M', 'Product.ID = {productID}') >= 10"
ValueExpression: "order.Subtotal * .10"

Implementation notes

Limitations

  • Expression length: 400 characters
  • Optimize for efficiency
  • Evaluated at application and submit

Requirements

  • Order history requires Premium Search
  • Proper promotion assignments
  • User access via GET v1/me/promotions
If you have suggestions for improving this article, let us know!