Why does my Add to Cart button spin forever and never actually add the item?
When the Add to Cart button spins forever instead of confirming the item was added, the cause is almost always a JavaScript conflict between your theme and an installed app, not a Shopify outage. Here's how to isolate it methodically.
What's going on
A customer clicks "Add to Cart," the button shows its loading spinner, and then it just... stays that way. No error message, no cart drawer sliding open, no updated cart count. Refresh the page and the item might actually be in the cart, or it might not be there at all. It's inconsistent enough that you can't always reproduce it yourself, but customers are hitting it and some are almost certainly abandoning the page when it happens.
This is one of the more frustrating storefront bugs to chase because the spinner itself isn't the bug, it's a symptom. The Add to Cart button's loading state is just a CSS class or attribute that your theme's JavaScript adds when the click happens and removes once it gets a response back from Shopify's cart API. If that JavaScript never gets a response, throws an error partway through, or never runs at all because something else on the page broke first, the spinner has no signal telling it to stop, so it just sits there indefinitely.
Because the underlying causes range from "a coding mistake in a custom snippet" to "two apps are both trying to control the same button" to "a specific product variant is misconfigured," the fix depends entirely on correctly diagnosing which of those it is before changing anything.
Why it happens
Shopify's native Add to Cart flow makes an asynchronous request (typically to the /cart/add endpoint) and then updates the page once that request resolves, all driven by your theme's JavaScript. Anything that breaks that JavaScript chain, an error thrown earlier on the page, a script that never finishes loading, a conflicting event listener attached by a second script, or a request that times out or returns an unexpected response, can leave the button's loading state with no code left to turn it off.
In practice this is overwhelmingly caused by one of two things: a customization made directly to the theme's code (by an agency, freelancer, or trial-and-error edits) that has a bug, or an installed app that also modifies the product page or cart behavior and ends up conflicting with the theme's own script. Apps that add upsells, bundles, subscription options, or custom cart drawers are especially prone to this because they frequently attach their own logic to the exact same button element the theme is already managing.
Less commonly, the issue is specific to certain products or variants, for example a variant that's technically out of stock or misconfigured in a way that causes the cart API to respond with an error the theme's JavaScript doesn't handle gracefully, so the spinner hangs only on that subset of products rather than storewide.
5 ways to fix it
Open the browser console and watch what actually happens when you click Add to Cart
Before touching theme code, reproduce the problem with your browser's developer console open (F12 or right-click > Inspect > Console) and the Network tab visible. Click Add to Cart and watch for red errors in the console and for the /cart/add.js (or /cart/add) request in the Network tab. If the request never fires, a JavaScript error earlier on the page is likely blocking the click handler from running at all. If the request fires but the button never resets, the request itself is failing (look at its response status and body) or the theme's own success/error callback is throwing an error before it removes the loading class. This single step tells you whether you're dealing with a broken request or a broken UI update, which determines everything else you do next.
Test on an unedited copy of your theme with all custom code removed
Duplicate your live theme, and on the duplicate remove any custom snippets, theme.liquid edits, or custom.js/custom.css files your team or a freelancer has added, then test Add to Cart there. Shopify's own themes (Dawn and other current free themes) handle the add-to-cart spinner state reliably out of the box, so if the button works correctly on a clean duplicate, the bug is in your customizations, not Shopify or the app it. This isolates the problem to something you can actually search your own codebase for rather than guessing at platform-level causes.
Disable apps one at a time, starting with anything that touches the cart or product page
Apps that inject their own product page scripts, cart drawers, upsell popups, or subscription widgets are a common cause of this exact symptom, because they often attach their own click listener to the same Add to Cart button and can silently intercept or duplicate the event. In your Shopify admin, go to Settings > Apps and sales channels, then deactivate suspect apps one at a time (cart upsell, bundles, reviews-with-widgets, and any recently installed app are good first suspects), reloading the product page after each change to see when the spinner starts resolving normally again. If disabling a specific app fixes it, you've found your conflict and can decide whether to remove that app, switch to an alternative, or ask its support team about a known compatibility issue with your theme.
Check theme app embeds and app blocks for overlapping cart scripts
Many apps now install as theme app embeds or app blocks (visible under Theme Editor > App embeds, or as blocks inside sections) rather than as raw code injections, and these can still load scripts that interfere with the native add-to-cart form. With the browser console open, turn off app embeds one at a time in the Theme Editor and retest, the same way you tested standalone apps. This step matters because an app can look 'disabled' at the app level while its theme embed is still active and still shipping JavaScript to the page.
If nothing above resolves it, get a developer to trace the exact click handler and network response
If the button still hangs after ruling out custom code and app conflicts, the remaining causes are usually more specific: a slow or failing response from Shopify's cart API for a particular variant (for example, an out-of-stock or misconfigured variant), a theme JavaScript error that only fires under certain conditions (sold-out states, quantity selectors, or specific product templates), or a race condition between two scripts both trying to manage the same button's disabled/loading state. At this point it's worth having a developer read the actual add-to-cart JavaScript in your theme (usually in a file like global.js, product-form.js, or similar) alongside the Network tab response, since the fix is almost always a small, specific code correction rather than a platform setting.
Bottom line
Most "spinner never completes" cases trace back to a JavaScript conflict between your theme and one specific app (or a leftover custom code edit) rather than anything wrong with Shopify itself, so isolating with a clean theme duplicate and one-by-one app disabling will get you to the cause faster than randomly reinstalling apps or theme files. If you go through this process and confirm the culprit is a genuine app conflict rather than your own theme code, that's the point where a focused app-conflict diagnostic tool (rather than guesswork) earns its keep.
Browse the rest of the problem library, run a free storefront scan to catch issues like this automatically, or email us and we'll work out a custom solution for it.