Create and manage selling plans
Selling plans represent how products can be sold and purchased. This tutorial shows you how to create and manage selling plans in your app by illustrating two use cases: "Subscribe and save" and "Prepaid" subscriptions.
"Subscribe and save", also known as "pay per delivery", is a selling method where a customer pays for goods or services per delivery. "Prepaid" is a selling method where a customer makes a single payment upfront.
Requirements
- You've completed our Getting started with the GraphQL Admin and REST Admin APIs guide and you're authenticated with the API.
- You've created products and product variants in your development store.
- To be eligible to use Shopify subscriptions, merchants must meet the qualifying criteria.
Scopes
To use the GraphQL mutations, your app needs to request the following access scopes for a Shopify store:
write_products
: Allows an app to write products.read_customer_payment_methods
: Allows an app to read customer payment methods.read_own_subscription_contracts
: Allows an app to read subscription contract mutations for contracts they own.write_own_subscription_contracts
: Allows an app to write subscription contract mutations for contracts they own.
Selling plans
A selling plan group represents a selling method. Selling plans are organized into selling plan groups. Each selling plan group includes products or variants as well as a delivery, billing, and pricing policy.
View selling plans object descriptions
API object | Description |
---|---|
Selling plan group | Represents a selling method. For example, "Subscribe and save" or "Prepaid" subscriptions. |
Selling plan | Represents an alternative way to buy a product or variant. Selling plans are organized into a selling plan group. For example, individual selling plans might be named "Deliver weekly" or "Deliver monthly". |
Policies | Each selling plan is associated with the following policies:
|
Create a selling plan group
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).
Associate a selling plan group to a product variant
Selling plans can be created with products or product variants 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.
In the following example, the selling plan group is associated with a product variant.
Request
POST /admin/api/2021-01/graphql.json
mutation {
sellingPlanGroupAddProductVariants(
id: "gid://shopify/SellingPlanGroup/294969"
productVariantIds: ["gid://shopify/ProductVariant/31374109802518"]
) {
sellingPlanGroup {
id
productVariantCount
productVariants(first: 10) {
edges {
node {
id
title
inventoryQuantity
product {
id
title
totalInventory
}
}
}
}
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"sellingPlanGroupAddProductVariants": {
"sellingPlanGroup": {
"id": "gid://shopify/SellingPlanGroup/294969",
"productVariantCount": 1,
"productVariants": {
"edges": [
{
"node": {
"id": "gid://shopify/ProductVariant/31374109802518",
"title": "Type A",
"inventoryQuantity": 7,
"product": {
"id": "gid://shopify/Product/4352352387128",
"title": "The best coffee",
"totalInventory": 17
}
}
}
]
}
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 32,
"actualQueryCost": 14,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 986,
"restoreRate": 50.0
}
}
}
}
Associate multiple selling plan groups to a product or product variant
If you want multiple selling plan groups to be associated with a product or product variant, you can use the productJoinSellingPlanGroups
or productVariantJoinSellingPlanGroups
mutations.
In the following example, two selling plan groups are associated with a product:
POST /admin/api/2021-01/graphql.json
mutation {
productJoinSellingPlanGroups(
id: "gid://shopify/Product/4353554710550"
sellingPlanGroupIds: [
"gid://shopify/SellingPlanGroup/294968"
"gid://shopify/SellingPlanGroup/491542"
]
) {
product {
id
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"productJoinSellingPlanGroups": {
"product": {
"id": "gid://shopify/Product/4353554710550"
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
In the following example, two selling plan groups are associated with a product variant:
POST /admin/api/2021-01/graphql.json
mutation {
productVariantJoinSellingPlanGroups(
id: "gid://shopify/ProductVariant/31374835974166"
sellingPlanGroupIds: [
"gid://shopify/SellingPlanGroup/294968"
"gid://shopify/SellingPlanGroup/491542"
]
) {
productVariant {
id
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"productVariantJoinSellingPlanGroups": {
"productVariant": {
"id": "gid://shopify/ProductVariant/31374835974166"
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
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 only sold on subscription.
Request
POST /admin/api/2021-01/graphql.json
mutation {
productUpdate(
input: { id: "gid://shopify/Product/1", requiresSellingPlan: true }
) {
product {
id
requiresSellingPlan
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"productUpdate": {
"product": {
"id": "gid://shopify/Product/1",
"requiresSellingPlan": true
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
Edit a selling plan group
You can call the sellingPlanGroupUpdate
mutation to edit the attributes associated with a selling plan group. In the following example, the “Subscribe and save” selling plan group is renamed to “Pay per delivery”.
Request
POST /admin/api/2021-01/graphql.json
mutation {
sellingPlanGroupUpdate(
id: "gid://shopify/SellingPlanGroup/294969"
input: { name: "Pay per delivery" }
) {
sellingPlanGroup {
id
name
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"sellingPlanGroupUpdate": {
"sellingPlanGroup": {
"id": "gid://shopify/SellingPlanGroup/294969",
"name": "Pay per delivery"
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
Remove 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 this example, a product is removed from a selling plan group.
POST /admin/api/2021-01/graphql.json
mutation {
sellingPlanGroupRemoveProducts(
id: "gid://shopify/SellingPlanGroup/294968"
productIds: ["gid://shopify/Product/4353554710550"]
) {
userErrors {
field
message
}
removedProductIds
}
}
JSON response:
{
"data": {
"sellingPlanGroupRemoveProducts": {
"userErrors": [],
"removedProductIds": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 10,
"actualQueryCost": 10,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 990,
"restoreRate": 50.0
}
}
}
}
Collecting payment information
Once you have 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. Once 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.
Advanced delivery behaviors for subscriptions
If you need to define more advanced delivery behaviors for subscriptions, then you can use anchors. Anchors are useful in the following scenarios:
- A merchant starts fulfillment on a specific date every month
- A merchant wants to bill the 1st of every quarter
- A customer expects their delivery every Tuesday
Anchors define the date when fulfillment is completed by a merchant or when delivery occurs for the customer for a given time cycle. You can also define a cutoff for which customers are eligible to enter this cycle and the desired behavior for customers who start their subscription inside the cutoff period.
To learn more about anchors, refer to the SellingPlanRecurringDeliveryPolicy reference topic. To learn how to manage orders and fulfillments associated with prepaid subscriptions, refer to Manage orders for prepaid subscriptions.
View examples of intended results and anchor values
Intended result | Values |
---|---|
Buy on anchor date, no cutoff (asap) |
|
Buy on anchor date, no cutoff (next) |
|
Buy before anchor date, no cutoff (asap) |
|
Buy before anchor date, no cutoff (next) |
|
Buy after anchor date, no cutoff (asap) |
|
Buy after anchor date, no cutoff (next) |
|
Buy inside cutoff date, no cutoff (asap) |
|
Buy inside cutoff date, no cutoff (next) |
|
Buy before cutoff date, no cutoff (asap) |
|
Buy before cutoff date, no cutoff (next) |
|
Example call
The following example illustrates the use of anchors
in an API call. In the example, the fulfillment and billing dates are defined as the 15th of each month.
POST /admin/api/2021-01/graphql.json
mutation {
sellingPlanGroupCreate(
input: {
name: "Every month delivery"
options: ["Delivery Every"]
sellingPlansToCreate: {
name: "15th of the month"
options: ["15"]
deliveryPolicy: {
recurring: {
anchors: { day: 15, type: MONTHDAY }
preAnchorBehavior: ASAP
intent: FULFILLMENT_BEGIN
interval: MONTH
intervalCount: 1
}
}
pricingPolicies: {
fixed: { adjustmentType: PERCENTAGE, adjustmentValue: { percentage: 10 } }
}
billingPolicy: {
recurring: {
interval: MONTH
intervalCount: 1
anchors: { day: 15, type: MONTHDAY }
}
}
}
}
resources: { productVariantIds: ["gid://shopify/ProductVariant/1"] }
) {
sellingPlanGroup {
name
sellingPlans(first: 10) {
edges {
node {
name
options
}
}
}
}
userErrors {
code
field
message
}
}
}
JSON response:
{
"data": {
"sellingPlanGroupCreate": {
"sellingPlanGroup": {
"name": "Every month delivery",
"sellingPlans": {
"edges": [
{
"node": {
"name": "15th of the month",
"options": [
"15"
]
}
}
]
}
},
"userErrors": []
}
},
"extensions": {
"cost": {
"requestedQueryCost": 22,
"actualQueryCost": 13,
"throttleStatus": {
"maximumAvailable": 1000.0,
"currentlyAvailable": 987,
"restoreRate": 50.0
}
}
}
}
Next steps
- Create and manage subscription contracts: Follow a step-by-step workflow to create and manage subscription contracts, and get familiar with how billing and webhooks for subscriptions work.
- Create and manage discounts on subscriptions: Learn how to apply different types of discounts on subscriptions, including percentage, fixed amount, and free shipping discounts.
- Create and manage subscription shipping rates and delivery methods: Learn how to update delivery methods on subscriptions and understand the shipping rates customers see during checkout.