Group products into a combined listing

Show separate color products as one listing: create a parent product, then attach the children and their option values with combinedListingUpdate.

API
Admin GraphQL API
Operations
productCreate, combinedListingUpdate
Access scope
write_products
Plan
Shopify Plus
API version
2026-10
Last checked

In short

To build a combined listing, create a parent product with combinedListingRole PARENT using productCreate, then call combinedListingUpdate with the parent’s ID, the option and values it shows (optionsAndValues) and each child product with the parent option value it stands for (productsAdded). Combined listings are available only to stores on Shopify Plus.

How to use it

  1. Create the child products first, one per color, each with its own images, handle and variants.
  2. Send CreateListingParent with combinedListingRole PARENT. The parent has no stock and can’t be bought itself.
  3. Send AddColorsToListing with the parent ID, the parent option (Color with its values) and each child mapped to one value.
  4. Later, use productsEdited to remap a child, productsRemovedIds to take one out, and optionsAndValues to change the parent options.

Code

product-create-parent.graphql
mutation CreateListingParent($product: ProductCreateInput!) {
  productCreate(product: $product) {
    product {
      id
      combinedListingRole
    }
    userErrors {
      field
      message
    }
  }
}
product-create-parent.variables.json
{
  "product": {
    "title": "Linen shirt",
    "handle": "linen-shirt-all-colors",
    "status": "ACTIVE",
    "combinedListingRole": "PARENT"
  }
}
product-create-parent.response.json
{
  "data": {
    "productCreate": {
      "product": {
        "id": "gid://shopify/Product/1234567890",
        "combinedListingRole": "PARENT"
      },
      "userErrors": []
    }
  }
}
combined-listing-update.graphql
mutation AddColorsToListing(
  $parentProductId: ID!
  $productsAdded: [ChildProductRelationInput!]
  $optionsAndValues: [OptionAndValueInput!]
) {
  combinedListingUpdate(
    parentProductId: $parentProductId
    productsAdded: $productsAdded
    optionsAndValues: $optionsAndValues
  ) {
    product {
      id
      combinedListingRole
      combinedListing {
        combinedListingChildren(first: 10) {
          nodes {
            product {
              id
              title
            }
            parentVariant {
              id
              selectedOptions {
                name
                value
              }
            }
          }
        }
      }
    }
    userErrors {
      code
      field
      message
    }
  }
}
combined-listing-update.variables.json
{
  "parentProductId": "gid://shopify/Product/1234567890",
  "optionsAndValues": [
    {"name": "Color", "values": ["Sand", "Navy"]}
  ],
  "productsAdded": [
    {
      "childProductId": "gid://shopify/Product/1111111111",
      "selectedParentOptionValues": [{"name": "Color", "value": "Sand"}]
    },
    {
      "childProductId": "gid://shopify/Product/1111111112",
      "selectedParentOptionValues": [{"name": "Color", "value": "Navy"}]
    }
  ]
}
combined-listing-update.response.json
{
  "data": {
    "combinedListingUpdate": {
      "product": {
        "id": "gid://shopify/Product/1234567890",
        "combinedListingRole": "PARENT",
        "combinedListing": {
          "combinedListingChildren": {
            "nodes": [
              {
                "product": {"id": "gid://shopify/Product/1111111111", "title": "Linen shirt - Sand"},
                "parentVariant": {"id": "gid://shopify/ProductVariant/2222222221", "selectedOptions": [{"name": "Color", "value": "Sand"}]}
              },
              {
                "product": {"id": "gid://shopify/Product/1111111112", "title": "Linen shirt - Navy"},
                "parentVariant": {"id": "gid://shopify/ProductVariant/2222222222", "selectedOptions": [{"name": "Color", "value": "Navy"}]}
              }
            ]
          }
        }
      },
      "userErrors": []
    }
  }
}

Written by Lintel. MIT license: free to use in your own store and in client work.

Limits and edge cases

  • A parent can have up to 60 child products and up to 2000 variants across them.
  • Sales are tracked on the child products; checkout and orders show the child, not the parent.
  • A combined listing can’t be a bundle, and it can’t be part of another combined listing.
  • The storefront shows it as one product only when the theme supports combined listings.

Questions

What are Shopify combined listings?
Several products, usually one per color, shown on the storefront as one product with a shared option picker. Each child keeps its own URL, images and stock.
Do combined listings need Shopify Plus?
Yes. Only stores on a Shopify Plus plan can use combined listings.
Can I create the parent with productSet?
Shopify’s reference creates the parent with productCreate and combinedListingRole PARENT, which is the path shown here.
  • Validated against the Admin or Storefront API schema for version 2026-10 on the date shown. Check the version in your request URL.
  • IDs and store addresses in the examples are placeholders. Replace them with your own.
  • Admin API calls need an access token from your app. Never put an Admin API token in a storefront or theme.
  • MIT license. Use the code in your own store or in client work.

Need this built, tested and maintained for your store? See API integrations.

Have something to build? Let’s talk it through.

Taking a limited number of projects at a time. Every brief is read by an engineer, not a salesperson.

Gencer KarakayaShopify Engineer

An engineer reads your brief, and we reply by email.