Skip to content

Hooks for Discount Calculation

Filters for modifying discount calculation and price rounding.

Each rule can have a calculation_base_mode setting that determines which price the discount is calculated from:

ValueConstantDescription
current_priceCalculationBaseModes::CURRENT_PRICEDiscount from current price (after previous discounts) - default
original_priceCalculationBaseModes::ORIGINAL_PRICEDiscount always from regular price (regular_price)
Product: regular_price = $100
Rule 1 (Product): -20% → price = $80
Rule 2 (BOGO): -50%
With calculation_base_mode = 'current_price':
→ 50% of 80 = $40 (discounts stack)
With calculation_base_mode = 'original_price':
→ 50% of 100 = $50 (discount from original price)
use WpifyWooDiscountRule\Services\Rules;
use WpifyWooDiscountRule\Enums\CalculationBaseModes;
// Within a rule
$calc_base_mode = $rule[ Rules::CALCULATION_BASE_MODE ] ?? CalculationBaseModes::CURRENT_PRICE;
if ( CalculationBaseModes::ORIGINAL_PRICE === $calc_base_mode ) {
// Use regular_price
$base = $product->get_regular_price();
} else {
// Use current price (may include other discounts)
$base = $product->get_price();
}

Modifying Data Before Discount Calculation

Section titled “Modifying Data Before Discount Calculation”

This filter allows you to modify data before the actual discount calculation.

apply_filters( 'wpify_woo_discounts_calculate_data', $data, $product, $rule, $range );
ParameterTypeDescription
$dataarrayData for discount calculation (original_price, calculation_base, discount_type, discount_value)
$productWC_ProductProduct the discount is applied to
$rulearrayRule settings (including calculation_base_mode)
$rangearrayCurrent discount range/tier

Adjusting Discount for a Specific Category

Section titled “Adjusting Discount for a Specific Category”
/**
* Increase discount for products in the "sale" category
*
* @param array $data Calculation data
* @param WC_Product $product Product
* @param array $rule Rule
* @param array $range Discount range
*
* @return array
*/
function boost_discount_for_sale_category( $data, $product, $rule, $range ): array {
if ( has_term( 'akce', 'product_cat', $product->get_id() ) ) {
// Increase percentage discount by 5%
if ( $data['discount_type'] === 'percentage' && isset( $data['discount_value'] ) ) {
$data['discount_value'] += 5;
}
}
return $data;
}
add_filter( 'wpify_woo_discounts_calculate_data', 'boost_discount_for_sale_category', 10, 4 );
/**
* Ensure a minimum discount of 10%
*
* @param array $data Calculation data
* @param WC_Product $product Product
* @param array $rule Rule
* @param array $range Discount range
*
* @return array
*/
function ensure_minimum_discount( $data, $product, $rule, $range ): array {
if ( $data['discount_type'] === 'percentage' ) {
$data['discount_value'] = max( 10, $data['discount_value'] ?? 0 );
}
return $data;
}
add_filter( 'wpify_woo_discounts_calculate_data', 'ensure_minimum_discount', 10, 4 );

This filter allows you to modify the result after the discount has been calculated.

apply_filters( 'wpify_woo_discounts_calculate_product_discount', $result, $product, $rule, $range );
ParameterTypeDescription
$resultarrayCalculation result (discounted_price, discount_amount, discount_percentage)
$productWC_ProductProduct
$rulearrayRule settings
$rangearrayDiscount range
/**
* Log all discount calculations
*
* @param array $result Calculation result
* @param WC_Product $product Product
* @param array $rule Rule
* @param array $range Discount range
*
* @return array
*/
function log_discount_calculation( $result, $product, $rule, $range ): array {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( sprintf(
'Discount calculated: Product #%d, Original: %s, Discounted: %s',
$product->get_id(),
$result['original_price'] ?? 'N/A',
$result['discounted_price'] ?? 'N/A'
) );
}
return $result;
}
add_filter( 'wpify_woo_discounts_calculate_product_discount', 'log_discount_calculation', 10, 4 );

This filter allows you to modify the rounding logic of the final discounted price.

apply_filters( 'wpify_woo_discounts_round_price', $rounded_price, $original_price, $rounding_mode, $rule );
ParameterTypeDescription
$rounded_pricefloatPrice after rounding (according to the configured mode)
$original_pricefloatPrice before rounding (after discount)
$rounding_modestringMode: whole, ending_99, ending_90, ending_9
$rulearrayComplete rule data
/**
* Always round down for VIP customers
*
* @param float $rounded_price Rounded price
* @param float $original_price Price before rounding
* @param string $rounding_mode Rounding mode
* @param array $rule Rule
*
* @return float
*/
function vip_rounding( $rounded_price, $original_price, $rounding_mode, $rule ): float {
if ( current_user_can( 'vip_member' ) ) {
return floor( $original_price );
}
return $rounded_price;
}
add_filter( 'wpify_woo_discounts_round_price', 'vip_rounding', 10, 4 );
/**
* Round price to multiples of 10
*
* @param float $rounded_price Rounded price
* @param float $original_price Price before rounding
* @param string $rounding_mode Rounding mode
* @param array $rule Rule
*
* @return float
*/
function round_to_tens( $rounded_price, $original_price, $rounding_mode, $rule ): float {
return round( $original_price / 10 ) * 10;
}
add_filter( 'wpify_woo_discounts_round_price', 'round_to_tens', 10, 4 );

Controlling Discount Application (Subscriptions)

Section titled “Controlling Discount Application (Subscriptions)”

Filter to control whether a discount should be applied. Primarily used for WooCommerce Subscriptions.

apply_filters( 'wpify_woo_discounts_should_apply_discount', $should_apply, $rule );
ParameterTypeDescription
$should_applyboolDefault value (true)
$rulearrayRule data including renewal_behavior
/**
* Never apply bulk discounts on renewal orders
*
* @param bool $should_apply Default value
* @param array $rule Rule
*
* @return bool
*/
function no_bulk_on_renewals( $should_apply, $rule ): bool {
if ( function_exists( 'wcs_cart_contains_renewal' ) && wcs_cart_contains_renewal() ) {
if ( ( $rule['rule_type'] ?? '' ) === 'bulk' ) {
return false;
}
}
return $should_apply;
}
add_filter( 'wpify_woo_discounts_should_apply_discount', 'no_bulk_on_renewals', 10, 2 );

Available renewal behavior values:

  • first_order_only - Discount only on the first order
  • renewals_only - Discount only on renewal orders
  • both - Discount on both (default)

This filter allows you to modify the list of target products after they have been prepared.

apply_filters( 'wpify_woo_discounts_targets_prepared', $targets, $rule );
ParameterTypeDescription
$targetsarrayArray of target products
$rulearrayRule settings
/**
* Exclude low-margin products from discount targets
*
* @param array $targets Target products
* @param array $rule Rule
*
* @return array
*/
function exclude_low_margin_products( $targets, $rule ): array {
return array_filter( $targets, function( $target ) {
$product_id = $target['product_id'] ?? 0;
$margin = get_post_meta( $product_id, '_profit_margin', true );
return $margin > 10; // Exclude products with margin below 10%
} );
}
add_filter( 'wpify_woo_discounts_targets_prepared', 'exclude_low_margin_products', 10, 2 );

This filter allows you to add custom metadata to subrules (discount tiers).

apply_filters( 'wpify_woo_discounts_subrule_metadata', $metadata, $subrule, $rule );
ParameterTypeDescription
$metadataarraySubrule metadata
$subrulearraySubrule data
$rulearrayRule settings
/**
* Add custom metadata for tracking
*
* @param array $metadata Metadata
* @param array $subrule Subrule
* @param array $rule Rule
*
* @return array
*/
function add_tracking_metadata( $metadata, $subrule, $rule ): array {
$metadata['campaign_id'] = $rule['campaign_id'] ?? '';
$metadata['applied_at'] = current_time( 'mysql' );
return $metadata;
}
add_filter( 'wpify_woo_discounts_subrule_metadata', 'add_tracking_metadata', 10, 3 );

This filter allows you to modify the maximum quantity for a discount.

apply_filters( 'wpify_woo_discounts_quantity_limit', $limit, $product, $rule );
ParameterTypeDescription
$limitintQuantity limit
$productWC_ProductProduct
$rulearrayRule settings
/**
* Limit quantity for wholesale customers
*
* @param int $limit Limit
* @param WC_Product $product Product
* @param array $rule Rule
*
* @return int
*/
function limit_wholesale_quantity( $limit, $product, $rule ): int {
if ( current_user_can( 'wholesale_customer' ) ) {
return min( $limit, 100 ); // Max 100 pcs for wholesale
}
return $limit;
}
add_filter( 'wpify_woo_discounts_quantity_limit', 'limit_wholesale_quantity', 10, 3 );

This filter allows you to modify the fee/discount application type in the cart.

apply_filters( 'wpify_woo_discounts_fee_application_type', $type, $rule );
ParameterTypeDescription
$typestringApplication type (fixed, percent)
$rulearrayRule settings
/**
* Change application type for specific rules
*
* @param string $type Application type
* @param array $rule Rule
*
* @return string
*/
function change_fee_application_type( $type, $rule ): string {
// Use percentage for rules with the high_value tag
if ( in_array( 'high_value', $rule['tags'] ?? [], true ) ) {
return 'percent';
}
return $type;
}
add_filter( 'wpify_woo_discounts_fee_application_type', 'change_fee_application_type', 10, 2 );

You can add custom functions either in your child theme’s functions.php or using the Code Snippets plugin.