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:

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.

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.

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.

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
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
Saved me so much time, great posts as always.
This:
$order->apply_coupon( 'blackfrd' );
took me a day to find, couldn’t find it anywhere in the docs! Thank you!Hey Misha, I think your explanation and code snippet examples are the BEST and easiest to understand. BIG thank you!
Can I please ask you for help to improve the code snippet “Apply a coupon if there is a specific product in cart.”
I’m offering free shipping coupon for product category A, B and C only. But NO free shipping for categories D and E.
Do you know how to:
IF cart has products from categories A, B, C, D, and E
1) APPLY coupon ONLY to products from category A, B and C
2) Calculate shipping for products from categories D and E
If this is too hard or not possible, then remove coupon when the cart has products from categories D and E.
BIG thank you, Misha.