Shopify’s Bundles API lets merchants group multiple products or variants into a single sellable unit. There are two bundle architectures — Fixed and Customized — each with different limits, mutations, and storefront behavior. For rendering bundles on a Hydrogen storefront, see hydrogen-bundles.
Fixed Bundles
Basic use cases including standard bundles and multi-packs, operating within Shopify’s variant limits.
- Limits: 30 components max, 3 options max
- Oversell protection: Shopify maintains parent variant inventory (minimum of component quantities) — always enforced
- Pricing: derived from parent variant, allocated to components via weighted algorithm in checkout/cart/orders
- Taxes: computed on components, not the parent
- Storefront: works without Liquid changes; sellable qty available via Liquid
Product Fixed Bundles
Configured at the product level using products and option values. The API automatically maps all underlying variants of the bundle parent product to the component products. Structure: Product → Product component (quantity, parent product, component product, selected options).
- Create:
productBundleCreatemutation — input:title,components(array ofquantity,productId,optionSelections). Returns aproductBundleOperationID for async polling. - Update:
productBundleUpdatemutation — same structure for add/remove. - Poll: query
productOperation(id)with... on ProductBundleOperation; statuses:CREATED→COMPLETE. - Access scope:
write_products - Relationship model:
bundleComponentsfield on bundle product; components connected viaproductIdwithoptionSelectionsfor variant mapping. - Combined options: when components share identical option names/values,
they consolidate into a single storefront selector via
consolidatedOptionsmapping. Counts as one option toward the 3-option limit. - App-exclusive: once an app assigns components, only that app can manage them.
- No nesting: a bundle can’t have components and be part of another bundle.
- Supports bundle publishing
- Docs: Add Product Fixed Bundle
Example — Hair and Skin Bundle:
| Option | Values |
|---|---|
| Scent | Shampoo, Conditioner |
| Shampoo Size | 50ml, 100ml |
Components: 1x Natural Shampoo (50ml or 100ml), 1x Coconut Conditioner.
Variant Fixed Bundles
Configured at the variant level, ideal for multi-packs. Structure: Product → Product variant → Product variant component (quantity, parent variant, child variant).
- Two-step process: first
productCreate, thenproductVariantRelationshipBulkUpdateto associate components. - Mutation input:
parentProductVariantId(the bundle variant) +productVariantRelationshipsToCreate(array of component variant IDs and quantities). SupportsproductVariantRelationshipsToRemovefor deletion. - Access scope:
write_products - Relationship model:
productVariantComponentsfield on the variant (vsbundleComponentsfor product fixed bundles). Components connected via variant IDs, not product IDs. - Detection:
productVariant.requiresComponentsreturnstruewhen components are associated — same field used in Storefront API for hydrogen-bundles rendering. - Docs: Add Variant Fixed Bundle
Example — Hair and Skin Bundle:
| Variant | Components |
|---|---|
| Variant 1 | 2x Natural Shampoo 50ml, 1x Conditioner |
| Variant 2 | 1x Natural Shampoo 100ml, 1x Conditioner |
Customized Bundles
Complex use cases like mix-and-match, where customers choose their own components.
- Limits: 150 components max, 3 options max
- Oversell protection: app-maintained on storefront; built-in post-add-to-cart component checking
- Pricing: Expand mode: parent-derived; Merge mode: component-derived with price adjustment in function; weighted allocation
- Taxes: computed on components
- Storefront: multiple component variants; app-managed picker; sellable qty via Storefront API only
- Cart Transform Function:
cart_transformShopify Function (API 2025-07+). Two operations: Expand (bundle line → component lines) and Merge (linesMerge— when all components are in cart, combine into parent variant). - Activation:
cartTransformCreatemutation with the function handle. - Access scopes:
write_cart_transforms+write_products - Implementation: Rust or JS/TS via Shopify CLI
(
shopify app generate extension --template cart_transform). - Docs: Add Customized Bundle Function
- Tutorial: Create Bundle App
Data Sources
| Approach | Security | Use Case | Notes |
|---|---|---|---|
| Metafields | Secure (server) | Merchant-defined | Recommended; requires metafield definitions |
| Line properties | Browser-editable | Mix-and-match | Requires validation in function |
Metafields
Defined under Settings > Custom data > Variants. All variant references use GID
format (gid://shopify/ProductVariant/<id>).
| Metafield | Type | Purpose |
|---|---|---|
component_reference | Product Variant — List | Product variant IDs included in the bundle |
component_quantities | Integer — List (min 1) | Quantity per component (order matches refs) |
component_parents | JSON | Reverse-lookup: parent bundles a child belongs to |
The component_parents JSON stores an array of parent definitions, each with
id (parent variant GID), component_reference.value (array of child GIDs),
and component_quantities.value (array of quantities). This enables the Merge
operation to identify when all components of a bundle are present in the cart.
Shared Behavior (Both Types)
- Discounts: calculated on the parent, allocated to components
- Cart display: grouped in cart/checkout; queryable via
cart.line.components - Bundle grouping: by parent variant ID
- Order storage: components with parent reference via groupings
- Fulfillment: no constraint — components can be fulfilled independently
- Refunds/returns: component-level operations
- Reporting: component-level sales reporting
Store Eligibility
Use the BundlesFeature GraphQL object to verify whether a store is eligible
for bundles. Ineligible stores cannot publish bundles to sales channels.
Bundle Lifecycle
| Phase | App Role | Shopify Role |
|---|---|---|
| Admin | Merchant creates product; app configures bundles per variant; UI ext summarizes | N/A |
| Storefront | Customized bundles use theme app blocks; fixed bundles work automatically | N/A |
| Checkout | N/A | Groups bundle products as line collections |
| Orders | Fulfillment apps access bundle data | Order lines return components with parent ref |
Build Surfaces
- Checkout — Shopify Functions group products into bundles in the cart and at checkout.
- Admin — Product configuration extensions for merchant bundle setup.
- Online Store — Theme app blocks for customer bundle selection on product pages.
Sales Channel Support
Bundles work natively on Online Store, Shop, and Shopify POS. Custom storefronts require bundle publishing to be enabled (disabled by default). Publishing is only supported for product fixed bundles — variant fixed bundles cannot be published to custom storefronts. Enablement requires the app to be a sales channel; for third-party apps, activate via Partner Dashboard (App setup → “Sell Bundles”).
Limitations
- Selling plans — bundles cannot be combined with subscriptions, pre-orders, or try-before-you-buy.
- Shopify Scripts — line item Scripts don’t apply to bundle line items; operations are discarded. Scripts sunset June 30, 2026 — migrate to Shopify Functions.
- No nesting — a bundle can’t be a component of another bundle.
- App-exclusive management — once an app assigns components, only that app can modify them.
- Quantity options — cannot be combined across components.
- Custom storefront publishing — only product fixed bundles; variant fixed bundles cannot be published.
Admin UI
Product Configuration Extension
A ui_extension that displays bundle component summaries on product and variant
pages. Two targets required:
admin.product-details.configuration.renderadmin.product-variant-details.configuration.render
Generated via shopify app generate extension --template product_configuration.
Supports edit links using RFC 6570 URL templates ({product_id} variable) to
open the bundle app’s configuration UI. Requires Shopify CLI 3.76+ and API
version 2025-01.
- Migration: extensions created via Partner Dashboard must migrate to CLI —
add
[extensions.targeting.urls]to TOML and redeploy. - Docs: Add Merchant Config UI
Admin Link Extension
Opens the embedded bundle app to create or update bundle components.
- Docs: Create Admin Links
See Also
- hydrogen-bundles — Storefront rendering: detection, components, GraphQL patterns
- hydrogen-development-training — Hydrogen learning curriculum
- Shopify Bundles (Confluence source)
- Shopify Bundles Overview (shopify.dev)
- Start Building Bundles (shopify.dev)
- Add Product Fixed Bundle (shopify.dev)
- Add Variant Fixed Bundle (shopify.dev)
- Add Customized Bundle Function (shopify.dev)
- Shopify Bundles API docs