Creating a custom woocommerce Coupon

Sometimes we need to create a coupon, and program it to only work under certain conditions.

To do this, we need to follow a few steps:

  • Create the coupon
  • Hook into the coupon validation process to make woocommerce check our code logic to see if the coupon is valid or not. In our example, we will make the coupon only valid if the user has been registered on the site for less than 7 days.
  • Create a custom error message if the coupon is not valid and hook that in.

First, we create the coupon as normal. We will use the coupon code to identify the coupon in our code. For the purposes of the code below, we’ll use the coupon CUSTOM20 .

Now we need to add some code to check the validity of the coupon against our spec. So we need to hook into the woocommerce woocommerce_coupon_is_valid filter. Woocommerce filters the validity of a coupon through various filters, but we’ll use this one as it is the last, and most generic one.

You can add the following code to a plugin or your functions.php file in your theme.


function plugin_coupon_validation($result,$coupon) {
 if( 'custom20' === strtolower($coupon->code) ) {
 return plugin_is_user_new();
 return true; 

So we’ve created a function called plugin_coupon_validation which will receive 2 parameters:

$result is always true (as there’s no point checking for validity if we already know it’s not).

$coupon is the interesting one. Woo generously gives us the whole coupon object.

The first thing we need to do is determine which coupon is being used. We should assume there will be other coupons on the system, so we can check this is the right coupon using $coupon->code property.

 if( 'custom20' === strtolower($coupon->code) ) {
 return plugin_is_user_new();

We can add other coupon codes here in the future if we need to.

For now, we need to check this coupon, so we’ll call and return the response from plugin_is_user_new().

function plugin_is_user_new() {
 // get date object of the time the user registered
 $user_id = get_current_user_id();
 $udata = get_userdata( $user_id);

$registered_date = new DateTime($udata->user_registered);
 // calculate the date 20 days ago
 $twenty_days_ago = new DateTime("-20 days");
 // compare (return true if registered after 20 days ago)
 return ($registered_date > $twenty_days_ago);

That will be enough to make the coupon conditional to our function, but it will display a very generic message if the coupon is not valid. That’s no good, so we need to add some code to change this:


function plugin_coupon_error_message($err,$err_code,$coupon) {
  if( 'custom20' === strtolower($coupon->code) && intval($err_code) === WC_COUPON::E_WC_COUPON_INVALID_FILTERED ) {
    return __("Sorry, this coupon is valid only for users who have been registered for less than 20 days.");

 return $err;

In the code above, we use the woocommerce_coupon_error filter to change the message, under 2 conditions:

  • We need to check the coupon code (otherwise it will affect other coupons)
  • We also need to check that this is the default generic “Coupon is not valid” message. Otherwise, it may interfere with other woocommerce messages. For example, if a customer has already applied the coupon, they will get the message saying their coupon is already applied. We don’t want to confuse anyone. I’m using the woocommerce constant E_WC_COUPON_INVALID_FILTERED
    (which has a value of 100)

After that, our work is done. We have a coupon that only works if our code is validated, and returns a custom error message in case it is not.

4 comments on “Creating a custom woocommerce CouponAdd yours →

  1. Thanks for the example. I needed to setup a coupon that is only valid when the shipping method is set to local pickup. I had no idea how to begin until I ran across your script. With some trail and error… well mostly error 🙂 … I made it work, well sort of. If the shipping method is changed after the coupon is added things get a little weird, so I am not completely finished yet, but I’m much closer then I was a few hours ago, so thank you!!! You totally made my day! I just need to figure out how to remove the coupon when the shipping method changes and I’m golden.

  2. Hi, Callum! Thank you so much for your article! This is very useful information. Waiting for new articles about customization woocommerce.

  3. This is my code that I have seen here in this tutorial and I havealmost implemented the same just changed some necessary things. When I am adding coupon it’s saying not valid. Please let me know what is the issue?

    add_action( ‘woocommerce_before_cart’, ‘sh_coupons_matched’ );
    function sh_coupons_matched() {
    global $woocommerce;
    $sh_coupon = ‘OnlineShop’;
    if ( $woocommerce->cart->has_discount( $sh_coupon ) ) return;
    foreach ( $woocommerce->cart->cart_contents as $key => $values ) {
    $autocoupon = array( 65 );
    if( in_array( $values[‘product_id’], $autocoupon ) ) {
    $woocommerce->cart->add_discount( $cw_coupon );

    1. Hi Alvina. You are adding a coupon from the variable called ‘$cw_coupon’ but I do not see where that is initialised in your code. I assume it should be $sh_coupon?

Leave a Reply

Your email address will not be published. Required fields are marked *