Build a selling plan
Selling plans represent how products can be sold and purchased. When you create a selling plan, you can determine the policies under which a product can be sold. For example, you can create a selling plan where a customer can purchase a subscription on a monthly billing cycle, and where you offer a 15% discount for weekly deliveries of the product.
This guide shows you how to create a "Subscribe and save" and a "Prepaid" selling plan, and how to associate products with them.
Anchor to RequirementsRequirements
- Most subscriptions, pre-order and try before you buy apps need to request API access through the Partner Dashboard. We give API access to apps that are designed according to our [principles for subscriptions, pre-order and TBYB apps] (/docs/apps/selling-strategies/purchase-options#shopifys-principles).
- Public apps that use subscriptions, pre-order or TBYB need to meet specific requirements to be published on the Shopify App Store.
- Custom apps created in the Shopify admin can't use subscriptions, pre-order or TBYB because these apps can't use extensions or request access to protected scopes. If you're building a solution for a single store, then build your custom app in the Partner Dashboard.
- Your app can make authenticated requests to the GraphQL Admin API.
- Your app has the
write_products
,read_customer_payment_methods
,read_own_subscription_contracts
, andwrite_own_subscription_contracts
access scopes. Learn how to configure your access scopes using Shopify CLI. - You've created products and product variants in your development store.
- To be eligible to use Shopify subscriptions, users need to meet the qualifying criteria.
- You've familiarized yourself with the concept of selling plans.
Anchor to Step 1: Create a selling plan groupStep 1: Create a selling plan group
Subscriptions, pre-orders, TBYB, and associated records, including SellingPlanGroup
, SellingPlan
, policies, and associations to products and variants, are deleted 48 hours after a user uninstalls a subscriptions, pre-orders, or TBYB app. Products and product variants aren't deleted. We recommend backing up Subscriptions, pre-orders, and TBYB records in case you need to restore them later.
In the following example, a selling plan group is created using the sellingPlanGroupCreate
mutation.
The input fields include name
(the plan group name that customers see), merchantCode
(the plan name that the merchant sees), sellingPlansToCreate
(the individual selling plans to create), options
(the selling plan options available in the drop-down list in the storefront), and position
(how the options are sorted).
Learn more about GraphQL Admin API objects for purchase options. For more information on input fields and values, refer to the following resources:
SellingPlan
objects are grouped together in Liquid when they are created by the same app, and when they have the same selling_plan_group.name
and selling_plan_group.options
values. For more information, refer to the selling_plan_group
object.
Within each individual selling plan, the billing, delivery, and pricing policies are set:
billingPolicy
: The schedule is based on a weekly, every two weeks, or monthly pay per delivery subscription.deliveryPolicy
: The schedule is based on the merchant offering delivery every week, two weeks, and one month.pricingPolicies(fixed)
: The pricing is set at 15% off for deliveries every week, 10% off for deliveries every two weeks, and 5% off for deliveries every month. Selling plan pricing policies also work in conjunction with price lists. For more information, refer to the Catalogs overview.
The category
field should be set to SUBSCRIPTION
.
If you need to define more advanced delivery behaviors for subscriptions, such as specifying that fulfillment starts on a certain date each month, then you can include anchors in your API call. The following example sets billing and delivery anchor dates on Mondays or on the 15th of the month.
The interval
needs to be the same within a selling plan. For example, you can specify either WEEK
or MONTH
, but not both in the same plan. For information about other errors related to selling plans, refer to SellingPlanGroupUserErrorCode
.
Anchor to Selling plan API propertiesSelling plan API properties
The following selling plan API properties display merchant-facing strings on the Product page in Shopify admin and on the storefront product page and checkout. The app populates the strings. To provide the best user experience, you can follow the Subscription UX guidelines and the Pre-orders and try before you buy UX guidelines.
Field | Content guideline | Description |
---|---|---|
SellingPlan.name | Subscription, delivery every week | Display type and delivery frequency selected by the customer. |
Pattern: [Subscription type], delivery every [frequency] | ||
SellingPlanGroup.description (if field is set) | SellingPlanGroup.summary | Shopify will output the contents of SellingPlanGroup.summary directly. It will not add the Customer can choose string. |
SellingPlanGroup.description (if field isn't set) | Customer can choose
| Shopify will output Customer can choose: and loop through the selling plan group's associated selling plans, outputting SellingPlan.name. |
POST https://{shop}.myshopify.com/admin/api/{api_version}/graphql.json
GraphQL mutation
mutation {
sellingPlanGroupCreate(
input: {
name: "Subscribe and save"
merchantCode: "subscribe-and-save"
options: ["Delivery every"]
position: 1
sellingPlansToCreate: [
{
name: "Delivered every week"
options: "1 Week(s)"
position: 1
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: WEEK,
intervalCount: 1
anchors: { type: WEEKDAY, day: 1 }
}
}
deliveryPolicy: {
recurring: {
interval: WEEK,
intervalCount: 1
anchors: { type: WEEKDAY, day: 1 }
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 15.0 }
}
}
]
}
{
name: "Delivered every two weeks"
options: "2 Week(s)"
position: 2
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: WEEK,
intervalCount: 2
anchors: { type: WEEKDAY, day: 1 }
}
}
deliveryPolicy: {
recurring: {
interval: WEEK,
intervalCount: 2
anchors: { type: WEEKDAY, day: 1 }
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 10.0 }
}
}
]
}
{
name: "Delivered every month"
options: "1 Month"
position: 3
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: MONTH,
intervalCount: 1
anchors: { type: MONTHDAY, day: 15 }
}
}
deliveryPolicy: {
recurring: {
interval: MONTH,
intervalCount: 1
anchors: { type: MONTHDAY, day: 15 }
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 5.0 }
}
}
]
}
]
}
resources: { productIds: [], productVariantIds: [] }
) {
sellingPlanGroup {
id
}
userErrors {
field
message
}
}
}
mutation {
sellingPlanGroupCreate(
input: {
name: "Prepaid subscription"
merchantCode: "prepaid"
options: ["Delivery every"]
position: 1
sellingPlansToCreate: [
{
name: "12 week prepaid subscription, delivery every week"
options: "1 Week(s)"
position: 1
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: WEEK
intervalCount: 12
}
}
deliveryPolicy: {
recurring: {
interval: WEEK
intervalCount: 1
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 20.0 }
}
}
]
}
{
name: "12 week prepaid subscription, delivery every two weeks"
options: "2 Week(s)"
position: 2
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: WEEK
intervalCount: 12
}
}
deliveryPolicy: {
recurring: {
interval: WEEK
intervalCount: 2
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 15.0 }
}
}
]
}
{
name: "12 week prepaid subscription, delivery every three weeks"
options: "3 Week(s)"
position: 3
category: SUBSCRIPTION
billingPolicy: {
recurring: {
interval: WEEK
intervalCount: 12
}
}
deliveryPolicy: {
recurring: {
interval: WEEK
intervalCount: 3
preAnchorBehavior: ASAP
cutoff: 0
intent: FULFILLMENT_BEGIN
}
}
pricingPolicies: [
{
fixed: {
adjustmentType: PERCENTAGE
adjustmentValue: { percentage: 10.0 }
}
}
]
}
]
}
resources: { productIds: [], productVariantIds: [] }
) {
sellingPlanGroup {
id
}
userErrors {
field
message
}
}
}
JSON response
{
"data": {
"sellingPlanGroupCreate": {
"sellingPlanGroup": {
"id": "gid://shopify/SellingPlanGroup/294969"
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
{
"data": {
"sellingPlanGroupCreate": {
"sellingPlanGroup": {
"id": "gid://shopify/SellingPlanGroup/294968"
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
Use a Product subscription app extension to make sure that the Create subscription plan function works as expected from the product or variant page in Shopify admin. If you're not familiar with extensions, then refer to Getting started building a product subscription app extension. If you're already familiar with extensions, then you can learn more about the Create mode.

Anchor to Editing a selling plan groupEditing a selling plan group
You can call the sellingPlanGroupUpdate
mutation to edit the attributes for a selling plan group that has already been created. In the following example, the "Subscribe and save" selling plan group is renamed to "Pay per delivery":
POST https://{shop}.myshopify.com/admin/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Use a Product subscription app extension to make sure that the Edit function works as expected from the product or variant page in Shopify admin. If you aren't familiar with extensions, then refer to Getting started building a product subscription app extension. If you're already familiar with extensions, then you can learn more about the Edit purchase option mode.

Anchor to Step 2: Associate a selling plan group to a productStep 2: Associate a selling plan group to a product
Selling plans can be created with products or product variants that are already associated in the sellingPlanGroupCreate
call.
However, you can also use the sellingPlanGroupAddProducts
or sellingPlanGroupAddProductVariants
mutation to make a separate call to associate a selling plan group with a product or product variant, without having to delete and recreate the selling plan group.
If you have multiple selling plan groups to be associated with a product or product variant, then you can use the productJoinSellingPlanGroups
or productVariantJoinSellingPlanGroups
mutations.
In the following example, the selling plan group is associated with a product variant.
POST https://{shop}.myshopify.com/admin/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Use a Product subscription app extension to make sure that the Add existing plan function works from the product or variant page in Shopify admin. If you aren't familiar with extensions, then refer to Getting started building a product subscription app extension. If you're already familiar with extensions, then you can learn more about the Add mode.

Anchor to Removing a product or variant from a selling plan groupRemoving a product or variant from a selling plan group
If you want to disassociate a product from a selling plan group, then you can use the sellingPlanGroupRemoveProducts
mutation. To remove a product variant from a selling plan group, you can use the sellingPlanGroupRemoveProductVariants
mutation. In the following example, a product is removed from a selling plan group:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Use a Product subscription app extension to make sure the Remove function works as expected from the product or variant page in Shopify admin. If you aren't familiar with extensions, then refer to Getting started building a product subscription app extension. If you're already familiar with extensions, then you can learn more about the Remove mode.
The Remove function depends on whether the selling plan is associated with products or variants. If the selling plan is associated with products, then only the Product page shows the function. If the selling plan is associated with variants, then both the product and variant pages show the function.
Removing a product from a selling plan removes all variants associated with the product from the selling plan.

Anchor to Step 3 (Optional): Configure a product to be sold only as a subscriptionStep 3 (Optional): Configure a product to be sold only as a subscription
You can configure which products are sold on a subscription by specifying the requiresSellingPlan
field as true
in the productUpdate
mutation. In the following example, the product is configured to be sold only on subscription.
Selling plans are available only through the online store sales channel. Products that are marked as "subscription only" are unpublished from other sales channels.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Merchants can manually set a product or product variant as "subscription only" on the Product page. Changing whether a product is sold as subscription only or not doesn't change the state of the plan. The Sell product as a subscription only setting is visible when a plan is applied to the product or product variant.

Anchor to Collecting payment informationCollecting payment information
After you've created the selling plan group, customers can purchase a product on a subscription and add it to their cart. For more information on implementing storefront Liquid properties, refer to Showing selling plan groups and selling plans on a product page.
Customer payment methods allow merchants to initiate new charges, with or without the customer being present. After a checkout is complete, a customer payment method is associated with the customer.
When an order includes subscription products, the payment method is associated with the subscription contract. This allows subscription apps to know which payment method to use for recurring payments.

Anchor to Next stepsNext steps
- Learn how to use subscription contracts to create agreements between a customer and a merchant, and bill customers on a recurring basis.
- Learn how to manage orders and fulfillments for prepaid subscriptions.