Cart Transform: Expand Operation
Replace bundled products in the cart with their individual components
Overview
The Expand Lines block replaces bundled products in the cart with their individual components. The customer sees one line item in their cart, but the system processes it as containing multiple components.
- Product bundles — break down bundle products into their individual items
- Kit products — expand kits to show individual components with custom pricing
- Custom component products — transform products with attached component data into separate line items
- Dynamic pricing — apply per-variant pricing from metafield mappings
Two Methods
Components can come from two sources, and both can be used together:
- Function Studio configuration — define components directly in the block using the visual editor
- Cart line properties — attach component data to cart lines via the
_componentsproperty (set by your theme, app, or storefront)
Setup
Open your cart transform function
Navigate to the function you want to edit in Function Studio
Add the Expand Lines block
Click Add Action and select Expand Lines from the action list
Configure the block
Set the options described in the Settings section below
Settings
Cart Line Groups
Required
Select which groups of cart lines should be expanded. Groups must be defined earlier in your function using a Define Cart Line Groups block.
Component Items
Define the component items that will be added to the selected cart line. For each component:
Component Variant
Required
Select the product variant that will be added to the cart.
Quantity
How many of this component per bundle item (default: 1). When the bundled item has a quantity greater than 1, component quantities are automatically multiplied.
Component Price Override
Set a fixed price for this component, or leave at 0 to use the original product price. Hidden when Apply Bundle Discount is enabled — component prices are then controlled by the bundle discount instead.
Read From Attributes
Optional
When enabled, the block reads component data from the _components cart line property in addition to any components configured in Function Studio. See Cart Line Properties Configuration below.
Apply Bundle Discount
When enabled, a percentage discount is applied to the entire expanded bundle. Individual component price overrides are hidden — the discount applies to the bundle total instead.
Bundle Price Adjustment
Shown when Apply Bundle Discount is enabled
The percentage discount to apply to the bundle (0–100%). This field supports two modes:
- Static value — enter a fixed percentage (e.g., 10%)
- Linked value — click the link icon to connect the discount to a metafield, cart attribute, or line property. This allows different products to have different bundle discount percentages.
Note
Linking this field requires the Advanced plan.
Bundle Image
Optional
Custom image for the expanded bundle product.
Bundle Title
Optional
Custom display title for the expanded bundle.
Cart Line Properties Configuration
You can configure expansion by adding component data directly to your cart lines using the _components property. Enable Read from attributes in the block settings to use this method.
Components JSON Structure
The _components attribute should contain a JSON array of component objects:
[
{
"id": "12345",
"price": "29.99",
"qty": 2,
"properties": {
"color": "Red",
"size": "Large"
}
},
{
"id": "67890",
"price": "15.50",
"qty": 1,
"properties": {
"material": "Cotton"
}
}
]
Component Fields
id
Required
Product variant ID for the component. Must be the numeric part of the Shopify variant GID — e.g., "12345" from gid://shopify/ProductVariant/12345.
price
Optional
Fixed price per unit for this component. If omitted, defaults to 0. This becomes the component’s unit price in the expanded cart.
qty
Optional
Quantity of this component per bundled item. If omitted, defaults to 1.
properties
Optional
Custom key-value pairs for the component. Converted to line item attributes in the expanded cart. Keys and values must be strings.
Object Format with Per-Line Overrides
Instead of a plain array, you can use an object format that includes per-line overrides for the bundle image, title, and discount percentage. The system auto-detects which format you’re using.
{
"image": "https://cdn.shopify.com/bundle-image.jpg",
"title": "Custom Bundle Title",
"percentageDecrease": 20,
"items": [
{"id": "12345", "price": "29.99", "qty": 2, "properties": {"color": "Red"}},
{"id": "67890", "price": "19.99", "qty": 1}
]
}
image
Optional
Bundle image URL for this specific cart line. Overrides the global bundle image configured in Function Studio.
title
Optional
Bundle title for this specific cart line. Overrides the global bundle title.
percentageDecrease
Optional
Bundle percentage decrease for this specific cart line (e.g., 20 means 20% off). Overrides the bundle discount configured in Function Studio. Set to 0 to explicitly remove the discount for this line.
items
Required
Component items using the same format as the array format described above.
Setting the Components Property
The _components property can be set through various methods:
In Product Forms (Liquid Templates)
<input type="hidden" name="properties[_components]" value='[{"id":"12345","price":"29.99","qty":2}]'>
Via Ajax Cart API
{
"id": "12345",
"qty": 1,
"properties": {
"_components": '[{"id":"12345","price":"29.99","qty":2}]'
}
}
How It Works
Weighted Price Allocation
When you use both component-level fixed prices and a bundle discount percentage, Shopify doesn’t allow combining these directly. Function Studio automatically handles this by using a weighted price allocation algorithm:
Calculate total
The system sums all component prices (unit price × quantity)
Apply discount
The percentage discount is applied to the total
Distribute proportionally
The discounted total is distributed across components based on their original price weight
Set final prices
Each component’s final price is set to their allocated share
Example:
- Component A: $60 (weight: 60%)
- Component B: $40 (weight: 40%)
- Bundle discount: 10%
- Discounted total: $90
- Component A final price: $54 (60% of $90)
- Component B final price: $36 (40% of $90)
Dynamic Component Quantities
When the bundled item has a quantity greater than 1, component quantities are automatically multiplied:
- Bundle in cart: Quantity 3
- Component configuration: Quantity 2 per bundle
- Result: 6 total components (3 × 2)
Combined Configuration Sources
When both Function Studio components and cart line properties are used, the system combines components from both sources. Function Studio components are added first, then any components from the _components property.
Examples
Example 1: Static Components (Function Studio)
A “Starter Kit” bundle expands into its individual components.
Create a cart line group
Add a “Define Cart Line Groups” block with group name STARTER_KITS
Add the Expand block
Select Expand Lines and set Cart Line Groups to STARTER_KITS
Add components
Add T-shirt variant (qty 1, $25.99), Cap variant (qty 1, $15.99), and Stickers variant (qty 2, $5.99)
Result
Bundle item is replaced with a single line item containing all 3 components with combined pricing
Example 2: Dynamic Components from Cart Properties
Products with a _components property are automatically expanded.
Create a cart line group
Add a “Define Cart Line Groups” block with group name COMPONENT_BUNDLES
Add the Expand block
Select Expand Lines, set Cart Line Groups to COMPONENT_BUNDLES, and enable Read from attributes
Leave Component Items empty
Components come from the cart line’s _components property
Result
Each bundle is expanded using the component data attached to the cart line
Example 3: Dynamic Bundle Discount from Metafield
Different bundle products have different discount percentages stored in a variant metafield.
Set up metafields
Create a variant metafield custom.bundle_discount (type: number_decimal) and set values per variant
Create the group and block
Add a “Define Cart Line Groups” block for bundles, then an “Expand Lines” block
Enable bundle discount
Turn on Apply Bundle Discount, then click the link icon next to the discount field and select custom.bundle_discount
Result
Each bundle product is expanded with its own discount percentage pulled from the variant metafield
Example 4: Price Mapping from Variant Metafield
Use a Variant Price Mapping block to apply dynamic per-component pricing from a CSV metafield.
Add a Variant Price Mapping block
Place it before the Expand block. Configure it to read from the variant metafield containing pricing data
Add the Expand block
In the Price Mapping dropdown, select the mapping variable created by the Variant Price Mapping block
Result
Component prices are dynamically looked up from the metafield CSV data at runtime, overriding static price overrides
Best Practices
Component Setup
- Ensure all component variants exist and are published in your store
- Consider inventory management — component products may need separate stock tracking
- Test with different cart quantities to verify component multiplication
Pricing Strategy
- Use percentage discounts to incentivize bundles over individual purchases
- When using linked fields for the discount, ensure the linked field always resolves to a valid number between 0 and 100
- Use Price Mapping when you need per-variant component pricing that can be updated without redeploying the function
Customer Experience
- Use meaningful bundle titles so customers understand what they’re purchasing
- Provide a bundle image that represents the combined items
- The customer sees one line item — individual component prices are not visible
Important Considerations
Product Availability
- All component variants must exist in your store
- Components must be available (not archived or deleted)
- Consider inventory levels for component products
Cart Behavior
- Original bundle items are completely replaced by the expanded bundle
- All components are merged into a single line item in the cart
- Cart totals reflect the combined pricing of all components
- Individual component prices are not visible to customers
Data Format Requirements
- Cart properties must contain valid JSON
- Component IDs must be the numeric part of Shopify variant GIDs (e.g.,
12345fromgid://shopify/ProductVariant/12345) - Property keys and values must be strings
- Quantities must be positive numbers
Plan Requirements
- Linking the Bundle Price Adjustment field to a metafield or attribute requires the Advanced plan
Troubleshooting
Expansion Not Working
- Check your groups — review conditions in your line item groups
- Verify variant IDs — ensure all component variant IDs exist in your store
- Start simple — begin with basic expansion and add complexity gradually
Cart Properties Issues
- Check JSON format — ensure the
_componentsproperty contains valid JSON - Verify variant IDs — make sure all component IDs are correct numeric IDs
- Enable Read from attributes — the toggle must be on for cart properties to be read
- Test the property — add the property to a test cart and verify it’s set correctly
Pricing Problems
- Verify price format — prices in
_componentsJSON should be strings (e.g.,"29.99") - Check bundle discounts — confirm discount percentages are between 0 and 100
Components Not Appearing
- Check group matching — verify your cart items match the group conditions
- Review component data — ensure component variants are available and not archived
- Test step by step — use the function tester to see which components are being processed