Skip to main content

Add a product fixed bundle

A product fixed bundle is a bundle that's configured at the product level. This guide shows you how to add a product fixed bundle using the productBundleCreate mutation.


In this tutorial, you'll learn how to do the following tasks:

  • Use the GraphQL Admin API to create a bundle
  • Poll the status of the bundle creation job
  • Use the GraphQL Admin API to update a bundle


A product fixed bundle is modeled as a product and is associated with other products using the bundleComponents relationship. This relationship is dictated by which options are chosen, for each component, when creating the bundle.

The bundle parent variant's price determines the price, while the inventory of each component's variants determines the bundle inventory. This is the same for variant fixed bundles.

A product has a bundleComponents field that determines the bundles' components.

A diagram showing the relationship between products that model a product fixed bundle

The next diagram shows an example of a product ("The Hair and Skin Bundle") that models a bundle and contains the following components: "Natural Shampoo 50 ml" and "Coconut Conditioner". The bundle is modeled by selecting which option values should be considered for each component.

A diagram showing an example of relationships between products that model a product fixed bundle

The next diagram shows an example of a product ("Hair and Soap Bundle") that models a bundle containing the following components: "Natural Shampoo", "Coconut Conditioner", "Hand Soap", and "Body Wash". The scent option names and values are the same for each component so they can be combined. When customers visit the storefront, combined options show up as one selector.

A diagram showing combined bundle options in a product fixed bundle

Anchor to Limitations and considerationsLimitations and considerations

  • A bundle can have up to 30 components.
  • Bundles can have up to three options. Combined options are considered one option.
  • You can't combine quantity options.
  • After an app has assigned components to a bundle, only that app can manage the components of the bundle.
  • Nested bundles aren't supported. A bundle can't have components and be part of another bundle simultaneously.

Anchor to Step 1: Create a bundleStep 1: Create a bundle

To create a product fixed bundle, you can run the productBundleCreate mutation.

The following example creates a bundle product ("The Hair and Skin Bundle") with two products as components (Shampoo and Soap). The mutation will return a productBundleOperation that you can use later to poll for the operation status. This example uses unique option names for each component ("Shampoo scent" and "Soap scent"). When using consolidatedOptions (shown in Step 4), you can use the same name for multiple components (for example, all "Scent"), and the API will consolidate them into a single bundle option based on the consolidatedOptions mapping.

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

mutation ProductBundleCreate($input: ProductBundleCreateInput!) {
productBundleCreate(input: $input) {
productBundleOperation {
id
status
}
userErrors {
message
field
}
}
}

Variables

{
"input":{
"title": "The hair and skin bundle",
"components": [
{
"quantity": 1,
"productId": "gid://shopify/Product/1",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/1",
"name": "Shampoo scent",
"values": ["Lavender", "Mint"]
}
]
},
{
"quantity": 1,
"productId": "gid://shopify/Product/2",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/2",
"name": "Soap scent",
"values": ["Rose", "Lemon"]
}
]
}
]
}
}

JSON response

{
"data": {
"productBundleCreate": {
"productBundleOperation": {
"id": "gid://shopify/ProductBundleOperation/1",
"status": "CREATED"
},
"userErrors": []
}
}
}

Anchor to Step 2: Poll the status of the bundle creation jobStep 2: Poll the status of the bundle creation job

After running the productBundleCreate mutation, you need to poll the status of the resulting product operation to know when the bundle is created.

The following example polls the status of the bundle creation job.

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

query productBundleOperation($id: ID!) {
productOperation(id: $id) {
... on ProductBundleOperation {
id
status
product {
id
}
userErrors {
field
message
code
}
}
}
}

Variables

{
"id": "gid://shopify/ProductBundleOperation/1"
}

JSON response

{
"productOperation": {
"id": "gid://shopify/ProductBundleOperation/1",
"status": "COMPLETE",
"product": {
"id": "gid://shopify/Product/3"
},
"userErrors": []
}
}

Anchor to Step 3: Update the bundleStep 3: Update the bundle

To update a bundle, you can run the productBundleUpdate mutation. The following example updates the bundle created previously by removing the soap component and adding a sponge component.

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

mutation ProductBundleUpdate($input: ProductBundleUpdateInput!) {
productBundleUpdate(input: $input) {
productBundleOperation {
id
status
}
userErrors {
message
field
}
}
}

Variables

{
"input": {
"productId": "gid://shopify/Product/3",
"title": "The hair and skin bundle",
"components": [
{
"quantity": 1,
"productId": "gid://shopify/Product/1",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/1",
"name": "Shampoo scent",
"values": ["Lavender", "Mint"]
}
]
},
{
"quantity": 1,
"productId": "gid://shopify/Product/4",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/5",
"name": "Sponge color",
"values": ["Blue", "Red"]
}
]
}
]
}
}

JSON response

{
"data": {
"productBundleUpdate": {
"productBundleOperation": {
"id": "gid://shopify/ProductBundleOperation/2",
"status": "CREATED"
},
"userErrors": []
}
}
}

You can poll the status of the bundle update operation in the same way as you did for the bundle creation operation.


Anchor to Step 4: Combine bundle optionsStep 4: Combine bundle options

You can consolidate multiple component options into a single bundle option by using the consolidatedOptions field when creating or updating a bundle. This allows buyers to select one option value (for example, "Lavender") that applies to multiple options.

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json

GraphQL query

mutation ProductBundleUpdate($input: ProductBundleUpdateInput!) {
productBundleUpdate(input: $input) {
productBundleOperation {
id
status
}
userErrors {
message
field
}
}
}

Variables

{
"input": {
"productId": "gid://shopify/Product/3",
"title": "The hair and skin bundle",
"components": [
{
"quantity": 1,
"productId": "gid://shopify/Product/1",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/1",
"name": "Scent",
"values": ["Lavender", "Mint"]
},
{
"componentOptionId": "gid://shopify/ProductOption/3",
"name": "Size",
"values": ["10oz", "12oz"]
}
]
},
{
"quantity": 1,
"productId": "gid://shopify/Product/5",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/6",
"name": "Scent",
"values": ["Lavender", "Mint"]
}
]
},
{
"quantity": 1,
"productId": "gid://shopify/Product/2",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/2",
"name": "Scent",
"values": ["Lavender", "Mint"]
}
]
},
{
"quantity": 1,
"productId": "gid://shopify/Product/6",
"optionSelections": [
{
"componentOptionId": "gid://shopify/ProductOption/7",
"name": "Scent",
"values": ["Lavender", "Mint"]
}
]
}
],
"consolidatedOptions": [
{
"optionName": "Scent",
"optionSelections": [
{
"optionValue": "Lavender",
"components": [
{
"componentOptionId": "gid://shopify/ProductOption/1",
"componentOptionValue": "Lavender"
},
{
"componentOptionId": "gid://shopify/ProductOption/6",
"componentOptionValue": "Lavender"
},
{
"componentOptionId": "gid://shopify/ProductOption/2",
"componentOptionValue": "Lavender"
},
{
"componentOptionId": "gid://shopify/ProductOption/7",
"componentOptionValue": "Lavender"
}
]
},
{
"optionValue": "Mint",
"components": [
{
"componentOptionId": "gid://shopify/ProductOption/1",
"componentOptionValue": "Mint"
},
{
"componentOptionId": "gid://shopify/ProductOption/6",
"componentOptionValue": "Mint"
},
{
"componentOptionId": "gid://shopify/ProductOption/2",
"componentOptionValue": "Mint"
},
{
"componentOptionId": "gid://shopify/ProductOption/7",
"componentOptionValue": "Mint"
}
]
}
]
}
]
}
}

JSON response

{
"data": {
"productBundleUpdate": {
"productBundleOperation": {
"id": "gid://shopify/ProductBundleOperation/3",
"status": "CREATED"
},
"userErrors": []
}
}
}
Note

After you run the mutation, remember to poll the status of the operation (just like you did in Step 2) to confirm the bundle update is complete.



Was this page helpful?