WooCommerce supports AJAX add-to-cart natively for simple products via the add_to_cart button class. For custom cart widgets that need to reflect the updated cart total and item count without a page reload, use the woocommerce_add_to_cart_fragments filter.
Problem: WooCommerce variable and simple product pages redirect to the cart on every "Add to Cart" click, interrupting the user's browsing flow and making it difficult to add multiple items.
Solution: Enable the built-in AJAX add-to-cart option for archive pages in WooCommerce → Settings → Products. For single product pages, register a custom wp_ajax_nopriv_ action — enqueue a script that posts the product ID and variation data, receives the updated cart count in the JSON response, and updates the cart widget without a page reload.
First, enable AJAX add-to-cart for single product pages:
// Ensure AJAX add-to-cart is enabled for single products
add_filter( 'woocommerce_product_single_add_to_cart_text', function() {
return __( 'Add to cart', 'woocommerce' );
} );
// Optionally enable the AJAX refresh on the shop/archive pages
// (already enabled by default in WooCommerce settings)
Place a dynamic cart link anywhere in your template (header, sidebar, etc.):
// In your template file
?><a class="cart-contents" href="<?php echo esc_url( wc_get_cart_url() ); ?>"
title="<?php esc_attr_e( 'View your shopping cart', 'woocommerce' ); ?>">
<?php
printf(
_n( '%d item', '%d items', WC()->cart->get_cart_contents_count(), 'woocommerce' ),
WC()->cart->get_cart_contents_count()
);
echo ' — ' . WC()->cart->get_cart_total();
?>
</a><?php
Register the fragment so WooCommerce replaces the HTML after every AJAX cart event:
add_filter( 'woocommerce_add_to_cart_fragments', 'refresh_cart_contents_fragment' );
function refresh_cart_contents_fragment( $fragments ) {
ob_start();
?>
<a class="cart-contents" href="<?php echo esc_url( wc_get_cart_url() ); ?>"
title="<?php esc_attr_e( 'View your shopping cart', 'woocommerce' ); ?>">
<?php
printf(
_n( '%d item', '%d items', WC()->cart->get_cart_contents_count(), 'woocommerce' ),
WC()->cart->get_cart_contents_count()
);
echo ' — ' . WC()->cart->get_cart_total();
?>
</a>
<?php
$fragments['a.cart-contents'] = ob_get_clean();
return $fragments;
}
NOTE: The CSS selector key in the $fragments array (a.cart-contents) must exactly match the selector of the element in the template. If you change the HTML tag or class name, update the fragment key to match — otherwise WooCommerce will not find the element to replace and the cart widget will appear stuck after adding items.