Guide

Shopify selling plans, explained — billing, delivery, pricing policies

A deep technical walkthrough of the primitive every subscription app on Shopify is built on. What a selling plan actually is, how the three policies (billing, delivery, pricing) interact, how the cart and checkout behave, and the edge cases — mixed carts, multi-currency, B2B price lists, gift cards, discount stacking — that catch out merchants and developers alike.

16 min readUpdated 21 May 2026By SimpleSubscription Team
On this page (11)
  1. What a selling plan actually is
  2. Billing policy — when and how often the card gets charged
  3. Delivery policy — when fulfillment actually triggers
  4. Pricing policy — discounts, first-order incentives, and price overrides
  5. Selling plan groups: attaching plans to products
  6. Cart, checkout, and order behaviour with selling plans
  7. Mixed carts: subscription + one-time in the same checkout
  8. Edge cases: gift cards, B2B, multi-currency, discount stacking
  9. Inspecting selling plans via the GraphQL Admin API
  10. When you need multiple selling plan groups
  11. Pitfalls: pricing overrides during sales, anchor confusion, and silent failures

Shopify selling plans are the native way to mark a product as available on a recurring schedule. They were introduced in 2021 as part of Shopify's Subscription Contract API and are now the only supported mechanism — every modern subscription app (Recharge, Loop, Skio, SimpleSubscription) builds on the same primitive. Understanding selling plans helps you reason about every weird behaviour you'll otherwise blame on the app: why the cart price doesn't match the widget, why a discount stacked unexpectedly during a sale, why a gift card couldn't be used on a renewal, why a B2B customer saw the wrong price. This guide unpacks the data model, the three policies that define a plan's behaviour, the GraphQL shape, and the edge cases the official docs gloss over.

What a selling plan actually is

A selling plan is a Shopify object that tells the storefront, cart, and checkout: "this product can be purchased on a recurring schedule, here's how often, here's the price, and here's when the customer is charged." It is not a separate product. It is metadata attached to one or more existing products (or variants) describing how the recurring version of the purchase behaves. The product, its inventory, and its variants stay exactly as they were — a selling plan just says "and you can also buy this one every 4 weeks at 10% off."

Three things distinguish a selling plan from a legacy subscription system or a one-time product. First, it lives inside Shopify's Subscription Contract API — a renewal creates a real Shopify order with real tax, real shipping, real fulfillment records. Second, the customer's payment method is vaulted at first checkout through Shopify Payments (or another supported gateway with stored-card support), so renewals charge without the customer touching anything. Third, all three policies — billing, delivery, pricing — are defined on the selling plan itself, not on the product, which means the same product can be offered on multiple schedules without duplicating SKUs.

  • Selling plan: a single recurring offer (e.g. "every 4 weeks, 10% off")
  • Selling plan group: a collection of related plans attached to one or more products (e.g. weekly + monthly + quarterly cadences for the same coffee bag)
  • Subscription contract: the record of one customer's active subscription created at checkout from a selling plan
  • Subscription billing attempt: the renewal-day API call that creates a new order from the contract
A selling plan is metadata that turns an existing product into a recurring offer — without duplicating SKUs.

Billing policy — when and how often the card gets charged

The billing policy answers a single question: when does Shopify charge the customer's card? It has two main shapes: recurring (charged every N days/weeks/months indefinitely until cancelled) and fixed (a prepaid plan that charges once and delivers N times, like "pay today, get 3 months of coffee"). Most stores start with recurring and add fixed later for gift subscriptions or prepay-and-save offers.

For recurring plans, the billing interval doesn't have to match the delivery interval. A prepaid box subscription might bill quarterly (one charge, $90) but deliver monthly (one box per month). That's expressed as billingPolicy.interval = MONTH, intervalCount = 3, with a delivery policy of MONTH/1. Shopify's API lets you decouple billing from delivery, which is what makes prepaid and bulk-discount offers possible without writing custom code.

Two billing-policy concepts catch out new merchants. The first is the anchor date — does "every 4 weeks" mean exactly 4 weeks from each customer's signup date, or every 4 weeks aligned to the 1st of the month? The default is signup-relative (each subscriber renews on their own anniversary). Calendar-anchored renewals are useful when you want fulfillment concentration (e.g. weekly produce box all ships every Tuesday), but they create traffic spikes and need a 3PL that can absorb them. The second is the maximum cycle count — leave it null and the plan continues until the customer cancels; set it to 3 and the contract auto-completes after 3 renewals, which is how you build a fixed-term gift subscription.

Tip
Spread renewal dates across the month

Calendar-anchored renewals on the 1st look tidy on paper but concentrate every subscriber's fulfillment into the same 24 hours. Most stores see better fulfillment economics and lower stockout risk with signup-relative anchors — renewals naturally spread across the month as new subscribers join.

Billing interval, billing anchor, and max cycle count fully describe when the card gets charged.

Delivery policy — when fulfillment actually triggers

The delivery policy says how often the product physically ships. For most subscriptions it matches the billing interval — charge monthly, ship monthly. Where it diverges is on prepaid plans: charge once, ship monthly for 3 months. The delivery policy carries its own interval (DAY, WEEK, MONTH, YEAR), interval count, and an anchor that defines when within that interval the order is generated for fulfillment.

The fulfillment trigger isn't automatic — it happens when the renewal creates the next Shopify order. The order then enters your normal fulfillment workflow (3PL, ShipStation, manual). This matters because if your subscription app's cron job fails to run on a renewal day, no order is created and no fulfillment trigger fires. Reliable cron infrastructure (cron-job.org pinging the app's renewal endpoint, or Shopify's own scheduling) is the difference between subscribers getting their orders and getting silent gaps.

Anchor dates inside the delivery policy are also where prepaid plans get their behaviour. A 3-month prepaid coffee subscription with delivery anchored to the 1st of each month means the customer's card was charged on day 0, but the second and third orders are auto-generated on the 1st of the following two months. The customer experiences three regular shipments; the merchant only sees one billing event.

Watch out
Delivery interval mismatched with shipping cutoff

If your 3PL cuts off Monday's outbound orders at 10am and your delivery policy generates renewal orders at 11am, every subscription order misses the cutoff and ships a day late. Check what time of day your subscription app actually creates renewal orders, and align it with your warehouse cutoff — most apps let you configure this.

Delivery interval and anchor define when each shipment is generated — independent of when the customer was billed.

Pricing policy — discounts, first-order incentives, and price overrides

The pricing policy on a selling plan is where most of the merchant-facing logic lives. You define the discount type (percentage, fixed amount, or fixed price), the value, and whether it applies to every recurring order or just the first. This is how you express "10% off, every order" vs "20% off first order, 10% off thereafter" — the latter is two pricing adjustments attached to the same plan, one with appliesOnFirstOrder = true and one with appliesOnEachOrder = true.

The output of the pricing policy is a value called perDeliveryPrice — the actual amount the customer pays per shipment after all discounts are applied. This is the authoritative price for that subscription line, and it is what Shopify's cart and checkout actually charge. The most common bug in subscription widgets is JavaScript that recalculates a discounted price independently (productPrice * 0.9) instead of reading perDeliveryPrice from the selling plan allocation that Shopify already computed. Always read the displayed price from the allocation, never from a JS-side calculation, or your widget price will drift out of sync with what the cart actually charges.

Pricing policies also support fixed price overrides — say "this plan sells for exactly $24, regardless of the underlying product price." Useful when the product's regular price changes seasonally but you want the subscription price stable, or when you're running a promo and need a one-off subscription tier at a specific price point. Fixed-price overrides ignore the product's compareAtPrice, so make sure the subscribers' perceived discount still tracks reality.

  • PERCENTAGE: e.g. 10% off — recalculates if the underlying product price changes
  • FIXED_AMOUNT: e.g. $5 off — stable absolute discount regardless of product price changes
  • PRICE: e.g. "this plan sells for $24" — fixed price overrides any product price changes
  • appliesOnFirstOrder: discount applies once, on the initial purchase
  • appliesOnEachOrder: discount applies on every renewal
perDeliveryPrice is the authoritative subscription price. Read it; never recalculate it.

Selling plan groups: attaching plans to products

Selling plans don't attach to products directly. They live inside a selling plan group, and the group is what gets attached to one or more products or variants. A group is the unit a customer interacts with on the product page — the dropdown of available cadences is one group, and each option in that dropdown is one selling plan inside it.

This is why your customer portal, dunning emails, and analytics dashboards group subscriptions by plan rather than product: the plan is the recurring offer, and one product can belong to multiple groups (e.g. a coffee bag in both "monthly coffee subscription" and "prepaid 3-month coffee gift"). When you query the API for a contract's subscribed line items, you get the selling plan ID alongside the variant ID — that's the join key for everything analytics-related.

Attachment can be per-product or per-variant. Per-product is simpler but less flexible: every variant of the product is subscribable on the same terms. Per-variant lets you, for example, offer the 12oz bag on monthly subscription but require the 5lb bag to be purchased one-time only. Most stores start per-product and only move to per-variant when they have a clear SKU-level reason.

Premium Coffee Blend
$29.90
One-time purchase
$29.90
Subscribe & Save
$25.41 Save 15%
Deliver every
1 week -20%1 month -15%3 months -10%
Billing
Per delivery
Annual Save extra 10%
Free shipping on every delivery
Skip or cancel anytime
Subscribe — $25.41/mo
Selling plan rendered on the product page through the subscribe & save widget
Plans live inside groups; groups attach to products or variants. The plan ID is the join key for analytics.

Cart, checkout, and order behaviour with selling plans

When a customer adds a subscribable product to their cart with a selling plan attached, Shopify treats it as a different line item than the one-time version of the same product. The cart shows the line with the plan label ("Coffee — Monthly subscription, 10% off"), the perDeliveryPrice, and the next charge date. At checkout, Shopify Payments (or a supported gateway) vaults the customer's card and creates a subscription contract alongside the regular order.

The first order is a normal Shopify order — it shows up in the Orders admin like any other purchase, with full tax and shipping calculation, fulfillment workflow, and customer notification email. The difference is the order has a subscription contract attached, and on the contract's next billing date, Shopify's API will trigger a new billing attempt that creates a follow-up order using the vaulted payment method.

Tax and shipping are recalculated at every renewal — they're not frozen at signup. If a customer's shipping address changes through the portal, the next renewal recalculates shipping rates and tax based on the new address. This means your selling plan doesn't need to encode shipping cost; Shopify's shipping zones and rates apply at renewal time exactly as they would on a fresh one-time order. The same is true for VAT and state sales tax — Shopify Tax recalculates per renewal using the renewal-date address.

First order = regular Shopify order with a contract attached. Tax, shipping, and address are re-evaluated at every renewal.

Mixed carts: subscription + one-time in the same checkout

A single Shopify checkout can contain both subscription line items and one-time line items. The customer pays once for everything at checkout; the subscription items create contracts and the one-time items behave normally. This is one of the under-appreciated benefits of Shopify's native selling plan system — legacy subscription apps used separate checkouts for subscriptions, which broke conversion and confused customers who couldn't combine a subscription bag of coffee with a one-time gift mug in the same order.

There are a couple of constraints. All subscription items in a mixed cart must share the same shipping address (Shopify can't split a contract across addresses). All subscription items must be available through a gateway that supports stored payment methods — adding a subscription item from a payment-method-incompatible gateway will block checkout. And shipping rates are calculated once for the combined cart at checkout, not per-line — if you ship subscriptions and one-times from different warehouses, your shipping configuration needs to account for it.

Tip
Use mixed carts to drive subscription adoption

A customer browsing for a one-time gift who sees a Subscribe & Save option on their main product, adds both, and checks out together — that's a higher conversion path than forcing them to checkout twice. Make sure your widget actively offers the subscription option even when the customer has one-time items already in the cart.

Mixed carts work natively. Same address, same supported gateway, single shipping calculation.

Edge cases: gift cards, B2B, multi-currency, discount stacking

Selling plans interact with the rest of Shopify in ways that aren't obvious from the docs. Here are the edge cases that bite merchants and the developers building on top of the platform.

  • Gift cards: customers can apply a gift card to the first order of a subscription, but Shopify won't auto-apply remaining gift card balance to subsequent renewals — the renewal charges the vaulted card in full. If a customer expects their $50 gift card to carry across three $20 renewals, they'll be surprised; document this in your subscription FAQ.
  • B2B price lists: Shopify B2B catalogs can have wholesale prices on the underlying product, but a percentage-off selling plan applies on top of the B2B price, not the retail price. A 10% subscription discount on a product that's also 30% off via wholesale catalog stacks to ~37% off. Use FIXED_AMOUNT or PRICE pricing policies if you don't want B2B and subscription discounts to compound.
  • Multi-currency (Shopify Markets): selling plans price in the shop's default currency, and Markets converts at checkout using the current FX rate. If you offer a $24 subscription and a customer in EUR pays €22 today, in 4 weeks the FX rate may have shifted — Shopify converts at the renewal-day rate, so the customer might pay €21.40 or €22.60. This is usually fine, but it surprises customers in volatile currencies.
  • Discount stacking with site-wide promotions: a 10% subscription discount applied through the selling plan, combined with a 20% Black Friday site-wide automatic discount, can stack to ~28% off (multiplicatively) and lock that price in for every renewal. Most subscription apps offer a "don't combine with other discounts" setting on the selling plan group — turn it on before any sale.
  • Product deletion: deleting a product that's attached to an active subscription contract orphans the contract — Shopify will pause it on the next renewal attempt. Archive instead of delete if you have subscribers on that SKU, then migrate them to a replacement product through the app's swap feature.
Watch out
Site-wide sale stacking

The #1 selling plan disaster: you run a 20% Black Friday automatic discount, your 10% Subscribe & Save selling plan stacks on top, and every subscriber who signs up that weekend is locked into ~28% off for the lifetime of their subscription. Disable subscription discount stacking before any sale, or auto-revert subscription prices to the standard discount after the first renewal cycle.

Gift cards, B2B, multi-currency, and discount stacking each behave in non-obvious ways — read the rules before you launch.

Inspecting selling plans via the GraphQL Admin API

Every selling plan, group, and contract is queryable through Shopify's GraphQL Admin API. If you're a developer building a custom subscription experience, an analytics integration, or just want to audit what plans exist on a store, this is the entry point. The basic shape of a selling plan group query looks like this:

query SellingPlanGroups {
  sellingPlanGroups(first: 10) {
    edges { node {
      id
      name
      sellingPlans(first: 5) { edges { node {
        id
        name
        billingPolicy { ... on SellingPlanRecurringBillingPolicy { interval intervalCount } }
        deliveryPolicy { ... on SellingPlanRecurringDeliveryPolicy { interval intervalCount } }
        pricingPolicies { ... on SellingPlanFixedPricingPolicy { adjustmentType adjustmentValue { ... on MoneyV2 { amount currencyCode } } } }
      }}}
      products(first: 5) { edges { node { id title } } }
    }}
  }
}

Two endpoints matter most in practice. sellingPlanGroups lists every group on the shop with its attached plans and products — useful for an admin audit or a migration script. subscriptionContracts lists every active subscription on the shop with the customer, payment method, and next billing date — that's what your billing cron job iterates over each day to know who to charge. Both endpoints respect the read_own_subscription_contracts and read_purchase_options scopes; without those scopes your queries return empty arrays with no error, which is its own debugging trap.

GraphQL queries on sellingPlanGroups and subscriptionContracts are the foundation of any custom subscription integration.

When you need multiple selling plan groups

Most stores start with one selling plan group per product line — "monthly coffee subscription" containing weekly, biweekly, and monthly plans. That's enough for a long time. You'll know you need a second group when one of these patterns appears.

  • Prepaid vs recurring on the same product: a coffee bag offered both as "monthly recurring, 10% off" and as "prepay 3 months, save 15%" — these are different billing behaviours and belong in separate groups so the product-page widget can present them as distinct choices
  • Gift subscriptions: fixed-term plans (3 months, 6 months) sold as gifts behave differently from open-ended subscriptions and need their own group with maxCycles set
  • B2B vs DTC pricing: a wholesale customer-list-restricted plan with B2B-only pricing alongside the standard retail plan; the storefront only shows the appropriate group based on customer tags
  • Membership tiers: a Plus tier with deeper discounts gets its own group, with eligibility gated by customer tag or app logic

The cost of adding a second group is mainly UX: the product-page widget has to present multiple groups intelligibly. Most subscription apps handle this by showing tabs or radio buttons for groups, then dropdowns within each for plan selection. If you find yourself with four or more groups on a single product, take a hard look — that's usually a sign the choice architecture is overwhelming customers and adoption will suffer.

Add a new group when the billing behaviour is genuinely different. Don't add groups just to express discount variants.

Pitfalls: pricing overrides during sales, anchor confusion, and silent failures

The pitfalls that wreck a launch usually come from misunderstanding how selling plans interact with the rest of Shopify, not from the API itself. Here are the recurring ones that show up in support tickets month after month.

Checklist
Selling plan launch sanity check
  • Verify perDeliveryPrice in the cart matches the widget display on desktop AND mobile — recalculation drift is the #1 customer-trust bug
  • Disable site-wide discount stacking on selling plan groups before any sale event
  • Confirm the billing anchor (signup-relative vs calendar-anchored) actually matches what you described to customers
  • Test a renewal end-to-end on a dev store — set up a contract with a 1-minute renewal interval, let it fire, confirm an order is created with correct tax + shipping
  • Confirm gift card application behaviour matches your subscriber FAQ (Shopify won't auto-apply card balance across renewals)
  • If you support B2B, verify subscription discounts don't compound with wholesale pricing unintentionally
  • Audit subscription contracts after the first week — orphaned, paused, and failed contracts shouldn't accumulate silently

Silent failures are the worst category. A misconfigured cron that doesn't run, a deprecated scope that returns empty arrays, a discount that stacks unexpectedly — none of these throw errors. They just produce wrong numbers in the analytics dashboard and confused customer emails. The defense is structured logging at every step of the renewal pipeline (billing attempt initiated, order created, fulfillment triggered, notification sent) so you can audit the trail when something looks off. Most subscription apps surface this in their admin UI; if yours doesn't, that's a signal worth taking seriously.

The expensive selling-plan bugs are silent: drifted prices, stacked discounts, missed renewals. Log every step and audit weekly.

Selling plan technical FAQ

Can I change a selling plan's price after subscribers sign up?

Yes, but with care. Updating the selling plan's pricing policy changes the price for all future renewals on existing contracts — subscribers who signed up at $20/month will start paying the new price on their next renewal. Most jurisdictions and most reputable subscription practice require giving subscribers advance notice (and a chance to cancel) before a price increase takes effect. California's AB-390 mandates explicit advance notice for any material change. Don't just edit the plan and let renewals catch the new price.

Do Shopify selling plans support free trials?

Partially. Shopify doesn't have a native "free trial" concept on selling plans — you can't say "first 14 days free, then start billing." The workarounds are (a) a fixed-amount discount of 100% on the first order via pricingPolicy.appliesOnFirstOrder, or (b) a delayed first-charge using billingPolicy anchor configuration with a trial period your subscription app manages outside the plan itself. Most apps offer the second pattern as a "trial" feature.

How do selling plans interact with Shopify Markets and multi-currency?

Selling plans are priced in the shop's default currency. Shopify Markets handles conversion to the customer's local currency at checkout using the current FX rate, and renewals are converted at the renewal-day rate. The customer is billed a stable amount in your default currency but the displayed and charged local-currency amount may fluctuate slightly between renewals as FX moves. This is usually fine; declare it in your subscription terms if your customer base is in volatile currencies.

What happens when a product attached to a selling plan is deleted?

Active subscription contracts tied to that product become orphaned. Shopify will pause those contracts on their next renewal attempt because there's no inventory or pricing source to draw from. Always archive (not delete) products with active subscribers, then use your app's swap feature to migrate subscribers to a replacement product before fully removing the old one.

Can a customer have two active subscriptions of the same selling plan?

Yes. Each checkout that includes the selling plan creates a separate subscription contract, so a customer can have multiple parallel contracts on the same plan. Most stores treat this as a feature (a customer who orders two of the same coffee monthly), but if it's a problem (e.g. duplicate signup bug), enforce one-per-customer at the cart level using app logic — Shopify doesn't enforce uniqueness on its own.

Can a selling plan apply to only specific variants of a product?

Yes. Selling plan groups can attach at either the product level (all variants subscribable on the same terms) or the variant level (only specific SKUs subscribable). Variant-level attachment is what you use when you want, say, the small bag subscribable but the large bag one-time only. Most subscription apps let you toggle this in their admin UI.

What's the difference between billing interval and delivery interval?

Billing interval is when the customer's card is charged. Delivery interval is when a fulfillment order is created. They're usually the same (charge monthly, ship monthly) but can be decoupled for prepaid plans — charge once today, ship three times over the next three months. The two are independent fields on the selling plan and can have different intervals and anchors.

Can I offer different selling plans to different customer segments (B2B, VIP)?

Yes, by gating selling plan group visibility on the storefront via customer tags or app logic. Shopify B2B catalogs also let you scope selling plans to wholesale customer lists. Most subscription apps expose a "customer eligibility" setting on each plan group that controls who sees the plan on the product page.

What is perDeliveryPrice and why does it matter?

perDeliveryPrice is the authoritative price each renewal will charge, after all pricing policy adjustments are applied. It's exposed in the selling plan allocation on the cart and product page. Widgets, dunning emails, and analytics should always read this value directly from Shopify's data — never recalculate it client-side in JavaScript. Client-side calculation is the #1 cause of widget-vs-cart price drift bugs.

Does Shopify enforce minimum or maximum cycle counts on selling plans?

Shopify doesn't enforce hard limits. You can leave maxCycles null (continues until customer cancels), set it to 1 (single-charge equivalent to one-time, rarely useful), or any positive integer (fixed-term subscription that auto-completes). Most stores use null for open-ended plans and 3/6/12 for gift or prepaid plans.

Can selling plans be discovered through Shopify search or collections?

Products attached to selling plans appear in normal collections and search results — the selling plan itself doesn't change product discoverability. What changes is the product page: it now shows the subscribe option. If you want a "subscribable products only" collection, build it as a smart collection filtering on a product tag your app sets when attaching a selling plan.

Do selling plans support installment payments ("4 payments of $25")?

Not natively — Shopify's selling plans are designed for recurring subscriptions, not split payments. For 4-of-X installments you'd use a buy-now-pay-later provider (Shop Pay Installments, Affirm, Klarna) at checkout. The use cases are different: subscriptions deliver repeatedly, installments split a single purchase into payments. Don't try to model installments as selling plans — the UX and accounting will fight you.

The pillar

Read the complete Shopify Subscription App overview

Pricing, every feature, side-by-side comparison, FAQ — the single page that ties all these guides together.

Go to the pillar

Build on selling plans the right way

SimpleSubscription uses Shopify's native selling plan and Subscription Contract API end-to-end. No parallel billing, no price drift, no surprises.

Install on Shopify

Start free · 14-day trial on paid plans · Zero transaction fees · Free migration