Most of the time when you set up products in WooCommerce you just enter the product price and you’re done with it. And chances are if you have a situation where you’re offering discounts, you already have a membership plugin or something else that’s taking care of that for you.

But every now and then you might need to adjust a price in some way that’s not covered by any other handy extension or WooCommerce add-on.

Fortunately for you, there’s a filter for that: woocommerce_get_price. Using this filter we can adjust the price for any special circumstance that may arise.

For example, let’s say you want to sell a product to customers who meet some special criteria — maybe they previously bought sunglasses on your site and now they qualify for a lifetime 5% discount. Whatever.

You’ll have to write your own function for whatever special conditions apply to your situation. Whatever function you write needs to return simply true or false. (Either the condition applies or it doesn’t.) In our case, let’s say we’ve written a function called check_previously_bought_sunglasses(), to check for a previous sunglasses purchase. Once you get that far, you just run it through the filter:

add_filter( 'woocommerce_get_price', 'adjust_lifetime_discount_price' );
function adjust_lifetime_discount_price( $price ) {
    return check_previously_bought_sunglasses() ? $price * 0.95 : $price;
}

But wait! What if you only want to offer the discount on sunscreen? We can handle that. Because fortunately, the filter will also pass us the current product information if we want it. All we need to know is which product ID qualifies for the discount. Say the sunscreen’s product ID is 538. Then:

add_filter( 'woocommerce_get_price', 'adjust_lifetime_sunscreen_price' );
function adjust_lifetime_sunscreen_price( $price, $product ) {
    if ( 538 !== $product->id ) return $price; // not the right product, bail!

    return check_previously_bought_sunglasses() ? $price * 0.95 : $price;
}

One last thought.

If you have other plugins or extensions that are also altering the price according to other criteria, you may have to adjust the priority of your call to add_filter to make sure your discount gets applied in the right order. So if the discount is in addition to any other discounts, you’ll want to make sure it’s set to run after those. Or, if you’re adjusting a product’s base price and you want other discounts to apply to it, give it an early priority.