Exclude products from coupon codes automatically

Recently one of my regular clients, TULA, started supporting e-gift cards on their Wordpress WooCommerce website. The problem was, they regularly run discount coupon codes on the site, and didn't want those coupon codes to be included on their e-gift cards (otherwise, they're basically just giving money away!).

Although on the surface this is a straightforward situation, the solution to fix it is somewhat more complicated. Here's how it was solved:

#include the woo toolkit
if ( ! function_exists( 'woothemes_queue_update' ) )
require_once( 'woo-includes/woo-functions.php' );

#check if woocommerce is active
if ( is_woocommerce_active() ) {

#class tula
class tula{

#on class load set the following actions
function __construct(){

#add filter to check if the product is valid
add_filter('woocommerce_coupon_is_valid_for_product', array($this,'is_coupon_valid'),100,4);
add_filter('woocommerce_coupon_get_discount_amount', array($this,'coupon_amount'),100,5);

#comma seperate product ids for products that are not discountable globally
$this->ignore_products = array(18950, 14488, 14484);

#comma seperate category IDs that you want to exclude from coupons globally
$this->ignore_categories = array();

#filter function to check if product is valid
function list_terms($product_id){
$cats = array();
$terms = get_the_terms($product_id, 'product_cat' );

if($terms != false){
foreach($terms as $term){
$cats[] = $term->term_id;

return $cats;

#check if term exists in ignore list
function cat_exists($cats){
$exists = false;
foreach($cats as $cat){
if(in_array($cat, $this->ignore_categories ) ){
$exists = true;

return $exists;

function is_coupon_valid($valid, $product, $coupon, $values ){

if(in_array($product->id,$this->ignore_products ) || $this->cat_exists($this->list_terms($product->id)) == true ){

$valid = false;
return $valid;

#set the discount to 0 if the product id is in the exclusion list
function coupon_amount($discount, $discounting_amount, $cart_item, $single, $coupon ){
if(in_array($cart_item['product_id'],$this->ignore_products ) || $this->cat_exists($this->list_terms($cart_item['product_id'])) == true ){

$discount = 0;
return $discount;

#initiate the class
new tula;

The code is commented directly to help explain it, but the key area is:

$this->ignore_products = array(18950, 14488, 14484);
$this->ignore_categories = array();

This creates an array of product IDs to ignore.  If you have multiple product IDs you want to exclude, simply add them with a comma after each. There is also some code to exclude whole categories if you wanted to, by using the category ID in the ignore_categories array.

Special thanks to Anthony for assistance with this one!

Russ Clow

Freelance Website Designer & Developer


I've been designing and developing websites for a very long time. In that time, I've learnt many things - and this article is written to help share that knowledge with others. Everything within this article is written based on my experience, but is my own professional view.

If you would like to tap into my knowledge further, please contact me for a free, no obligation quote.

Need a quote?  Contact me