Skip to main content

Build for combined listings

Plus

Combined listings are available only to stores on a Shopify Plus plan.

This guide shows you how to create, query, and edit combined listings using the GraphQL Admin API's productCreate mutation.


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

  • Use the GraphQL Admin API to create a parent product

  • Add child products to the combined listing

  • Query all combined listings

  • Add a child product to an existing combined listing

  • Remove a child product from an existing combined listing

  • Change the option value of a child product in an existing combined listing

  • Combine adding, editing, and removing child products into one mutation

    We're going to do that by creating a combined listing for a pair of shorts that come in four different colors. The combined listing will have a parent product that represents the shorts and four child products that represent each of the colors.



A combined listing is modeled on a single parent product that has variants that point to one or more child products using the CombinedListingRole type and the combinedListingUpdate mutation.

The relationship between combined listings and their children products

Anchor to Step 1: Create a parent productStep 1: Create a parent product

Creating a combined listing starts with creating a parent product. You'll use the productCreate mutation to create that combined listing.

Note

You should already have created the child products that you want to combine before you create the parent product.

For the shorts, you'll create a new product called "Shorts" with a combinedListingRole of PARENT. This creates the parent product, but does not yet associate the child products. You'll associate child products in a subsequent step.

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

GraphQL mutation

mutation createCombinedListingParent($input: ProductInput!) {
productCreate(input: $input) {
product {
id
title
combinedListingRole
status
}
userErrors {
field
message
}
}
}

Variables

{
"input": {
"title": "Shorts",
"status": "ACTIVE",
"combinedListingRole": "PARENT"
}
}

JSON response

{
"data": {
"productCreate": {
"product": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"combinedListingRole": "PARENT",
"status": "ACTIVE"
},
"userErrors": []
}
}
}

Anchor to Step 2: Add child products to the combined listingStep 2: Add child products to the combined listing

With the combined listing created, you'll add the child products to the combined listing using the combinedListingUpdate mutation.

For the child products you already have, you'll need to get their IDs to add them to the parent product that you created.

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

GraphQL mutation

mutation addChildProductsToCombinedListing(
$parentProductId: ID!,
$productsAdded: [ChildProductRelationInput!],
$optionsAndValues: [OptionAndValueInput!]
) {
combinedListingUpdate(
parentProductId: $parentProductId,
productsAdded: $productsAdded,
optionsAndValues: $optionsAndValues
) {
product {
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25) {
nodes {
product {
id
title
}
parentVariant {
id
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
userErrors {
code
field
message
}
}
}

Variables

{
"parentProductId": "gid://shopify/Product/1800",
"productsAdded": [
{
"childProductId": "gid://shopify/Product/1796",
"selectedParentOptionValues": {
"name": "Color",
"value": "Blue",
"linkedMetafieldValue": "gid://shopify/Metaobject/1"
}
},
{
"childProductId": "gid://shopify/Product/1797",
"selectedParentOptionValues": {
"name": "Color",
"value": "Black",
"linkedMetafieldValue": "gid://shopify/Metaobject/2"
}
},
{
"childProductId": "gid://shopify/Product/1798",
"selectedParentOptionValues": {
"name": "Color",
"value": "Maroon",
"linkedMetafieldValue": "gid://shopify/Metaobject/3"
}
},
{
"childProductId": "gid://shopify/Product/1799",
"selectedParentOptionValues": {
"name": "Color",
"value": "Orange",
"linkedMetafieldValue": "gid://shopify/Metaobject/4"
}
}
],
"optionsAndValues": [
{
"name": "Color",
"values": [
"Blue",
"Black",
"Orange",
"Maroon"
]
}
]
}

JSON response

{
"data": {
"combinedListingUpdate": {
"product": {
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1",
"title": "Shorts",
"status": "ACTIVE"
},
"combinedListingChildren": {
"nodes": [
{
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue",
"featuredImage": null
},
"parentVariant": {
"id": "gid://shopify/ProductVariant/2",
"selectedOptions": [
{
"name": "Color",
"value": "Blue",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black",
"featuredImage": null
},
"parentVariant": {
"id": "gid://shopify/ProductVariant/3",
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2"
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon",
"featuredImage": null
},
"parentVariant": {
"id": "gid://shopify/ProductVariant/2",
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1799",
"title": "Shorts - Orange",
"featuredImage": null
},
"parentVariant": {
"id": "gid://shopify/ProductVariant/4",
"selectedOptions": [
{
"name": "Color",
"value": "Orange",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/4",
},
}
]
}
}
]
}
}
}
}
}
}

Anchor to Step 3: Query all combined listingsStep 3: Query all combined listings

After creating a combined listings, you can use the products query to retrieve only combined listing parents and their children. With this, you can pull just the Shorts parent product and its children.

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

GraphQL query

query combinedListingIndex($query: String) {
products(first: 25, query: $query) {
nodes {
id
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25){
totalCount
edges {
node {
product {
id
title
status
}
parentVariant {
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
}
}
}

Variables

{
"query": "combined_listing_role:PARENT"
}

JSON response

{
"data": {
"products": {
"nodes": [
{
"id": "gid://shopify/Product/1800",
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"status": "ACTIVE",
},
"combinedListingChildren": {
"totalCount": "4",
"edges": [
{
"node": {
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue",
"status": "ACTIVE",
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Blue",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
},
}
]
}
}
},
{
"node": {
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black",
"status": "ACTIVE",
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2",
},
}
]
}
}
},
{
"node": {
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon",
"status": "ACTIVE",
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
}
},
{
"node": {
"product": {
"id": "gid://shopify/Product/1799",
"title": "Shorts - Orange",
"status": "ACTIVE",
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Orange",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
}
}
]
}
}
}
]
}
}
}

Anchor to Step 4: Add a child product to an existing combined listingStep 4: Add a child product to an existing combined listing

Your team has come up with a new color of Shorts and you want to add it to the combined listing so your customers can easily buy it. You can do that by using the same mutation you used to add child products earlier and add the new child product to the productsAdded field for the combinedListingUpdate mutation.

By default, new colors are added to the end of the parent product's option values. Alternatively, you can supply optionsAndValues to change the order of both options and option values. We'll do that here to put your new pink shorts at the front of the color option.

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

GraphQL mutation

mutation addNewChildProductsToCombinedListing(
$parentProductId: ID!,
$productsAdded: [ChildProductRelationInput!],
$optionsAndValues: [OptionAndValueInput!]
) {
combinedListingUpdate(
parentProductId: $parentProductId,
productsAdded: $productsAdded,
optionsAndValues: $optionsAndValues
) {
product {
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25) {
nodes {
product {
id
title
}
parentVariant {
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
userErrors {
code
field
message
}
}
}

Variables

{
"parentProductId": "gid://shopify/Product/1800",
"productsAdded": [
{
"childProductId": "gid://shopify/Product/1805",
"selectedParentOptionValues": {
"name": "Color",
"value": "Pink",
"linkedMetafieldValue": "gid://shopify/Metaobject/5",
}
}
],
"optionsAndValues": [
{
"name": "Color",
"values": ["Pink", "Blue", "Black", "Maroon", "Orange"],
"optionId": "gid://shopify/ProductOption/1",
"linkedMetafield": {
"namespace": "shopify",
"key": "color-pattern",
"values": [
"gid://shopify/Metaobject/5",
"gid://shopify/Metaobject/1",
"gid://shopify/Metaobject/2",
"gid://shopify/Metaobject/3",
"gid://shopify/Metaobject/4"
],
}
}
]
}

JSON response

{
"data": {
"combinedListingUpdate": {
"product": {
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"status": "ACTIVE"
},
"combinedListingChildren": {
"nodes": [
{
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Blue",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1799",
"title": "Shorts - Orange"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Orange",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/4",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1806",
"title": "Shorts - Pink"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Pink",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/5",
},
}
]
}
}
]
}
}
},
"userErrors": []
}
}
}

Anchor to Step 5: Remove a child product from an existing combined listingStep 5: Remove a child product from an existing combined listing

Later, you decide to stop selling the orange shorts. You can remove the orange shorts by using the productsRemovedIds argument for the combinedListingUpdate mutation.

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

GraphQL mutation

mutation deleteChildProductOnCombinedListing(
$parentProductId: ID!,
$productsRemovedIds: [ID!]
) {
combinedListingUpdate(parentProductId: $parentProductId, productsRemovedIds: $productsRemovedIds) {
product {
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25) {
nodes {
product {
id
title
}
parentVariant {
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
userErrors {
code
field
message
}
}
}

Variables

{
"parentProductId": "gid://shopify/Product/1800",
"productsRemovedIds": [
"gid://shopify/Product/1799"
]
}

JSON response

{
"data": {
"combinedListingUpdate": {
"product": {
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"status": "ACTIVE"
},
"combinedListingChildren": {
"nodes": [
{
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Blue",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1806",
"title": "Shorts - Pink"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Pink",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/5",
},
}
]
}
}
]
}
}
},
"userErrors": []
}
}
}

Anchor to Step 6: Change the option value of a child product in an existing combined listingStep 6: Change the option value of a child product in an existing combined listing

As part of a larger change the team decides to change the option value "Blue" to "Navy", this isn't a new product, but just a name change. In that case, we want to modify the name of the color option value while using the same product. You'll need to update the name of the child product separately, but you'll also want to modify the color option value on the parent product. You can do that by using the productsEdited argument on the combinedListingUpdate mutation.

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

GraphQL mutation

mutation editChildProductOnCombinedListing(
$parentProductId: ID!,
$productsEdited: [ChildProductRelationInput!],
$optionsAndValues: [OptionAndValueInput!]
) {
combinedListingUpdate(parentProductId: $parentProductId, productsEdited: $productsEdited, optionsAndValues: $optionsAndValues) {
product {
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25) {
nodes {
product {
id
title
}
parentVariant {
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
userErrors {
code
field
message
}
}
}

Variables

{
"parentProductId": "gid://shopify/Product/1800",
"productsEdited": [
{
"childProductId": "gid://shopify/Product/1796",
"selectedParentOptionValues": [
{
"name": "Color",
"value": "Blue"
}
]
}
],
"optionsAndValues": [
{
"name": "Color",
"values": ["Orange", "Blue", "Black", "Maroon"],
"optionId": "gid://shopify/ProductOption/28"
}
]
}

JSON response

{
"data": {
"combinedListingUpdate": {
"product": {
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"status": "ACTIVE"
},
"combinedListingChildren": {
"nodes": [
{
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Blue",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1"
}
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1799",
"title": "Shorts - Orange"
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Orange",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/4",
},
}
]
}
}
]
}
}
},
"userErrors": []
}
}
}

Anchor to Step 7: Combine adding, editing, and removing child products into one mutationStep 7: Combine adding, editing, and removing child products into one mutation

You can combine adding child products, changing options and option values on existing child products, and removing child products into a single mutation. With a single mutation you save time compared to sending multiple mutations.

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

GraphQL mutation

mutation updateCombinedListing(
$parentProductId: ID!,
$productsAdded: [ChildProductRelationInput!],
$productsEdited: [ChildProductRelationInput!],
$productsRemovedIds: [ID!],
$optionsAndValues: [OptionAndValueInput!],
) {
combinedListingUpdate(
parentProductId: $parentProductId,
productsAdded: $productsAdded,
productsEdited: $productsEdited,
productsRemovedIds: $productsRemovedIds,
optionsAndValues: $optionsAndValues
) {
product {
combinedListingRole
combinedListing {
parentProduct {
id
title
status
}
combinedListingChildren(first: 25) {
nodes {
product {
id
title
featuredImage {
url
altText
}
}
parentVariant {
selectedOptions {
name
value
optionValue {
linkedMetafieldValue
}
}
}
}
}
}
}
}
}

Variables

{
"parentProductId": "gid://shopify/Product/1800",
"productsAdded": [
{
"childProductId": "gid://shopify/Product/1806",
"selectedParentOptionValues": {
"name": "Color",
"value": "Pink",
"linkedMetafieldValue": "gid://shopify/Metaobject/5",
}
}
],
"productsRemovedIds": [
"gid://shopify/Product/1799"
],
"productsEdited": [
{
"childProductId": "gid://shopify/Product/1796",
"selectedParentOptionValues": [
{
"name": "Color",
"value": "Navy",
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
}
]
}
],
"optionsAndValues": [
{
"name": "Color",
"values": ["Pink", "Blue", "Black", "Maroon", "Orange"],
"optionId": "gid://shopify/ProductOption/1",
"linkedMetafield": {
"namespace": "shopify",
"key": "color-pattern",
"values": [
"gid://shopify/Metaobject/5",
"gid://shopify/Metaobject/1",
"gid://shopify/Metaobject/2",
"gid://shopify/Metaobject/3",
"gid://shopify/Metaobject/4"
],
}
}
]
}

JSON response

{
"data": {
"combinedListingUpdate": {
"product": {
"combinedListingRole": "PARENT",
"combinedListing": {
"parentProduct": {
"id": "gid://shopify/Product/1800",
"title": "Shorts",
"status": "ACTIVE"
},
"combinedListingChildren": {
"nodes": [
{
"product": {
"id": "gid://shopify/Product/1796",
"title": "Shorts - Blue",
"featuredImage": null
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Navy",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/1",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1797",
"title": "Shorts - Black",
"featuredImage": null
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Black",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/2",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1798",
"title": "Shorts - Maroon",
"featuredImage": null
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Maroon",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/3",
},
}
]
}
},
{
"product": {
"id": "gid://shopify/Product/1806",
"title": "Shorts - Pink",
"featuredImage": null
},
"parentVariant": {
"selectedOptions": [
{
"name": "Color",
"value": "Pink",
"optionValue": {
"linkedMetafieldValue": "gid://shopify/Metaobject/5",
},
}
]
}
}
]
}
}
}
}
}
}


Was this page helpful?