• Rishi Mehta is an PHP architect. His expert knowledge helps many international clients including India to extend the span of their business. If you are impressed with his articles on this blog - approaching him for freelance projects would not be bad deal.

WordPress Woocommerce - AJAX based Add to Cart for Variables

WordPress WooCommerce

If you are familiar with WordPress CMS then you might know about WooCommerce plugin. Well, WooCommerce is an eCommerce plugin that converts your WordPress CMS into dynamic shopping cart. It provides easy to use interface to play with products that you want to sell and earn money online.

I am using WooCommerce from 2 years. In my earlier article - I have written about setting up PayPal for INR in WooCommerce. You should have used WooCommerce to understand this article. Recently one of my project stuck and I will explain the solution that might help other developers too.

The Requirement

Most of eCommerce website has variable products to make an easy buy. But WordPress WooCommerce does not give variable product with AJAX. The project I was working was having all variable products and client wanted add to cart functionality on a single page. Also there should not be a separate product page instead everything should work on shopping page, category page or archive page. It means all variations of products should visible on archive page and we should able to add them to cart using AJAX.

Google Didn't Help

It was easy to show variables on archive page and I had done it within 15-20 minutes. After that real challenge started. I googled for "AJAX based Add to Cart for Variable Products" for couple of days and I found no solution but many tickets need solution for the same. That pushed me to find the solution by my own.

I took 2 hours for adding AJAX based Add to Cart Variable Products functionality.

Solution needs to change WooCommerce default core file, I would not suggest to do so if you are not a developer. Instead you should contact me for better solution.

The Solution

Might below video will guide you on adding variable products to WooCommerce.

First of all we need variable product option selection on archive page. you can add below code in your theme function file.

if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
     function woocommerce_template_loop_add_to_cart() {
         global $product;

         if ($product->product_type == "variable" ) {
         else {
             woocommerce_get_template( 'loop/add-to-cart.php' );

Above code will get option to select variable option on your archive or category page. Means select option button will change with your selected variable drop-down.

Now if you try to add product in cart - current page will reload and you will also get it done successfully (as per WooCommerce default functionality). But with AJAX WooCommerce has not implemented yet.

AJAX means no more page reload in very simple term.

  • You need a JavaScript file to write custom code which manipulate AJAX request
  • I have created a JavaScript file - `add-to-cart-variable.js`

jQuery Changes

Now create a new JavaScript file with below code and save it in your theme's JS directory and include file in your theme footer.

jQuery( function( $ ) {

    // wc_add_to_cart_params is required to continue, ensure the object exists
    if ( typeof wc_add_to_cart_params === 'undefined' )
        return false;

    // Ajax add to cart
    $( document ).on( 'click', '.product_type_variable', function() {
        $variation_form = $( this ).closest( '.variations_form' );
        var var_id = $variation_form.find( 'input[name=variation_id]' ).val();
        var att_grind = $variation_form.find( 'select[name=attribute_grind]' ).val();
        var att_size = $variation_form.find( 'select[name=attribute_size]' ).val();
        // AJAX add to cart request
        var $thisbutton = $( this );

        if ( $thisbutton.is( '.product_type_variable' ) ) {

            if ( ! $thisbutton.attr( 'data-product_id' ) )
                return true;

            $thisbutton.removeClass( 'added' );
            $thisbutton.addClass( 'loading' );

            var data = {
                action: 'woocommerce_add_to_cart_variable_rc',
                product_id: $thisbutton.attr( 'data-product_id' ),
                quantity: $thisbutton.attr( 'data-quantity' ),
                variation_id: var_id,
                variation: { attribute_grind: att_grind, attribute_size: att_size }

            // Trigger event
            $( 'body' ).trigger( 'adding_to_cart', [ $thisbutton, data ] );

            // Ajax action
            $.post( wc_add_to_cart_params.ajax_url, data, function( response ) {

                if ( ! response )

                var this_page = window.location.toString();

                this_page = this_page.replace( 'add-to-cart', 'added-to-cart' );

                if ( response.error && response.product_url ) {
                    window.location = response.product_url;

                // Redirect to cart option
                if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {

                    window.location = wc_add_to_cart_params.cart_url;

                } else {

                    $thisbutton.removeClass( 'loading' );

                    fragments = response.fragments;
                    cart_hash = response.cart_hash;

                    // Block fragments class
                    if ( fragments ) {
                        $.each( fragments, function( key, value ) {
                            $( key ).addClass( 'updating' );

                    // Block widgets and fragments
                    $( '.shop_table.cart, .updating, .cart_totals' ).fadeTo( '400', '0.6' ).block({ message: null, overlayCSS: { background: 'transparent url(' + wc_add_to_cart_params.ajax_loader_url + ') no-repeat center', backgroundSize: '16px 16px', opacity: 0.6 } } );

                    // Changes button classes
                    $thisbutton.addClass( 'added' );

                    // View cart text
                    if ( ! wc_add_to_cart_params.is_cart && $thisbutton.parent().find( '.added_to_cart' ).size() === 0 ) {
                        $thisbutton.after( ' <a class="added_to_cart wc-forward" title="' + wc_add_to_cart_params.i18n_view_cart + '" href="' + wc_add_to_cart_params.cart_url + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );

                    // Replace fragments
                    if ( fragments ) {
                        $.each( fragments, function( key, value ) {
                            $( key ).replaceWith( value );

                    // Unblock
                    $( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();

                    // Cart page elements
                    $( '.shop_table.cart' ).load( this_page + ' .shop_table.cart:eq(0) > *', function() {

                        $( 'div.quantity:not(.buttons_added), td.quantity:not(.buttons_added)' ).addClass( 'buttons_added' ).append( '<input id="add1" class="plus" type="button" value="+" />' ).prepend( '<input id="minus1" class="minus" type="button" value="-" />' );

                        $( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();

                        $( 'body' ).trigger( 'cart_page_refreshed' );

                    $( '.cart_totals' ).load( this_page + ' .cart_totals:eq(0) > *', function() {
                        $( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();

                    // Trigger event so themes can refresh other areas
                    $( 'body' ).trigger( 'added_to_cart', [ fragments, cart_hash ] );

            return false;


        return true;


Now in above code there is lots of thing you need to change according to your template and your product variations.

  1. Make sure your variable products' add to cart button have a class `product_type_variable`.
  2. If you check into code there is a `var` declaration. In that list you need to declare your own products' variables name like in my example variation name is grind and size. you can add or change so.
  3. In data array, you need to update your "variation" values according to your variations. It will be same as below. Just replace grind and size with your variation.
    var att_variation_name = $variation_form.find( 'select[name=attribute_variation_name]' ).val();
    // Like in above code we have a variation size it will be convert to below //
    var att_size = $variation_form.find( 'select[name=attribute_size]' ).val();

That's it you are done with jQuery changes. Now if you try to add variable product in cart, AJAX will work and loading icon will come.

Also it will show product added to cart text and view cart button but it's not all! If you check shopping cart after above code change, product will not be added in and you will find empty cart.

WooCommerce Core File Changes

Now it's time when you need to make change in WooCommerce's file which handles AJAX request.

Go to WordPress - WooCommerce plugin directory -> Includes and open file named class-wc-ajax.php. Open the file in some code-editor. Go to line no 29. it's having code below code.

'add_to_cart' => true,
'checkout'    => true,

Add below code in between this 2 line. so it will be below code

'add_to_cart' => true,
'add_to_cart_variable_rc' => true,
'checkout'     => true,

Basically we declare new ajax function for variable product. Now we need to add code of that function in same file. To do so go to line no - 273. At this line Add to Cart AJAX function is being completed. We will add - add to cart AJAX code for variable product now.

Please start adding below code from line no 274.

public function add_to_cart_variable_rc() {
    $product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
    $quantity = empty( $_POST['quantity'] ) ? 1 : apply_filters( 'woocommerce_stock_amount', $_POST['quantity'] );
    $variation_id = $_POST['variation_id'];
    $variation  = $_POST['variation'];
    $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

    if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation  ) ) {
        do_action( 'woocommerce_ajax_added_to_cart', $product_id );
        if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
        wc_add_to_cart_message( $product_id );

        // Return fragments
    } else {

        // If there was an error adding to the cart, redirect to the product page to show any errors
    $data = array(
        'error' => true,
        'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id )
    echo json_encode( $data );

Above code will take request of our jQuery add_to_cart_variable.js and post it to default add to cart function of WooCommerce. Now we have to see that how our custom JavaScript will send data to our function. So if you look into our JS, the action is declared in Data array. It is a function name which we declare in our class-wc-ajax.php file.

I am done with everything. Please try to implement this code in your WooCommerce project and tel me your experience. If you have something in addition to - you can put a comment.

  • Thomas

    Huh, I try fix this problem but no luck.

    class="variations_form cart" method="post"
    enctype='multipart/form-data' data-product_id="ID; ?>" data-product_variations="">

    $options ) : $loop++; ?>

    <label for="">

    <select id="" name="attribute_">

    'name', 'hide_empty' => false, 'menu_order' => false );
    case 'id' :

    $args = array( 'orderby'
    => 'id', 'order' => 'ASC', 'menu_order' => false, 'hide_empty'
    => false );
    case 'menu_order' :
    $args = array( 'menu_order' => 'ASC', 'hide_empty' => false );

    $terms = get_terms( $name, $args );

    foreach ( $terms as $term ) {
    if ( ! in_array( $term->slug, $options ) )

    echo 'slug ) . '" ' . selected( sanitize_title(
    $selected_value ), sanitize_title( $term->slug ), false ) . '>' .
    apply_filters( 'woocommerce_variation_option_name', $term->name ) .
    } else {

    foreach ( $options as $option ) {

    echo '' .
    esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) )
    . '';

    //if ( sizeof( $attributes ) == $loop )

    //echo '' . __( 'Clear selection', 'woocommerce' ) .

    single_add_to_cart_text(); ?>

    <input type="hidden" name="add-to-cart" value="id; ?>" />
    <input type="hidden" name="product_id" value="ID ); ?>" />

    Could you please check where the missing file in variable.php that still reload page.

    • Hi Thomas,

      I am not sure with Variation.php file in template. I just use default one with my own classes. also I check your code its missing all add_action code from default variation.php file. Please check on that. also did you included add-to-cart-variable.js file as per steps. you need to add this js file in your template footer.

      Let me know if it helps.

  • zero

    Hi, this may be out of topic but i am in need of help. Do you know how do we call the ajax to work in the checkout page order_review?

    I have created some radio button for my users to select such that with each option selected they will be given a additional gift (another product) at a minimal fee. Have somehow managed to create a button that allow the adding of the gift to the cart, but the order review will not review until i reload the page or change the shipping methods.

    Really hope you can help me out. Thanks!

    • Hi, Let me know URL first. i will look into it and let you know if its possible or not. First if you get it added on cart by ajax, you only need to add that data to checkout page order details table via ajax from similar function.

      • zero

        Hi Rishi, thanks for the reply.

        My files are on a localhost, so i wont be able to give you a link. However, the code that i am adding is

        jQuery("#gift-cards_field input").on("change", function () {
        if (jQuery("input[name='gift-cards']:checked").val() !== "None") {
        return false;
        } else {
        $id = $_POST['1410'];
        $cart_id = $cart->generate_cart_id($id);
        $cart_item_id = $cart->find_product_in_cart($cart_id);

        function addToCart(v_id,v_name) {
        jQuery.post("http://localhost/nomnom/checkout/?add-to-cart=1409&variation_id="+v_id+"&attribute_card-type="+v_name, function () {
        // i managed to find how to do it by using the code below. however, there is a lag time between clicking on the radio button and the order review updating via ajax



        • Hi,

          This code only work add product into cart and will not update cart instantly. I understand your requirement and to achieve this you need to do minor modification in js i written above.

          1) $( document ).on( 'click', '.product_type_variable', function() { - Needs to change jQuery("#gift-cards_field input").on("change", function () {

          2) Remove code from line 10 to 17. means in between function start and if condition.

          3) Replace if condition code with yours if condition - if ( $thisbutton.is( '.product_type_variable' ) ) { change it to if (jQuery("input[name='gift-cards']:checked").val() !== "None") {

          4) Remove second if condition code - if ( ! $thisbutton.attr( 'data-product_id' ) ) return true;

          5) Now in data variable replace value with your products actual values and also change function to woocommerce_add_to_cart. After changes your code will look like something below. If you have variation_id and variation to add, replace their code too.

          var data = {
          action: 'woocommerce_add_to_cart',
          product_id: '1410',
          quantity: '1',
          variation_id: var_id,
          variation: { attribute_grind: att_grind, attribute_size: att_size }

          That's it, other all js script remains same. it will add product to cart and also update cart table instantly with ajax.

          Let me know if its works or not, send me url after you upload. 🙂

  • Hey, this code is great! I got it working after a few small changes but I'm getting one major bug!

    When I'm logged in everything works great, but when I'm logged out on a fresh browser nothing is being added to cart.

    If I temporarily break the add-to-cart-variable.js file to put an item into the cart without AJAX and then I re-upload the working JS file I can then add to cart with AJAX as a guest. So only after getting one item into the cart I can continue to add with AJAX as a logged out user.

    It is a very strange. I have replicated this my main site and on a new testing server with all fresh up to date installs and very little extra plugins.

    Attached is an image of the add-to-cart-variable.js that I have adjusted and the class-wc-ajax.php I have adjusted. Changes are marked in red.

    It would be great to nail this out for everyone else attempting this too.

    Hope to hear from you soon! Thanks Rishi

    • Hi Upper Thanks for the update code. I already created wordpress plugin for same and its having most of the things which needed. you can download plugin from :


      Check out plugin and if its having issue or you want to contribute, add things in wordpress sytem. so i can track changes and everything from my side.

      • Thank you! Awesome work. I just updated to the plugin version. I am currently working on getting it to work with the Bulk Variation forms plugin on an archive page. I will let you know when we get it running. Thanks again!

  • Rubio

    does this work on a single produt page?

  • Ruben Kuipers

    Hi Rishi,

    Thanks for coming up with the wordpress plugin. It works great on the single pages and archive pages. But on my homepage (front-page.php), I am loading a single product like this:

    But on adding the product to my shopping cart, It keeps refreshing the page. Any idea how that is possible?

    Thanks in advance!

  • In woocommerce i have product details page. on that product details page i have one button.on that button click i want to save the product details to database so i am not getting how to do that in woocommerce.so please can you help me for that

  • Brad Bush

    Nice post about WooCommerce. I would like to share one recently launched Woo-commerce Plugins named WC Checkout Fields Editor. It has features as,
    ~ Supports 11 custom fields
    ~ Edit existing fields(Billing/Shipping) support
    ~ Remove fields & Change display field order
    ~ Product specific field visibility
    ~ Category specific field visibility
    ~ File upload custom field in additional settings and much more...

  • chamika

    If we change woocommerce core file class-wc-ajax.php when there is any update the code will removed. what can i do for that?

  • Pingback: WordPress Woocommerce – AJAX based Add to Cart for Variables | Yogee Ideas()

  • Rafał Rostkowski


    Thanks for plugin! Unfortunately, it has a conflict with Woocommerce Addons plugin. After adding to cart only selected variation is displayed - addon not. Do you how to solve this problem?