
🛒 Ajax cart in WooCommerce: 3 ways from plugin to custom code
The "Add to cart" button in WooCommerce reloads the page by default on every click. A shopper picks a product, clicks, and waits. One and a half seconds, two, three. On mobile, all five. Every such delay cuts off part of the audience: according to the Baymard Institute, the average cart abandonment rate in e-commerce hovers around 70%, and a slow cart is one of the key factors.
An AJAX cart eliminates the reload. The product is added instantly, the header counter updates without the page blinking, and the shopper stays right where they were. For a store, this is a direct path to conversion: less friction, more completed purchases.
You can build an AJAX cart in WooCommerce three ways. Below, each one: from installing a plugin in a minute to custom PHP and JavaScript code.
💡 Quick overview:
- Method 1: install a free plugin, 2 clicks, works for simple and variable products
- Method 2: built-in WooCommerce setting, archives only, no variations
- Method 3: PHP + JavaScript in a child theme, full control, modern
wc-ajaxendpoint
What an AJAX cart is and why your store needs it

A regular WooCommerce cart works like this: shopper clicks "Add to cart" → browser submits the form → server processes it → page reloads → shopper sees the result. A chain of four steps, and you can lose a person at each one.
An AJAX cart changes the mechanics. The browser sends an asynchronous request to the server, the server returns JSON with updated cart data, and JavaScript updates the counter and mini-cart on the fly. The page stays put. The shopper does not even notice anything happened: the product is already in the cart.
From the store's perspective, the difference is tangible. A 2023 Google study showed that every extra step in the purchase funnel reduces conversion by 10-15%. By removing the reload, you remove a step. Plus, server load decreases: instead of rendering a full page, it serves lightweight JSON.
But there is a nuance: WooCommerce out of the box enables AJAX only for shop and category pages. On the single product page and for variable products, the reload remains. That is exactly the gap we are closing.
Method 1: Ajax add to cart for WooCommerce plugin

The fastest path, the free Ajax Add to Cart for WooCommerce plugin. Installs in a minute, requires no configuration, works right after activation.
The plugin handles AJAX adding for simple and variable products on any page: product, archive, category. The mini-cart updates automatically. According to WordPress.org, 10,000+ active installs, a 4.7 out of 5 rating, compatibility with WordPress 7.0+ and recent WooCommerce versions. Updated regularly: the latest release 2.6.5 came out in June 2026.
Installation:
- Go to WordPress admin → Plugins → Add New
- Search for "Ajax add to cart for WooCommerce"
- Click "Install", then "Activate"
That is it. Go to any product page and click "Add to cart": no reload, product added. The plugin requires no additional settings. If you need to disable AJAX for certain pages, the plugin settings have a corresponding filter.
An alternative, FunnelKit Cart (also free). Besides an AJAX cart, it provides a slide-out cart side panel and upsells inside it. It is a bit heavier, but for stores focused on average order value, it is justified.
Method 2: built-in WooCommerce setting

WooCommerce can do an AJAX cart out of the box, but with two limitations. It works only on archive pages (shop, categories, tags) and does not support variable products. For the single product page, the reload remains.
If your store sells only simple products and shoppers add them to the cart from the shop floor, this is enough. Enabled with a single checkbox:
- Admin → WooCommerce → Settings → Products → General
- In the "Add to cart behaviour" block, check "Enable AJAX add to cart buttons on archives"
- Save
Done. On the shop page and category pages, the "Add to cart" button now works without a reload. But visit a single product page, and it is still the same: a full reload cycle. For most stores, this is not enough, so let us move to the third method.
Method 3: PHP and JavaScript in a child theme

Full control over the AJAX cart comes from custom code. You decide which pages AJAX works on, how errors are handled, and what the shopper sees after adding a product.
We will write a handler on the modern wc-ajax endpoint; it plays nicely with caching plugins (WP Rocket, LiteSpeed Cache exclude ?wc-ajax= from the cache by default), unlike the old admin-ajax.php, which often behaves unpredictably on cached sites.
3.1 Child theme
The code will go into a child theme: this is insurance against losing changes when the parent theme updates. If you do not have a child theme yet, create one or use a plugin like Code Snippets; it lets you add PHP code without editing theme files.
Why a child theme is mandatory: the next time the parent theme updates, all your edits in functions.php and JS files will be overwritten. A child theme lives separately and is not touched by updates.
3.2 Enqueue JavaScript
In the child theme's functions.php, we register and localize the script:
1 function sd_ajax_add_to_cart_script() { 2 if (is_admin()) { 3 return; 4 } 5 6 wp_register_script( 7 'sd-ajax-add-to-cart', 8 get_stylesheet_directory_uri() . '/js/ajax-add-to-cart.js', 9 array('jquery', 'wc-add-to-cart'), 10 '1.0', 11 true 12 ); 13 wp_enqueue_script('sd-ajax-add-to-cart'); 14 15 wp_localize_script('sd-ajax-add-to-cart', 'sdAjaxCart', array( 16 'wc_ajax_url' => WC_AJAX::get_endpoint('sd_ajax_add_to_cart'), 17 'nonce' => wp_create_nonce('sd_ajax_cart_nonce'), 18 )); 19 } 20 add_action('wp_enqueue_scripts', 'sd_ajax_add_to_cart_script');
Breakdown. wp_register_script registers our future JS file with dependencies on jQuery and the built-in wc-add-to-cart. wp_localize_script passes two key parameters to JavaScript: the wc-ajax endpoint URL and a nonce key for CSRF protection. A nonce is a cryptographic signature that the server will verify when processing the request: without it, any external site could poke your cart.
3.3 JavaScript handler
Create a js folder in the child theme root and an ajax-add-to-cart.js file inside it:
1 jQuery(function ($) { 2 $('form.cart').on('submit', function (e) { 3 var $form = $(this); 4 var $button = $form.find('.single_add_to_cart_button'); 5 6 if (!$button.length || $button.hasClass('disabled')) { 7 return; 8 } 9 10 e.preventDefault(); 11 12 var data = { 13 product_id: $form.find('input[name=product_id]').val() || $button.val(), 14 quantity: $form.find('input[name=quantity]').val() || 1, 15 variation_id: $form.find('input[name=variation_id]').val() || 0, 16 }; 17 18 $button.removeClass('added').addClass('loading'); 19 20 $.ajax({ 21 type: 'POST', 22 url: sdAjaxCart.wc_ajax_url, 23 data: $.param(data) + '&nonce=' + sdAjaxCart.nonce, 24 success: function (response) { 25 if (response && response.error) { 26 window.location = response.product_url; 27 return; 28 } 29 $(document.body).trigger('added_to_cart', [ 30 response.fragments, 31 response.cart_hash, 32 $button, 33 ]); 34 }, 35 complete: function () { 36 $button.addClass('added').removeClass('loading'); 37 }, 38 }); 39 }); 40 });
The key difference from outdated tutorials: we use sdAjaxCart.wc_ajax_url (the wc-ajax endpoint) instead of wc_add_to_cart_params.ajax_url (the old admin-ajax.php). wc-ajax is automatically excluded by caching plugins and does not require a separate wp_ajax_nopriv_ hook; WooCommerce itself handles authenticated and unauthenticated users.
3.4 PHP handler
Add the following to the child theme's functions.php right after the first block:
1 function sd_ajax_add_to_cart_handler() { 2 if (!wp_verify_nonce($_POST['nonce'], 'sd_ajax_cart_nonce')) { 3 wp_send_json_error(array('message' => 'Security error'), 403); 4 } 5 6 $product_id = apply_filters( 7 'sd_ajax_add_to_cart_product_id', 8 absint($_POST['product_id']) 9 ); 10 $quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']); 11 $variation_id = absint($_POST['variation_id']); 12 13 $passed = apply_filters( 14 'sd_ajax_add_to_cart_validation', 15 true, 16 $product_id, 17 $quantity 18 ); 19 20 $product_status = get_post_status($product_id); 21 22 if ($passed && 'publish' === $product_status 23 && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) 24 ) { 25 do_action('sd_ajax_added_to_cart', $product_id); 26 27 if ('yes' === get_option('woocommerce_cart_redirect_after_add')) { 28 wc_add_to_cart_message(array($product_id => $quantity), true); 29 } 30 31 WC_AJAX::get_refreshed_fragments(); 32 } else { 33 wp_send_json(array( 34 'error' => true, 35 'product_url' => apply_filters( 36 'sd_ajax_cart_redirect_after_error', 37 get_permalink($product_id), 38 $product_id 39 ), 40 )); 41 } 42 43 wp_die(); 44 } 45 add_action('wc_ajax_sd_ajax_add_to_cart', 'sd_ajax_add_to_cart_handler');
The handler does three things. It checks the nonce: if the request came from an external site, it immediately returns a 403. It adds the product to the cart via WC()->cart->add_to_cart(), the standard WooCommerce method that handles stock, variations, and validation on its own. It calls WC_AJAX::get_refreshed_fragments(); this method returns updated HTML fragments of the mini-cart, which our JavaScript will pick up.
The hook wc_ajax_sd_ajax_add_to_cart is a wc-ajax endpoint that WooCommerce processes bypassing most caching plugins. No wp_ajax_ / wp_ajax_nopriv_ needed: wc-ajax knows on its own whether the user is logged in or not.
Common mistakes when implementing an AJAX cart
An AJAX cart breaks predictably; almost always, three things are to blame. Here is what to check first.
Conflict with caching plugins. If the mini-cart does not update or updates with a delay, the cache plugin cached the AJAX response. Solution: use the wc-ajax endpoint (it is excluded from the cache automatically) and make sure WP Rocket / LiteSpeed Cache are not minifying the cart's inline JS. In the cache settings, find the "Delay JavaScript" directive and add /wc-ajax= to the exclusions.
The theme does not support WooCommerce fragments. Some themes customize the mini-cart so that the standard WooCommerce selectors stop working. Symptom: AJAX runs, the product is in the cart, but the header counter does not update. Fixed by replacing selectors via the woocommerce_add_to_cart_fragments filter.
Mobile button layout. On touch devices, the click event fires differently than on desktop, sometimes with a 300 ms delay or a double fire. If a product gets added twice on mobile, wrap the handler in a check for the $button.hasClass('disabled') flag, as in the code above.
⁉️🤔 Frequently asked questions
Does the AJAX cart work with variable products?
Yes. Both the Ajax Add to Cart for WooCommerce plugin and the custom code from method 3 handle variable products correctly. The variation is passed via
variation_idin the request body, and WooCommerce will substitute the correct price and attributes. The only condition: all required variation attributes must be selected before clicking the button.
Do I need to clear the cache after enabling the AJAX cart?
Absolutely. Clear the site cache (caching plugin → purge all), the CDN cache if used, and the browser cache. AJAX responses can get cached on the very first request, and the mini-cart will stop updating. On a production site after enabling AJAX, go through a full cycle: add a product → check the counter → open the cart → make sure the product is there.
Can I use the old admin-ajax.php instead of wc-ajax?
Technically, yes, but you should not.
admin-ajax.phprequires two hooks (wp_ajax_for authenticated users andwp_ajax_nopriv_for guests), and caching plugins often block or cache this endpoint.wc-ajaxis the modern WooCommerce standard; it is more reliable and simpler to configure. If you are porting code from an old tutorial that usesadmin-ajax.php, replace it withwc-ajax.
What if the cart counter does not update after an AJAX add?
Most likely, the theme uses non-standard mini-cart markup. WooCommerce updates fragments via selectors registered by the
woocommerce_add_to_cart_fragmentsfilter. Check the theme'sfunctions.phpfor this filter and compare the selectors with the actual mini-cart markup in the browser inspector. If the selectors do not match, fix them in the filter, and the counter will work.
Summary
An AJAX cart is not decoration; it is a direct conversion lever. A minute to install a plugin or an hour for custom code pays off through lower cart abandonment and more completed purchases. Pick the method that fits your needs:
- No time and you need results right now: install Ajax Add to Cart for WooCommerce, activate it, and go test your store.
- You sell only simple products from the shop floor: enable the built-in WooCommerce setting.
- You need full control and reliability on a cached site: go with method 3 using the
wc-ajaxendpoint and nonce check.
If your store runs on a block theme or uses WooCommerce Blocks for the product page, check compatibility: blocks render the "Add to cart" button via React, and standard jQuery handlers may not attach. In such cases, a plugin is more reliable.



