AJAX add to cart

Topic summary

AJAX add-to-cart uses a Liquid-rendered variant ID ({{ product.selected_or_first_available_variant.id }}) that does not change client-side when the user switches product options. The add.js request works only after a page reload because Liquid is rendered server-side, producing a fixed ID in the HTML.

Key explanation:

  • Liquid (Shopify’s templating) runs on the server, so the injected variant ID is static in the delivered HTML.
  • Changing options updates the selected variant in the browser, but the Liquid value won’t update without a new page render.

Suggested approach:

  • Watch option/variant selector changes in JavaScript and update the ID sent to cart/add.js accordingly.
  • Many themes update the URL when a new variant is selected; reloading reflects the new variant in Liquid. Alternatively, read the current variant from the updated URL or theme’s JS state and use that ID.

Status:

  • No concrete code solution provided; the core cause is identified.
  • Action item: implement a JS listener to capture variant changes and pass the correct variant ID to the AJAX add-to-cart.

Unresolved questions:

  • Specific method/event to detect variant changes in the current theme.
Summarized with AI on December 28. AI used: gpt-5.

I am using this code to add an item to the shopify cart

let formData = {
                    'items': [
                        { 'id': {{ product.selected_or_first_available_variant.id }}, 'quantity': 1 },
                    ]
                };
                
                fetch(window.Shopify.routes.root + 'cart/add.js', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(formData)
                })
                .then(response => {
                    return response.json();
                })
                .then(data => {
                    console.log('Success:', data);
                    // Add any additional logic here, e.g., updating the cart UI
                })
                .catch((error) => {
                    console.error('Error:', error);
                });

The issue is that {{ product.selected_or_first_available_variant.id }} doesn’t automatically update. I have to refresh/reload page before it works. Any help would be greatly appreciated. Thanks!

Of course it does not update – any liquid is processed server-side and then your browser receives HTML, which includes line like:
{ ‘id’: 2734609228746528, ‘quantity’: 1 }

If you change product option selectors, you’d need to watch for this in your JS code.

Most themes update the URL when new variant is selected so when you reload the page you receive updated HTML.