WordPress
Article

WooCommerce Actions and Filters to Manipulate the Cart

By Yojance Rabelo

Welcome to the second article in the series on Mastering WooCommerce Actions and Filters. In the previous article, even though it was very basic, we covered handling a customer’s billing and shipping address as well as what happens when a customer registers through WooCommerce and it sends them to a third party website, like Salesforce.

In this second article, we will manipulate the cart in some clever ways with real world scenarios you may encounter while creating your eCommerce website using WooCommerce.

Adding a Product to the Cart Programatically

Adding a product to the cart programatically only takes one line of code. The only brainstorming you’ll be doing is deciding when or why you’ll want to do it. We’ll talk more about this later in the third part of this article, when we work on our real world scenario.

All it takes to add a product to the cart is the following:

<?php
// Takes the Product ID and the Quantity
WC()->cart->add_to_cart( 73, 1 );

As a note of caution, make sure you don’t run this on an action that runs on every page, like the template_redirect action or you’ll be adding one of these products to the cart every page load or you reloads. Avoid doing this whenever possible:

<?php
// template_redirect runs once for every page so you'll be
// increasing the quantity by one on every page load
add_action( 'template_redirect', 'add_random_product' );
function add_random_product() {
    WC()->cart->add_to_cart( 73, 1 );
}

Removing a Product from the Cart Programatically

I’ve seen this question being asked an infinite number of times in various forums and websites with very little answers. Hopefully this will help you the next time you want to remove a product from the cart and again, the only brainstorming you’ll be doing is when or why you would want to remove a product from the cart. The following code will prevent anyone from checking out with a product from your store. I don’t know why you would want to do something like that but it will demonstrate the steps for removing the product from the cart which is not as simple as the previous example when we added the product to the cart.

<?php
add_action( 'template_redirect', 'remove_product_from_cart' );
function remove_product_from_cart() {
    // Run only in the Cart or Checkout Page
    if( is_cart() || is_checkout() ) {
        // Set the product ID to remove
        $prod_to_remove = 56;

        // Cycle through each product in the cart
        foreach( WC()->cart->cart_contents as $prod_in_cart ) {
            // Get the Variation or Product ID
            $prod_id = ( isset( $prod_in_cart['variation_id'] ) && $prod_in_cart['variation_id'] != 0 ) ? $prod_in_cart['variation_id'] : $prod_in_cart['product_id'];

            // Check to see if IDs match
            if( $prod_to_remove == $prod_id ) {
                // Get it's unique ID within the Cart
                $prod_unique_id = WC()->cart->generate_cart_id( $prod_id );
                // Remove it from the cart by un-setting it
                unset( WC()->cart->cart_contents[$prod_unique_id] );
            }
        }

    }
}

Emptying the Cart Programatically

To better illustrate how to empty the cart programatically, let’s add a button to the cart which would allow customers to click on it and clear their cart.

WooCommerce empty cart button

Let’s use the woocommerce_proceed_to_checkout action an echo our very own ‘Submit’ button which will clear the cart for the current customer.

<?php
add_action( 'woocommerce_proceed_to_checkout', 'insert_empty_cart_button' );
function insert_empty_cart_button() {
    // Echo our Empty Cart button
    echo '<input type="submit" class="button" name="empty_cart" value="Empty Cart" />';
}

The next step is to listen for the button to be clicked so that when it is clicked, we clear the cart. For that, we are going to hook into the template_redirect action.

<?php
// Let's wait for the button to be clicked on
add_action( 'template_redirect', 'empty_cart_button_handler' );
function empty_cart_button_handler() {
    if( isset( $_POST['empty_cart'] ) && $_SERVER['REQUEST_METHOD'] == "POST" ) {
        WC()->cart->empty_cart( true );
    }
}

You’ll notice now that after pressing the button, the cart-empty.php is displayed instead of the regular template.

WooCommerce emptied cart

Now that we’ve established how to add or remove a product from the cart, even emptying the cart completely, let’s move on to building our real world scenario where knowing this kind of stuff makes a big difference.

Incentive Products

In our real world scenario, we’re going to put all of this to work by building a system where you could give away a product as an incentive to all of your customers. Well, not exactly to all of your customers, just those who qualify based on a specific requirement.

The Problem

We need to be able to give out a product of your choice as an incentive to your customers.

The Solution

Build a system which will allow you to give away your incentive product based on the following:

  • Having a specific product in the cart

  • Having a minimum total amount for your order

  • Having a minimum weight in your cart

  • Having a product from a specific category

Because we are going to be building this the right way, not only will you be able to give away the product for customer qualifying to one of these criteria, but you’ll also be able to mix these up and really narrow down who gets the product and who doesn’t.

Not only will you be able to offer your customers the incentive product by qualifying to one of those criteria, you’ll have the power to combine them. In order words, for example, you’ll be able to test for someone having at least $100 total in their cart and a product from the ‘Clothing’ category.

Let’s take a quick look at the functions we’ll be writing in a minute and what each does in our problem/solution scenario.

  • get_id_from_product( $product, $check_variations = true ) – Gets the product ID and returns it. Takes variation IDs into account so we check for these before checking for the actual Product ID.

  • qualifies_basedon_specific_product( $product_required ) – Checks whether or not a customer qualifies for the incentive by having the specified product ID as one of the items in the cart.

  • qualifies_basedon_weight( $weight_required ) – Checks whether or not a customer qualifies for the incentive by having a minimum weight in the cart.

  • qualifies_basedon_cart_total( $total_required ) – Checks whether or not the customer qualifies for the incentive by having a minimum total amount before taxes are calculated.

  • qualifies_basedon_product_category( $category ) – Checks whether or not the customer qualifies for the incentive by having a product from a certain category in the cart.

  • add_incentive_to_cart( $product_id ) – Adds the incentive product to the cart if the customer qualified for it

  • remove_incentive_from_cart( $product_id ) – Removes the incentive product to the cart if the customer failed to qualify for the product.

  • qualifies_for_incentive() – This is where the magic will happen because it will have the rules that need to be matched in order for the customer to qualify for the incentive. This function will handle the logic for our incentive program.

<?php
/**
 * Will extract the Variation ID if available otherwise it will get the Product ID
 * @param $product Product
 * @param bool $check_variations Whether or not to check for variation IDs
 * @return mixed
 */
function get_id_from_product( $product, $check_variations = true ) {
    // Are we taking variations into account?
    if( $check_variations ) {
        // Ternary Operator
        // http://php.net/manual/en/language.operators.comparison.php
        return ( isset( $product['variation_id'] )
            && ! empty( $product['variation_id'])
            && $product['variation_id'] != 0 )
            ? $product['variation_id']
            : $product['product_id'];
    } else {
        // No variations, just need the product IDs
        return $product['product_id'];
    }
}

/**
 * Checks the existence of a specific product in the cart
 * @param $product_required The Product ID required to be in the cart
 * @return bool
 */
function qualifies_basedon_specific_product( $product_required ) {
    /*
     * We only want to run this on the cart or checkout page
     */
    if( is_cart() || is_checkout () ) {
        foreach( WC()->cart->cart_contents as $key => $product_in_cart ) {
            if( $product_required == get_id_from_product( $product_in_cart ) ) {
                return true;
            }
        }
        // Return false in case anything fails
        return false;
    }
}

/**
 * Checks the cart for the weight required to qualify for the incentive
 * @param $weight_required Weight Required
 * @return bool
 */
function qualifies_basedon_weight( $weight_required ) {

    /*
     * We only want to run this on the cart or checkout page
     */
    if( is_cart() || is_checkout () ) {
        if( $weight_required >= WC()->cart->cart_contents_weight ) {
            return true;
        }
    }
    // Return false in case anything fails
    return false;
}

/**
 * Checks the cart for the Total excluding taxes
 * @param $total_required
 * @return bool
 */
function qualifies_basedon_cart_total( $total_required ) {
    /*
     * We only want to run this on the cart or checkout page
     */
    if( is_cart() || is_checkout () ) {
        if( WC()->cart->subtotal_ex_tax >= $total_required ) {
            return true;
        }
    }
    // Return false in case anything fails
    return false;
}

/**
 * Checks the cart to verify whether or not a product from a Category is in the cart
 * @param $category Accepts the Product Category Name, ID, Slug or array of them
 * @return bool
 */
function qualifies_basedon_product_category( $category ) {
    foreach( WC()->cart->cart_contents as $key => $product_in_cart ) {
        if( has_term( $category, 'product_cat', get_id_from_product( $product_in_cart, false ) ) ) {
            return true;
        }
    }
    // Return false in case anything fails
    return false;
}

/**
 * Adds a specific product to the cart
 * @param $product_id Product to be added to the cart
 */
function add_incentive_to_cart( $product_id ) {
    // Check the cart for this product
    $cart_id = WC()->cart->generate_cart_id( $product_id );
    $prod_in_cart = WC()->cart->find_product_in_cart( $cart_id );
    // Add the product only if it's not in the cart already
    if( ! $prod_in_cart ) {
        WC()->cart->add_to_cart( $product_id );
    }
}

/**
 * Removes a specific product from the cart
 * @param $product_id Product ID to be removed from the cart
 */
function remove_incentive_from_cart( $product_id ) {
     $prod_unique_id = WC()->cart->generate_cart_id( $product_id );
    // Remove it from the cart by un-setting it
    unset( WC()->cart->cart_contents[$prod_unique_id] );
}

As you can see, these functions return ‘True’ or ‘False’ so it’s going to make it really easy for us to mix it up and create an incentive program that is really flexible. What’s left to do now is come up with the rules you want to set for your customers to qualify for the incentive product and write the qualifies_for_incentive() function which will be tied to the woocommerce_check_cart_items WooCommerce action.

<?php
/**
 * Checks whether or not the customer qualifies for the incentive
 */
add_action( 'woocommerce_check_cart_items', 'qualifies_for_incentive' );
function qualifies_for_incentive() {
}

Below are some examples of how you can use these functions to create something really unique.

Only One Requirement

Here are a few examples setting only one requirement.

Specific Product Existing in the Cart
<?php
// Specific product existing in the cart
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_specific_product( 70 ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}
Minimum Weight of All the Products in the Cart
<?php
// Minimum weight of all the products in the cart
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_weight( 10 ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}
Cart’s Total Excluding Taxes
<?php
// Cart's Total Excluding Taxes
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_cart_total( 199 ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}
Product from a Category in the Cart
<?php
// Product From A Category In The Cart
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_product_category( 'premium-quality' ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}

Mixing It up

Since we have a very flexible codebase, you can mix it up and truly make your incentive program unique. Below are some more examples showing how easy it is to add more conditions as necessary.

Product from a Category in the Cart or Minimum Cart Total
<?php
// Product From A Category In The Cart OR Minimum Cart Total
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_product_category( 'premium-quality' )
        || qualifies_basedon_cart_total( 199 ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}
Product from a Category and Minimum Cart Total
<?php
// Product From A Category AND Minimum Cart Total
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 102;

    if( qualifies_basedon_product_category( 'premium-quality' )
        && qualifies_basedon_cart_total( 199 ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } else {
        remove_incentive_from_cart( $incentive_product_id );
    }
}

You can even get more advanced than that and create more complex scenarios. The next step for you would be to turn this into a ‘Class’ so that you can have more than one incentive program, each with it’s own unique set of rules for qualifying.

That’s it for this article. In the third part of this series we will be working with actions and filters that run on the New Product/Edit Product screens. We’ll then explore how to add custom fields to the ‘Product Screens’ using nothing but the API.

Comments
Danielle

Hi there,
I want to say thank you so much for posting this! I feel I've been looking everywhere for this explanation as I am trying to add a specific product to a cart if the cart contains items from a certain category.
I have tried pasting the code into my theme's function.php file, but with no luck so far. I think I am missing some fundamental step...like how to add the parameters for the category required and the product id that will be added to the cart.
I am trying to check the cart for any items from category ID= 21, then if any items in the cart are from that category, add product ID= 506

I think I am missing something here, because I plut the code into the theme-functions file, then when I try to test, I can't actually see what's in my cart on the cart or checkout page anymore. The last line of the source code for the page says <div="woocommerce"> then it's blank with no content or footer or anything.

Any ideas where I am going wrong? I really need to get this working asap, and this is the closest thing I have found that may (hopefully) work!

Thank you so, so much for your time!!

Danielle

Danielle

Just to be clear, this is the code as it appears in my theme functions file:

    /**
 * Checks the cart to verify whether or not a product from a Category is in the cart
 * @param $category Accepts the Product Category Name, ID, Slug or array of them
 * @return bool
 */
function qualifies_basedon_product_category( $category ) {
    foreach( WC()->cart->cart_contents as $key => $product_in_cart ) {
        if( has_term( $category, 'fee', get_id_from_product( $product_in_cart, false ) ) ) {
            return true;
        }
    }
    // Return false in case anything fails
    return false;
}
 
/**
 * Adds a specific product to the cart
 * @param $product_id Product to be added to the cart
 */
function add_incentive_to_cart( $product_id ) {
    // Check the cart for this product
    $cart_id = WC()->cart->generate_cart_id( $product_id );
    $prod_in_cart = WC()->cart->find_product_in_cart( $cart_id );
    // Add the product only if it's not in the cart already
    if( ! $prod_in_cart ) {
        WC()->cart->add_to_cart( $product_id );
    }
}
 


add_action( 'woocommerce_check_cart_items', 'qualifies_for_incentive' );
function qualifies_for_incentive() {
    // Incentive product we are giving away
    $incentive_product_id = 506;
 
    if( qualifies_basedon_product_category( 'fee' ) ) {
        add_incentive_to_cart( $incentive_product_id );
    } 
}

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Instant Website Review

Use Woorank to analyze and optimize your website to improve your website to improve your ranking!

Run a review to see how your site can improve across 70+ metrics!

Get the latest in WordPress, once a week, for free.