Rule Groups & Logic
Rule Groups & Logic
Rule groups are the primary building blocks of discount configuration. Each rule group defines a set of conditions and a corresponding discount to apply when those conditions are met. Understanding how conditions are evaluated within a rule group — especially the interaction between AND/OR logic and the two condition categories — is essential for building correct discount rules.
Rule Group Structure
Every rule group shares a common set of fields, with additional type-specific fields depending on the function type.
Common Fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for the rule group |
name | string | Yes | Human-readable name for the rule group |
enabled | boolean | Yes | Whether this rule group is active |
priority | number | Yes | Evaluation order (lower numbers evaluate first) |
conditionLogic | string | Yes | How conditions combine: "and" or "or" |
conditions | array | Yes | Array of condition objects |
Type-Specific Fields
Depending on the function type, rule groups include additional fields:
- Conditional:
discountValue,target(product, order, or shipping target configuration) - Tiered:
tiers(array of tier definitions with quantity/spend thresholds and discount values) - BXGY:
buyConditions,getConditions,discountValue,maxUses(buy X / get Y configuration) - Bundle:
bundleItems,discountValue(bundle component definitions)
For details on discount values and targets, see the Discount Values & Targets reference.
Condition Logic Deep Dive
The conditionLogic field determines how the conditions array is evaluated. The behavior differs significantly between "and" and "or", particularly when mixing cart-level and product-level conditions.
AND Logic
When conditionLogic is set to "and", all conditions must be satisfied for the rule group to apply.
The evaluation proceeds in two phases:
-
Cart-level conditions are evaluated first. Every cart-level condition must pass. If any single cart-level condition fails, the entire rule group fails immediately — product-level conditions are never evaluated.
-
Product-level conditions filter individual lines. Each cart line is tested against all product-level conditions. A line must pass every product-level condition to be eligible for the discount. Lines that fail any product-level condition are excluded.
{
"conditionLogic": "and",
"conditions": [
{ "type": "cartSubtotal", "operator": "greaterThan", "value": 100 },
{ "type": "customerTag", "operator": "hasAny", "tags": ["VIP"] },
{ "type": "productTag", "operator": "hasAny", "tags": ["premium"] }
]
}
In this example:
- The cart subtotal must exceed $100 and the customer must have the “VIP” tag (both cart-level conditions must pass).
- Only lines with the “premium” product tag are eligible for the discount.
- If the subtotal is $80, the rule fails entirely — no products are discounted regardless of tags.
OR Logic
When conditionLogic is set to "or", the evaluation follows a more nuanced process that depends on whether cart-level conditions pass and whether product-level conditions are present.
The rules for OR logic are:
-
If any cart-level condition passes, ALL cart lines are eligible for the discount. Product-level conditions are skipped entirely — the passing cart-level condition is sufficient.
-
If all cart-level conditions fail but product-level conditions exist, each cart line is evaluated against the product-level conditions. A line is eligible if it passes any of the product-level conditions.
-
If all cart-level conditions fail and no product-level conditions exist, the rule group fails entirely.
This means OR logic creates a “fast path” through cart-level conditions: a single passing cart-level condition makes everything eligible without per-line filtering.
Example: OR with Mixed Conditions
Consider the following rule group:
{
"conditionLogic": "or",
"conditions": [
{ "type": "cartSubtotal", "operator": "greaterThan", "value": 200 },
{ "type": "productTag", "operator": "hasAny", "tags": ["premium"] }
]
}
Scenario A: Cart subtotal is $250
The cartSubtotal condition passes. Because a cart-level condition passed in OR mode, all lines in the cart are eligible for the discount — even lines without the “premium” tag. The productTag condition is never evaluated.
Scenario B: Cart subtotal is $150, cart contains lines tagged “premium” and “basic”
The cartSubtotal condition fails. Since all cart-level conditions failed but a product-level condition exists, the function evaluates each line individually:
- Lines tagged “premium” pass the
productTagcondition and are eligible. - Lines tagged “basic” fail and are excluded.
Scenario C: Cart subtotal is $150, no lines have the “premium” tag
The cartSubtotal condition fails. The productTag condition fails for every line. No lines are eligible, and the rule group produces no discount.
Empty Conditions
When the conditions array is empty, the rule group always matches. There are no conditions to fail, so the rule group is treated as unconditionally active.
{
"id": "rule_always_on",
"name": "Store-wide discount",
"enabled": true,
"priority": 1,
"conditionLogic": "and",
"conditions": []
}
This is a valid and common pattern for discounts that should apply universally without any prerequisites, such as store-wide sales or unconditional free shipping.
The conditionLogic value is irrelevant when conditions are empty — both "and" and "or" produce the same result (always match).