Skip to Content

Discount code mapping

StagingDiscountCode flattens Shopify’s nested discount shape into a handful of fields. You set one discount value flavor (percentage, amount, or freeShipping) plus optional minimum requirements and combination rules.

Quick reference — minimum loadable code

{ "original_id": rule_id, "title": rule_name, "code": coupon_code, "startsAt": from_date, "percentage": discount_percent / 100 }

Identity & schedule

titlestring

Internal name shown in Shopify admin.

"title": rule_name
codestring

The redemption code customers enter at checkout.

"code": coupon_code
startsAtstring (ISO8601)

When the code becomes active.

"startsAt": from_date
endsAtstring (ISO8601)

When the code expires. Omit for codes that never expire.

Discount value

Set exactly one of percentage, amount, or freeShipping. Setting more than one is undefined behavior.

percentagenumber

Decimal between 0 and 1 — 0.25 means 25% off. Not 25.

"percentage": discount_percent / 100
amountnumber

Fixed money amount off (in currencyCode).

"amount": discount_amount, "currencyCode": "USD"
currencyCodestring

Currency for amount. ISO 4217 (USD, EUR, …). Required when amount is set.

freeShippingboolean

true for a free-shipping discount code. Mutually exclusive with percentage / amount.

appliesOnEachItemboolean

For fixed-amount discounts: true means “$X off each qualifying line item”, false means “$X off the order subtotal”. Defaults to false if not set.

Limits

usageLimitinteger

Total redemptions allowed across all customers. null = unlimited.

"usageLimit": uses_per_coupon > 0 ? uses_per_coupon : null
appliesOncePerCustomerboolean

If true, a single customer can use the code only once.

recurringCycleLimitinteger

For subscription discounts: number of billing cycles the discount lasts. 0 means indefinite.

Minimum requirements

Set one (subtotal OR quantity), both, or neither.

minimumSubtotalnumber

Minimum order subtotal required for the discount to apply.

"minimumSubtotal": minimum_amount
minimumQuantityinteger

Minimum quantity of qualifying items required.

Scope

allItemsbooleandefault true

Whether the discount applies to all items. Defaults to true. The staging model only supports the all: true items selector today; narrowing to specific products / collections needs custom work post-migration.

appliesOnOneTimePurchaseboolean
appliesOnSubscriptionboolean

Combination rules

Whether this discount stacks with other discount classes. Set at least one to enable combinesWith.

orderDiscountsboolean

Stacks with other order-level discounts.

productDiscountsboolean

Stacks with product-specific discounts.

shippingDiscountsboolean

Stacks with shipping discounts.

Patterns

Magento percentage cart rule → Shopify code

{ "original_id": rule_id, "title": rule_name, "code": coupon_code, "startsAt": from_date, "endsAt": to_date, "usageLimit": uses_per_coupon > 0 ? uses_per_coupon : null, "appliesOncePerCustomer": uses_per_customer = 1, "percentage": discount_amount / 100, "minimumSubtotal": minimum_amount > 0 ? minimum_amount : null, "allItems": true }

Fixed-amount-off subtotal

{ "original_id": rule_id, "title": rule_name, "code": coupon_code, "startsAt": from_date, "amount": discount_amount, "currencyCode": store_currency, "appliesOnEachItem": false }

Free shipping over a threshold

{ "original_id": rule_id, "title": "Free shipping over " & $string(threshold), "code": coupon_code, "startsAt": from_date, "freeShipping": true, "minimumSubtotal": threshold }

Code that stacks with everything

{ …, "orderDiscounts": true, "productDiscounts": true, "shippingDiscounts": true }

Gotchas

Percentage is a decimal between 0 and 1. 0.25 for 25%, not 25. The most common mapping bug — load succeeds and the merchant later discovers customers redeemed for 2,500% off.

  • One discount value flavor only. Setting both percentage and amount produces undefined behavior in the load. Pick one per code.
  • amount without currencyCode loads but Shopify infers the shop’s primary currency, which can be wrong for multi-currency shops. Always set both.
  • combinesWith defaults to false for every class. If you don’t set any of orderDiscounts / productDiscounts / shippingDiscounts, the code combines with nothing.
  • Code uniqueness. Two discount codes with the same code collide on Shopify. If your source allows duplicates (some platforms do — different rules sharing the same code), resolve in the mapping by suffixing with the rule ID.
  • Scope today is “all items”. If the merchant’s source rule was scoped to specific products or categories, that nuance is lost. Surface a warning to the merchant; the code still applies but more broadly than the source.
  • Subscription cycles. recurringCycleLimit only matters if the destination Shopify store has subscription apps — for plain one-time purchases, it has no effect.
Last updated on