Shopify combined listings let merchants present multiple independent products as a single product page, connected by a shared option like color or model. Available on Shopify Plus only. For using combined listing children as bundle components, see bundles.
Why Combined Listings
Regular Shopify products support up to 3 options and 2,000 variants — but all variants share a single set of images, descriptions, and URLs. When products are visually or functionally distinct (e.g., a shoe in three colors, each with its own lifestyle photos, SEO-optimized URL, and unique description), cramming them into one product’s variant matrix loses that richness.
Combined listings solve this by keeping each product independent — with its own images, URLs, descriptions, and variant options — while presenting them to the customer as a single unified listing. The customer sees one product page with a Color selector, but behind the scenes each color is a separate product with separate inventory, analytics, and fulfillment.
Use combined listings when:
- Products need distinct images, URLs, or descriptions per option value (e.g., per color)
- Products have different secondary options (e.g., one color comes in 3 sizes, another in 5)
- You want independent inventory and sales tracking per product rather than per variant
- The merchant already manages these as separate products and wants a unified storefront display
How It Works
A parent product exists solely for display — it cannot be purchased and does not track inventory. Each child product retains its own images, URLs, variants, and inventory. Customers see a single product page with options drawn from all children.
Example: three shoe colors with ten sizes each appear as one product page with a Color option (from the combined listing) and a Size option (from each child’s own variants).
Limits
| Constraint | Limit |
|---|---|
| Plan requirement | Plus |
| Sales channels | Online Store only (no POS, no third-party) |
| Child products per parent | 60 |
| Variants across all children | 2,000 |
| Options on parent | 3 |
| Nesting | Cannot be bundles or nested in other combined listings |
Sales attribution tracks child products, not the parent.
Admin API
Requires write_products access scope. The API uses the unstable version for
combined listing mutations.
Creating a Combined Listing
- Create the parent with
productSet, settingcombinedListingRoletoPARENT. - Associate children with
combinedListingUpdate, providing each child’s product ID and selected parent option values (name, value, optional metafield link).
Querying
Query products with filter "combined_listing_role:PARENT" and expand the
combinedListing field to access parentProduct and combinedListingChildren.
Each child node exposes parentVariant.selectedOptions — the option values that
identify the child within the combined listing.
Editing
All operations use combinedListingUpdate:
- Add children —
productsAddedargument - Remove children —
productsRemovedIdsargument - Edit option values —
productsEditedargument with updatedoptionsAndValues - Batch — combine add, edit, and remove in a single mutation
Hydrogen Storefront Implementation
Hydrogen’s combined listings recipe uses tag-based detection — not the
combinedListingRole API field. Tag a parent product (e.g., "combined") in
the Shopify admin, then detect it in code via product.tags.
(Source)
Configuration
A settings object in app/lib/combined-listings.ts controls behavior:
export const combinedListingsSettings = {
redirectToFirstVariant: false,
combinedListingTag: "combined",
hideCombinedListingsFromProductList: true
};UI Patterns
| Concern | Behavior for combined listings |
|---|---|
| Add to cart | Hidden — parent products are not purchasable |
| Price | Show range (From / To) from priceRange instead of variant price |
| Image | Show parent’s featuredImage instead of variant image |
| Option selection | Don’t mark options as selected; don’t set URL search params |
| Redirect | Optional: redirect parent handle to first child variant |
Filtering Parents from Product Lists
Parents should not appear alongside regular products in collections and search. The approach depends on the query context:
collections.all/ recommended products — add aqueryvariable to the GraphQL query:NOT tag:combinedcollections.$handle— query filter not supported on collection products; filter client-side after retrieval usingisCombinedListing(product)
All product queries need the tags field added to their fragments.
Files Touched
| File | Change |
|---|---|
app/lib/combined-listings.ts | New — settings + isCombinedListing + query filter helper |
app/components/ProductForm.tsx | Hide “Add to cart” for parents; don’t mark options selected |
app/components/ProductImage.tsx | Accept both variant and product image types |
app/components/ProductItem.tsx | Show price range for combined listings |
app/routes/products.$handle.tsx | Detect combined listing; price range; featured image; optional redirect |
app/routes/collections.all.tsx | Filter parents via query variable |
app/routes/collections.$handle.tsx | Filter parents client-side |
app/routes/_index.tsx | Filter parents from recommended products |
app/lib/redirect.ts | Add redirectIfCombinedListing utility |
app/styles/app.css | Price range flexbox layout |
Relationship to Bundles
Combined listing children are separate products. When they are used as bundle components, product-fixed bundles don’t work — they attach every child to every variant regardless of option selection. Use variant-fixed or customized bundles instead. See bundles for the full comparison and implementation guide.
See Also
- bundles — Bundle implementation guide with combined listings deep-dive
- Combined Listings Overview (shopify.dev)
- Build for Combined Listings (shopify.dev)
- Hydrogen Combined Listings Recipe (source)
- Hydrogen Combined Listings LLM Prompt (source)
- Shopify Combined Listings docs