# Quantity Price Breaks With a Price Table

> Lowers the unit price when a customer buys more of the same product, for example 5% off from 10 units, and shows a price-break table on the product page.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, pricing, quantity, tiers
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-quantity-price-tiers/

## Code

```php
$wpide_qty_tiers = array(
    'tiers'    => array( 10 => 5, 25 => 10, 50 => 15 ), // Minimum quantity => percent off.
    'products' => array(),                              // Product IDs, empty for all.
);

$wpide_tier_percent = function ( $qty ) use ( $wpide_qty_tiers ) {
    $percent = 0;

    foreach ( $wpide_qty_tiers['tiers'] as $min => $off ) {
        if ( $qty >= $min ) {
            $percent = $off;
        }
    }

    return $percent;
};

$wpide_tier_applies = function ( $product_id ) use ( $wpide_qty_tiers ) {
    return empty( $wpide_qty_tiers['products'] ) || in_array( (int) $product_id, array_map( 'intval', $wpide_qty_tiers['products'] ), true );
};

add_action( 'woocommerce_before_calculate_totals', function ( $cart ) use ( $wpide_tier_percent, $wpide_tier_applies ) {
    static $base_prices = null;

    if ( is_admin() && ! wp_doing_ajax() ) {
        return;
    }

    $base_prices = $base_prices ?: new SplObjectStorage(); // Original prices, so repeated totals runs never stack.

    foreach ( $cart->get_cart() as $item ) {
        if ( ! $wpide_tier_applies( $item['product_id'] ) ) {
            continue;
        }

        if ( ! $base_prices->contains( $item['data'] ) ) {
            $base_prices[ $item['data'] ] = (float) $item['data']->get_price( 'edit' );
        }

        $base    = $base_prices[ $item['data'] ];
        $percent = $wpide_tier_percent( (int) $item['quantity'] );
        $item['data']->set_price( $percent ? round( $base * ( 100 - $percent ) / 100, wc_get_price_decimals() ) : $base );
    }
}, 20 );

add_action( 'woocommerce_single_product_summary', function () use ( $wpide_qty_tiers, $wpide_tier_applies ) {
    global $product;

    if ( ! $product instanceof WC_Product || ! $product->is_purchasable() || '' === $product->get_price() || ! $wpide_tier_applies( $product->get_id() ) ) {
        return;
    }

    $price = (float) wc_get_price_to_display( $product );

    echo '<table class="wpide-price-tiers shop_table"><thead><tr><th>' . esc_html( 'Quantity' ) . '</th><th>' . esc_html( 'Price each' ) . '</th></tr></thead><tbody>';

    foreach ( $wpide_qty_tiers['tiers'] as $min => $off ) {
        printf( '<tr><td>%s+</td><td>%s <small>(-%s%%)</small></td></tr>', esc_html( $min ), wp_kses_post( wc_price( $price * ( 100 - $off ) / 100 ) ), esc_html( $off ) );
    }

    echo '</tbody></table>';
}, 25 );
```

## Notes

Tiers apply per cart line; list product IDs in 'products' to limit them, or leave it empty for every product.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Quantity Price Breaks With a Price Table" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
