Mastering Multi-Product Bundles: Add Multiple Items & Quantities to Checkout on Shopify
Hey there, fellow store owners! As a Shopify migration expert, I spend a lot of time diving into the nitty-gritty of what makes our stores tick, and that often means sifting through some fantastic community discussions. Recently, a thread popped up that really caught my eye – "Displaying a list of products with quantities" – started by a user named Conehead. It’s a common challenge, and the community came through with some brilliant solutions.
Conehead’s dilemma was straightforward but powerful: how to present a list of, say, four specific products, let customers pick quantities for each, and then, with a single "Buy Now" click, whisk them straight to checkout with all those chosen items in their cart. Sounds simple, right? But as Conehead found, trying to get AI-generated code to play nicely with a Shopify theme for this kind of multi-item functionality can be a real headache.
Why Standard Solutions Fall Short (and What Works)
The core issue, as Recomento in the thread pointed out, is that standard single-product forms in Shopify are designed to submit just one product ID and quantity at a time. This is why "AI-generated code usually fails" – it often doesn't account for Shopify's specific requirements for batch-adding items. What we need is a way to tell Shopify, "Hey, add ALL these items with their specific quantities, simultaneously!"
This "Build Your Own Bundle" mechanic is a fantastic way to boost your Average Order Value (AOV), and thankfully, the community offered up two robust, code-based solutions that integrate seamlessly into your Shopify theme. Both leverage Shopify's native capabilities, moving beyond basic forms to handle multiple products at once.
Option 1: The Quick & Direct Route with a Custom Section
Ploqo initially offered a solution using a "Custom Liquid" section, which Conehead loved for its immediate effectiveness. The beauty of this approach, and one that Conehead specifically asked about, is making it a proper, organized section file. This keeps your code clean and makes it easy to manage via the Shopify Theme Editor.
This method uses a direct URL redirect to the cart, appending all selected items and quantities. It’s straightforward and effective for many use cases. Here’s the code for a custom section file, let's call it sections/quantity-list.liquid:
{%- for p in section.settings.products -%}
{%- assign v = p.selected_or_first_available_variant -%}
{%- if v -%}
{{ p.title }}
{{ v.price | money }}
{%- endif -%}
{%- endfor -%}
{% schema %}
{
"name": "Quantity list",
"settings": [
{ "type": "product_list", "id": "products", "label": "Products", "limit": 10 },
{ "type": "text", "id": "button_label", "label": "Button label", "default": "Buy now" }
],
"presets": [{ "name": "Quantity list" }]
}
{% endschema %}
Implementing the Quantity List Section:
Here’s how you can add this to your theme, just like Ploqo detailed:
- Go to your Shopify Admin, navigate to Online Store > Themes.
- Click the … button next to your current theme and select Edit code.

- In the code editor, click the sections folder, then click the Add a new section icon (or New File).
- Name the new file
quantity-list.liquidand press Enter. 
- Paste the code block above into this new file and click Save.

- Now, go back to your theme customization screen (Online Store > Themes > Customize).
- On the page where you want the list to appear, click Add section under Template.
- Search for "Quantity list" and click it.

- In the section settings, under Products, you can pick the specific products you want to feature. You can also customize the "Buy now" button label.

- Click Save.
This method is quick to implement, but remember NoahMueller’s excellent advice: always test mixed quantities, zeroed rows, and products that might become unavailable. Confirm the checkout contains exactly what the customer selected to avoid support headaches later.
Option 2: The Robust & Flexible Approach with Cart AJAX API
For a more advanced and robust solution, Recomento provided a fantastic implementation using Shopify’s native Cart AJAX API (/cart/add.js). This is often preferred because it handles the addition of multiple items in a single, atomic network request. This means no race conditions or partially filled carts, and it gives you more control over the process, including better error handling.
This solution also comes as a custom section, making it super friendly for your theme customizer. Here’s the code for sections/multi-product-bundle.liquid:
{{ section.settings.heading | default: 'Select Your Products' }}
{% for block in section.blocks %}
{% assign prod = block.settings.product %}
{% if prod != blank %}
{{ prod.title }}
{{ prod.price | money }}
{% endif %}
{% endfor %}
Total Items: 0
{% schema %}
{
"name": "Multi-Product Bundle",
"settings": [
{ "type": "text", "id": "heading", "label": "Heading", "default": "Build Your Bundle" }
],
"blocks": [
{
"type": "product",
"name": "Product",
"settings": [
{ "type": "product", "id": "product", "label": "Select Product" }
]
}
],
"presets": [
{ "name": "Multi-Product Bundle" }
]
}
{% endschema %}
And here’s the crucial JavaScript logic that goes with it (you can place this in your theme’s main JavaScript file or directly within the section’s script tags):
document.addEventListener('DOMContentLoaded', () => {
const c
if (!container) return;
const checkoutBtn = document.getElementById('bundle-checkout-btn');
const totalQtyDisplay = document.getElementById('total-bundle-qty');
const items = container.querySelectorAll('.bundle-item');
function updateTotal() {
let total = 0;
items.forEach(item => {
const input = item.querySelector('.bundle-qty-input');
total += parseInt(input.value || 0, 10);
});
totalQtyDisplay.textC
checkoutBtn.disabled = total === 0;
}
// Handle + / - buttons
container.addEventListener('click', (e) => {
if (e.target.classList.contains('qty-btn')) {
const input = e.target.parentElement.querySelector('.bundle-qty-input');
let val = parseInt(input.value || 0, 10);
if (e.target.classList.contains('plus')) val++;
if (e.target.classList.contains('minus') && val > 0) val--;
input.value = val;
updateTotal();
}
});
// Handle direct input change
container.addEventListener('input', (e) => {
if (e.target.classList.contains('bundle-qty-input')) {
updateTotal();
}
});
// Add all to cart and redirect straight to Checkout
checkoutBtn.addEventListener('click', async () => {
const itemsToAdd = [];
items.forEach(item => {
const variantId = item.dataset.variantId;
const qty = parseInt(item.querySelector('.bundle-qty-input').value || 0, 10);
if (qty > 0 && variantId) {
itemsToAdd.push({ id: parseInt(variantId, 10), quantity: qty });
}
});
if (itemsToAdd.length === 0) return;
checkoutBtn.innerText = 'Processing...';
checkoutBtn.disabled = true;
try {
const resp fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items: itemsToAdd })
});
if (response.ok) {
// Redirect directly to checkout
window.location.href = '/checkout';
} else {
const err = await response.json();
alert('Error adding products: ' + (err.description || 'Please check stock availability.'));
checkoutBtn.innerText = 'Buy Now';
checkoutBtn.disabled = false;
}
} catch (error) {
console.error(error);
window.location.href = '/checkout';
}
});
});
Implementing the Multi-Product Bundle Section:
The steps are similar to the previous section:
- Follow steps 1-4 from the previous section to create a new file in your sections folder. Name it
multi-product-bundle.liquid. - Paste the HTML/Liquid/Schema code block (the first one for this option) into this new file and click Save.
- Paste the JavaScript code block (the second one for this option) into your theme’s main JavaScript file (e.g.,
assets/theme.jsorassets/global.js, depending on your theme structure) or withintags at the bottom of yourmulti-product-bundle.liquidfile. If placing in the section file, ensure it's after the HTML. - Go to your theme customizer (Online Store > Themes > Customize).
- On your desired page, click Add section and search for "Multi-Product Bundle" and add it.
- In the section settings, you can customize the heading and then add individual products using the "Product" blocks.
- Click Save.
This method offers a better user experience by instantly updating the total quantity and disabling the "Buy Now" button when no items are selected. It also provides clearer feedback if there's an issue adding products. NoahMueller’s point about verifying the checkout contents after the redirect is particularly crucial here, especially with more complex bundles.
Bringing It All Together & Next Steps
Both of these solutions address Conehead's original question beautifully, offering ways to display products with quantities and send them directly to checkout. The key takeaway from this community discussion is that while AI can give you a starting point, understanding Shopify's underlying APIs and theme structure is essential for robust, maintainable solutions.
Conehead also asked about resources for Shopify code fragments. While there isn't one official "book of snippets," Ploqo correctly pointed to Shopify's Liquid reference and the Sections documentation as your best friends. These official docs provide the foundational knowledge you need to build and customize your store like a pro. And if you're thinking about starting your own Shopify store or migrating to this powerful platform, getting familiar with these customization options is a huge advantage. You can start your Shopify journey right here and put these insights into practice!
Remember, the goal isn't just to get the code working, but to ensure it creates a smooth, error-free experience for your customers. Happy selling!