woocommerce_before_calculate_totals

This action runs before WooCommerce calculates cart totals, giving developers access to the current cart items and their product objects for adjustments.

Quick Reference

TypeAction hook
AreaCart totals
Arguments$cart (WC_Cart)
SourceWooCommerce code reference

How It Works

WooCommerce calls do_action() during WC_Cart::calculate_totals() and passes the cart object. A callback can inspect items before totals are calculated. Totals may be recalculated more than once per request, so avoid multiplying or repeatedly reducing an already modified price.

PHP Example

add_action( 'woocommerce_before_calculate_totals', function ( $cart ) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return;
    }

    foreach ( $cart->get_cart() as $item ) {
        if ( 123 === (int) $item['product_id'] ) {
            $item['data']->set_price( 19.00 );
        }
    }
} );

Replace product ID 123 and the price with values appropriate to your store. This sets an absolute unit price, avoiding repeated percentage adjustments during recalculation.

Add the code to a site-specific plugin or a child theme's functions.php file, then test it on a staging site.

Common Pitfalls

WooCommerce may calculate totals several times as a shopper updates the cart or checkout. Repeatedly subtracting a percentage from $item['data']->get_price() can make a discount grow on each pass. The example sets a fixed price instead, so rerunning it produces the same result. Do not call $cart->calculate_totals() from this callback, since that can start the same calculation again.

For a variation, $item['product_id'] identifies its parent product, while $item['variation_id'] identifies the specific variation. The example targets the parent ID, so it also affects variations of that product.

Compatibility

This is a cart-calculation hook, not a checkout-form display hook. Verify the result with your taxes, discounts, subscriptions, and checkout setup before using it in production.