Apply Coupons Programmatically

In this tutorial I am going to show so many different ways and conditions how you can apply coupons in WooCommerce.

But the very first thing you have to keep in mind is that coupons can be applied either to products in the cart or to products in an order.

In Cart

In order to apply a coupon to your cart content, you can use apply_coupon()method of WC_Cart object. There is also add_discount() method but it is deprecated.

$coupon_code = 'blackfrd';
WC()->cart->apply_coupon( $coupon_code );

Sometimes you may check if this coupon is already applied with has_discount(), I can recommend you to do that, because the same coupon is not going to be applied twice but it may prevent an error message to be displayed in some cases.

$coupon_code = 'blackfrd';
if ( ! WC()->cart->has_discount( $coupon_code ) ) {
    WC()->cart->apply_coupon( $coupon_code );
}

Let’s try a ready to use snippet which you can insert to your current theme functions.php file.

/**
 * Apply a Coupon Programmatically
 * 
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#in-cart
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon' );

function misha_apply_coupon() {
	$coupon_code = 'blackfrd';
	if ( WC()->cart->has_discount( $coupon_code ) ) {
		return;
	}
	WC()->cart->apply_coupon( $coupon_code );
}

The result will be:

WooCommerce apply coupon programmatically
By the way I am using StoreFront theme here.

Apply a coupon if there is a specific product in cart

Sometimes when a customer purchases a specific product you may want to provide a specific discount to all the products in the cart automatically. It is also possible to do with the snippet below.

/**
 * Apply a Coupon Programmatically if a Specific Product in Cart 
 *
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#if-specific-product
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon_if_specific_product' );

function misha_apply_coupon_if_specific_product() {
	$coupon_code = 'blackfrd';
	$product_id = 1234;
	// if product in the cart
	if( in_array( $product_id, array_column( WC()->cart->get_cart(), 'product_id' ) ) ) {
		if( ! WC()->cart->has_discount( $coupon_code ) ) {
			WC()->cart->apply_coupon( $coupon_code );
		}
	} else { // if product removed from cart we remove the coupon
		WC()->cart->remove_coupon( $coupon_code );
		WC()->cart->calculate_totals();
	}
}

Please check my another tutorial where I uncovered all the different ways how you can check if a product is in the cart.

And yes, do not forget to remove a coupon if the product has been removed from the cart.

Apply a coupon depending on a number of products in the cart

Number of products in the cart can be calculated easy enough, you can use count( WC()->cart->get_cart() ), you can read about it in this tutorial.

By the way, the snippet will be similar to the above one, we just have to change one line of code.

/**
 * Apply a Coupon Depending on a number of Products in the Cart
 *
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#if-number-of-products
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon_if_number_of_products' );

function misha_apply_coupon_if_number_of_products() {
	$coupon_code = 'blackfrd';
	// if there are more than 3 different products in the cart
	if( 3 < count( WC()->cart->get_cart() ) ) {
		if( ! WC()->cart->has_discount( $coupon_code ) ) {
			WC()->cart->apply_coupon( $coupon_code );
		}
	} else {
		WC()->cart->remove_coupon( $coupon_code );
		WC()->cart->calculate_totals();
	}
}

Apply a coupon depending on cart subtotal

/**
 * Apply a Coupon Depending on Cart Subtotal
 *
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#if-cart-subtotal
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon_if_cart_subtotal' );

function misha_apply_coupon_if_cart_subtotal() {
	$coupon_code = 'blackfrd';
	// if cart subtotal is more than 1,000,000
	if( 1000000 < WC()->cart->get_subtotal() ) {
		if( ! WC()->cart->has_discount( $coupon_code ) ) {
			WC()->cart->apply_coupon( $coupon_code );
		}
	} else {
		WC()->cart->remove_coupon( $coupon_code );
		WC()->cart->calculate_totals();
	}
}

Apply a coupon depending on cart weight

/**
 * Apply a Coupon Depending on Cart Weight
 *
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#if-cart-weight
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon_if_cart_weight' );

function misha_apply_coupon_if_cart_weight() {
	$coupon_code = 'blackfrd';
	// if cart content weight is more than 10kg
	if( 10 < WC()->cart->get_cart_contents_weight() ) {
		if( ! WC()->cart->has_discount( $coupon_code ) ) {
			WC()->cart->apply_coupon( $coupon_code );
		}
	} else {
		WC()->cart->remove_coupon( $coupon_code );
		WC()->cart->calculate_totals();
	}
}

Apply a coupon code via URL

Let’s assume, that you would like to add a coupon to cart programmatically when your customer visits a specific URL. For example it could be http://example.com/cart?apply_coupon=couponcode.

The only question here is – would you like apply_coupon parameter to work for any coupon? Or only for specific ones? Let’s make it work for any coupon, ok?

/**
 * Apply a Coupon Programmatically via URL
 *
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/woocommerce/apply-coupon-programmatically.html#apply-coupon-code-via-url
 */
add_action( 'woocommerce_before_cart', 'misha_apply_coupon_by_url' );

function misha_apply_coupon_by_url() {
	
	// if there are no GET-parameter, do nothing
	if( empty( $_GET[ 'apply_coupon' ] ) || ! $_GET[ 'apply_coupon' ] ) {
		return;
	}

	// applying the coupon!
	if( ! WC()->cart->has_discount( $_GET[ 'apply_coupon' ] ) ) {
		WC()->cart->apply_coupon( $_GET[ 'apply_coupon' ] );
	}
}

In Order

Now let’s apply a coupon code for an existing order.

$order = wc_get_order( $order_id );
$order->apply_coupon( 'blackfrd' );

That’s it.

Applying a coupon as an order item

But there is also a difficult way. Not sure why you would need it – maybe it will be more correct in case you’re creating an order programmatically. Anyway, let’s look at it.

Not sure if you know it or not, but coupons are order items. So, we have to get a coupon by its code and then apply it to order as an order item.

$coupon_code = 'blackfrd';

// we need it just to get the coupond discount programmatically
$coupon = new WC_Coupon( $coupon_code );
$discount_total = $coupon->get_amount();

// create and add an order item to an order
$item = new WC_Order_Item_Coupon();
$item->set_props( array( 'code' => $coupon_code, 'discount' => $discount_total ) );
$order = wc_get_order( $order_id );
$order->add_item( $item );
$order->save();

This is the coupon amount we get on line 5.

coupon amount in WooCommerce

Here you should remember that we have different discount types of coupons. My code works great for “Fixed cart discount” but for the other discount types you have to calculate the coupon discount depending on the items in cart.

And this is the result we should get after using this code.

coupon order item is added to order

As you see on the screenshot above, the coupon is added but items subtotal and order total are the same. You think that I have forgotten about $order->calculate_totals()? Ok, add it. Nothing will change, I guarantee. Because this method recalculates the order depending on items subtotal.

So, what are we should do? Yep, our goal is to apply discount manually to every order item. The tricky thing is that we have to share it proportionally. For example, if we have $20 discount and 3 products (Wizard Hat in 2 quantity and T-Shirt in 1 quantity), then we have to share it in $13.34 and $6.66 between products.

$discount_per_item = bcdiv( $discount_total, $order->get_item_count(), 2 );
// Discount remainder (we don't want to forget about 2 cents of discount, right? ;)
$discount_remainder = $discount_total - $discount_per_item * $order->get_item_count();

// loop through product order items
foreach( $order->get_items() as $order_item ){

	$discount = $discount_per_item * $order_item->get_quantity() - $discount_remainder;
	// we are going to add discount remainder only in the first iteration
	$discount_remainder = 0;

	$order_item->set_total( $order_item->get_subtotal() - $discount );
	$order_item->save();

}

$order->calculate_totals();

$order->save();

Here we are. Everything is working.

how to apply coupon to a WooCommerce order programmatically

The are also a couple questions you have to keep in mind:

  • What if a product price is lower than a discount?
  • What are we going to do for different coupon discount types?

More calculations are coming and I am not sure that I should cover everything in this tutorial. Why? Because you can use $order->apply_coupon().

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X