On a large WooCommerce store, the Add to Cart buttons on shop and category pages are where most sales start. When they misbehave, shoppers notice straight away: the button sends them to the product page instead of adding the item, the page reloads and loses their place, or an out-of-stock item looks buyable until they click it.

I recently fixed exactly this on a collectibles store with more than 28,000 products, built with Elementor. Here's what was going on, how to check your own store, and the fix, including the approach I had to throw away because it made the store slow.

The symptoms

  • Clicking Add to Cart on a category page took shoppers to the product page, or reloaded the page, instead of adding the item in place.
  • Out-of-stock products in the grid weren't handled consistently, so some buttons looked like they would add an item that couldn't be bought.
  • None of it happened on every product, which made it look random.

Why it happens

Three separate things were overlapping.

1. WooCommerce only adds to cart in place when it's allowed to. Two settings in WooCommerce → Settings → Products decide this:

  • Enable AJAX add to cart buttons on archives must be ticked.
  • Redirect to the cart page after successful addition must be unticked, unless you really want every click to open the cart.

2. The page builder can change the button. Elementor's product widgets and some themes output their own version of the button, and on this store a redirect was being added to the button link. WooCommerce's JavaScript saw a normal link and simply followed it.

3. Out-of-stock products have a different link. This is the useful part. For a simple product that can be bought, WooCommerce builds the button link as ?add-to-cart=123. For a product that is out of stock, variable, or otherwise can't go straight into the cart, the "button" is just a link to the product page. So the link itself tells you whether the product can be added, even when the theme's CSS classes don't.

Check your own store

  1. Open a category page, right-click an Add to Cart button and choose Inspect.
  2. Look at the href. If it contains add-to-cart=, WooCommerce considers the product buyable from the grid.
  3. Look at the classes. WooCommerce needs add_to_cart_button and ajax_add_to_cart to add the item without leaving the page.
  4. Check for extra parameters added to the link by your theme or builder, and test with the setting Redirect to the cart page turned off.

The fix

The fix has two small parts: make sure the right buttons get WooCommerce's AJAX behaviour, and stop anything else redirecting them.

In PHP, give every buyable simple product in the grid the AJAX class. This runs on products WooCommerce has already loaded for the page, so it costs nothing extra:

add_filter( 'woocommerce_loop_add_to_cart_args', function ( $args, $product ) {
    if ( $product->is_type( 'simple' ) && $product->is_purchasable() && $product->is_in_stock() ) {
        $args['class'] = trim( $args['class'] . ' ajax_add_to_cart' );
    }
    return $args;
}, 10, 2 );

Then a few lines of JavaScript tidy up buttons that a builder widget renders on its own. They decide from the link, not from styling classes, whether a product can go straight into the cart, and they remove any redirect that has been added to it:

document.querySelectorAll( 'a.add_to_cart_button' ).forEach( ( button ) => {
    const url = new URL( button.href, location.origin );

    if ( ! url.searchParams.has( 'add-to-cart' ) ) {
        // Out of stock or needs options: it's a product link, so make that clear.
        button.classList.remove( 'ajax_add_to_cart' );
        return;
    }

    // Buyable: let WooCommerce add it in place.
    button.classList.add( 'ajax_add_to_cart' );
    button.dataset.product_id = url.searchParams.get( 'add-to-cart' );
} );

Run the script after the product grid has loaded, and again if the grid loads more products with infinite scroll or filters. Adjust the redirect clean-up to whatever your builder adds to the link.

The approach to avoid

My first version checked stock in PHP: on each page it built a list of every product's stock status, so the script could look them up. On a small shop that's fine. On 28,000 products it means a large query and a lot of memory on every single page view, and the store slowed down badly.

The lesson: don't load data for the whole catalogue to fix something on one page. WooCommerce already tells you what you need in the button link, so use it.

The result

Add to Cart now works the way shoppers expect across the whole catalogue: buyable items go straight into the cart without leaving the page, out-of-stock items lead to the product page where shoppers can see why, and the store is as fast as before.

If your shop buttons behave strangely and you'd rather not dig through it yourself, get in touch. It's usually a quick fix once you know where to look.