Table of Contents
- Why use metafields for bundles?
- Step 1: Add a metafield definition
- Step 2: Add bundle components to variants
- Step 3: Liquid logic to check availability
- Step 4: Show or disable the add-to-cart button
- Conclusion
Why use metafields for bundles?
Shopify doesn’t support real bundles natively, and apps can be slow, bloated, or expensive. With a bit of Liquid and metafields, you can create virtual bundles that reuse existing SKUs, track real inventory, and update dynamically depending on selected variant.
Step 1: Add a metafield definition
Go to Settings → Metafields and metaobjects in your Shopify Admin. Then:
- Click Variants
- Click Add definition
- Call it something like “Bundle Components”
- Set Namespace and key to:
custom.bundle_components
- Choose Single line text as the content type
- Click Save
Step 2: Add bundle components to variants
Now go to any product you want to use as a bundle. For each variant (e.g. Size M, Size L), scroll down to the Metafields section.
Insert a comma-separated list of SKUs that make up this bundle variant. For example:
SKU123, SKU456, SKU789
Each of these must correspond to existing variant SKUs in your store (that are actively stocked).
Step 3: Liquid logic to check availability
Paste this near the top of your product template:
{% raw %}
{% liquid
assign variant_available = current_variant.available
assign bundle_skus = current_variant.metafields.custom.bundle_components | split: ','
assign is_bundle = false
assign is_bundle_available = true
if bundle_skus.size > 0 and bundle_skus.first != blank
assign is_bundle = true
for sku in bundle_skus
assign trimmed_sku = sku | strip
assign found_variant = nil
for p in collections.all.products
for v in p.variants
if v.sku == trimmed_sku
assign found_variant = v
endif
endfor
endfor
if found_variant == nil or found_variant.available == false
assign is_bundle_available = false
endif
endfor
endif
%}
{% endraw %}
This block checks if the variant is a bundle, and whether all its components are in stock.
Step 4: Show or disable the add-to-cart button
Now, update your button text logic (and disable state) like this:
{% raw %}
{% if variant_available and is_bundle_available %}
{{ button_text }}
{% else %}
sold out
{% endif %}
{% endraw %}
You can also update Alpine.js or Vue bindings with similar logic if you’re using a JS framework.
Conclusion
This approach gives you full control over Shopify bundles:
- No paid apps
- Faster page load (no injected JS)
- Real inventory sync — since you’re using real SKUs
- Variant-specific bundles for sizes, colours, kits, and more
Need help implementing this on your theme? I work with Shopify stores running custom themes like Label and Dawn — and can help you build performant, flexible bundle logic with zero bloat.