Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
Hey everyone,
I'm trying to add an upsell section on the product page in Dawn - one click should add 3 products. The liquid part is easy, but I'm stuck on the ajax.
I've seen a few tutorials on using Fetch like this one and was able to replicate that method, but it seems this isn't the method used in Dawn, and I wanted to understand how Dawn does it, and have a more seamless integration.
For the Add to Cart button, Dawn uses the FormData API and passes the product ID with a hidden input. Why can't I do this with multiple items also? E.g. -
<input type="hidden" name="items" value="{id:41643147788484,quantity:1},{id:41643131044036,quantity:1},{id:41572158046404,quantity:1}">
Another thing I tried is to pass the items list in product-form.js, under the line where formData is defined.
let items = [
{id:41643147788484,quantity:1},
{id:41643131044036,quantity:1},
{id:41572158046404,quantity:1}
]
const formData = new FormData(this.form);
formData.append('items', JSON.stringify(items))
Neither of these work, I'm getting a 400 error and the error message is "must be a collection of items: items"
Do I even need to use stringify in FormData API? My payload in chrome inspector seems ok.
Any advice? Thanks!
You have a create a JSON of all the products and then send it with fetch /add API.
You can contact me if you need help in setting up the upsell products.
Any luck with this? looks like multiple items cannot be sent with FormData 😕
Couldn't get it to work with FormData. Doesn't look like items works for it.
Did get it to work with json though.
Had to change the fetchConfig() to json and setup the appropriate body. Something important is to make sure you're using variant.ids and not product.ids or you'll get a 404 error on the request.
<input name="items[0][id]" value="123456789" >
<input name="items[0][quantity]" value="1" >
<input name="items[1][id]" value="987654321" >
<input name="items[1][quantity]" value="1" >
<input name="items[1][properties][first prop key]" value="first prop value">
<input name="items[1][properties][second prop key]" value="second prop value">
const items = [
{
"id": "123456789",
"quantity": 1
},
{
"id": "987654321",
"quantity": 1,
"properties": {
"first prop key": "First prop value",
"second prop key": "Second prop value"
}
},
]
const formData = new FormData();
buildFormData(formData, 'items', items);
function buildFormData(formData, key, data) {
if (data === Object(data) || Array.isArray(data)) {
for (const i in data) buildFormData(formData, `${key}[${i}]`, data[i]);
} else data && formData.append(key, data);
}
buildFormData function is self explanatory. It should output something like this when you log your formData Object, which you can then use in your body request:
console.log(Object.fromEntries(formData.entries()))
---
{
"items[0][id]": "123456789",
"items[0][quantity]": "1",
"items[1][id]": "987654321",
"items[1][quantity]": "1",
"items[1][properties][first prop key]": "First prop value",
"items[1][properties][second prop key]": "Second prop value"
}
June brought summer energy to our community. Members jumped in with solutions, clicked ...
By JasonH Jun 5, 2025Learn how to build powerful custom workflows in Shopify Flow with expert guidance from ...
By Jacqui May 7, 2025Did You Know? May is named after Maia, the Roman goddess of growth and flourishing! ...
By JasonH May 2, 2025