Conditions
The 15 discount-rule condition types across cart, customer, shipping, and time, plus AND/OR match logic and the timezone gotcha for time-based rules.
A discount rule has two gates. Filters decide what products the rule applies to (see Discount rules for the filter UI). Conditions decide when the rule activates, based on cart value, who the customer is, where they're shipping, or the time of day. No conditions = the rule always fires when its filters match.
Every condition has three fields: a type, an operator, and a value. The 15 types group into 4 families.
Cart conditions
| Type | What it checks | Operators | Value type |
|---|---|---|---|
| Cart Subtotal | Total cart subtotal before discount. | >=, <=, =, between | Number ($) |
| Subtotal by Category | Subtotal of items in selected categories. Replaces minFilteredAmount. | >=, <=, =, between | Number + categoryIds |
| Subtotal by Products | Subtotal of selected products only. | >=, <=, =, between | Number + productIds |
| Line Items Count | Number of distinct line items in cart. | >=, <=, =, between | Integer |
| Total Items Count | Sum of all quantities across all lines. | >=, <=, =, between | Integer |
Customer conditions
These only work for signed-in shoppers. Customer Tag, Total Spent and Order Count all evaluate to false for anyone who is not authenticated, so a rule using them never fires at guest checkout, silently and with no error. If most of your buyers check out as guests, a "VIP customers only" rule will look broken. Pair it with a storefront that requires sign-in, or accept that it only rewards account holders.
| Type | What it checks | Operators | Value type |
|---|---|---|---|
| First Order | Is this the customer's first order? Judged on identity, not guest status, so an unidentified cart passes optimistically. | toggle (true/false) | Boolean |
| Customer Tag | Customer is in any of the selected segments. False for guests. | in, not_in | Customer tags |
| Total Spent | Lifetime spend across all orders. False for guests. | >=, <=, =, between | Number ($) |
| Order Count | Number of past orders. False for guests. | >=, <=, =, between | Integer |
| Is Logged In | Customer must be authenticated (not a guest checkout). | toggle (true/false) | Boolean |
Shipping conditions
| Type | What it checks | Operators | Value type |
|---|---|---|---|
| Shipping Country | The country on the shipping address (ISO 2-letter code). | in, not_in | Country codes |
| Shipping Region | The state/region on the shipping address. | in, not_in | Region codes |
| Shipping Postal Code | Match by postal code (prefix or exact). | starts_with, in, not_in | Strings |
Time conditions
| Type | What it checks | Operators | Value type |
|---|---|---|---|
| Day of Week | The current day in the store's timezone. | in, not_in | SUN, MON, …, SAT |
| Hour Range | The time of day in the store's timezone. | between | Minutes from midnight (0 to 1439), not hours, so 5pm is 1020. The dashboard shows a time picker and converts for you; only API/SDK callers set the number directly. |
Timezone gotcha, read this! Time conditions evaluate against the store's timezone (set on the Store record, default
UTC). If your store is in Israel but timezone is left at UTC, your "Happy Hour 17:00 to 19:00 IST" will actually fire at 17:00 to 19:00 UTC = 20:00 to 22:00 IST. Set Settings → General → Timezone toAsia/Jerusalem(or your IANA zone) BEFORE creating time-based rules.
Match logic: AND vs OR
At the top of the Conditions dialog, the Match toggle decides how rows combine:
- All conditions (AND, default) means every row must pass. Use for layered targeting: "VIP customer (Total Spent ≥ $5,000) AND ordering from US (Shipping Country = US)".
- Any condition (OR) means at least one row must pass. Use for "OR'd campaigns": "Is logged in OR First Order" = welcome bonus for either new accounts or returning members.
Conditions and shoppers you can't identify yet
Several conditions depend on knowing who the shopper is, and at cart stage you often don't. It's worth knowing which way each one falls:
- Customer group, total spent, order count all need a signed-in customer and are false for anyone who isn't. A "VIP, spent over $5,000" rule therefore never fires for a guest, even one whose email you have.
- First order is judged on identity, not on guest status. An unidentified cart passes it optimistically; a guest who has entered a checkout email is judged on their real order history, so a returning guest correctly fails it.
- Shipping location: before an address is known, an
iscondition fails and anis notcondition passes. So a geo-targeted rule stays quiet while the shopper browses, and a geo-exclusion rule applies until proven otherwise.
If a rule needs to reward signed-in customers, that is exactly what it will do. Just be aware that guests are not "not yet matched", they are excluded.
A ceiling on active rules
A store evaluates up to 500 active rules. Past that, the lowest-priority ones stop being considered. If you are anywhere near that number, disable what you're not using rather than letting the cutoff choose for you.
What's next?
- Discount rules show where conditions live in the rule form.
- Rule types cover what each rule does once its conditions pass.
- Stacking & priority covers when multiple matching rules collide.
- Promotion recipes show conditions in action (Happy Hour, VIP, geo-targeted).
Rule types
The 7 discount rule types (Product, Order, Buy X Get Y, Buy X Get X, Volume, Shipping, Bundle) and the exact config each one accepts, including per-unit vs set pricing on volume tiers, with JSON examples for the API/SDK.
Stacking & priority
How coupons and discount rules combine, covering per-rule stacking toggles, priority order, the store-wide Stacking Mode (Stack All / Apply Best / Apply First), and why a rule didn't fire.