WooCommerce Custom Pricing Method for Products

WooCommerce has two pricing fields for products – Regular and Sale price. These prices apply to everyone, registered users and visitors alike. Now, what if you want to offer a different price to a specific user role? There are plugins for that, of course. But how can you do it without a plugin? Well, we have a solution for that, and this article describes it.

With a few lines of PHP, we can add an extra pricing field, let’s call it Wholesale Price, and then apply this price to a specific user role. In this article the new pricing is called Wholesale Pricing, and Editor is the user role the price will apply to.

Note: this article has been updated for WooCommerce 3.0+. The old woocommerce_get_price filter and direct property access like $product->id were removed in WooCommerce 3.0, so the code below uses the current hooks.


Table of Contents


Determine if current user can avail the Wholesale Pricing

// this checks if the current user is capable to have the wholesale pricing
function w4dev_wholesale_applicable() {
    return (bool) ( current_user_can( 'editor' ) && ( ! is_admin() || wp_doing_ajax() ) );
}

Get the Wholesale Pricing value for a Product

// this gets the wholesale price when available, for Simple, Variable & Variation product types
function w4dev_get_wholesale_price( $product ) {
    if ( $product->is_type( array( 'simple', 'variable', 'variation' ) ) ) {
        $price = get_post_meta( $product->get_id(), '_wholesale_price', true );
        if ( $price > 0 ) {
            return $price;
        }
    }
    return 0;
}

Since WooCommerce 3.0, product properties should not be accessed directly, so we use $product->get_id() here. For a variation, get_id() returns the variation id, so one function covers all three product types.


Wholesale Pricing for Simple Product

Step One – Adding the input field

First, we need to add the Wholesale Price input to the product editing page. Here’s the code –

function w4dev_woocommerce_product_options_pricing() {
    woocommerce_wp_text_input( array(
        'id' => '_wholesale_price',
        'class' => 'wc_input_wholesale_price short',
        'label' => __( 'Wholesale Price', 'woocommerce' ) . ' ('.get_woocommerce_currency_symbol().')',
        'type' => 'text'
    ));
}
add_action( 'woocommerce_product_options_pricing', 'w4dev_woocommerce_product_options_pricing' );

After you have added this in your theme’s functions.php or plugin file, you will see a new input appear under the sale price input (note: Simple Product only).


Step Two – Saving the price

Next we need to save the wholesale price value.

add_action( 'woocommerce_process_product_meta_simple', 'w4dev_woocommerce_process_product_meta_simple' );
function w4dev_woocommerce_process_product_meta_simple( $product_id ) {
    if ( isset( $_POST['_wholesale_price'] ) && $_POST['_wholesale_price'] > 0 ) {
        update_post_meta( $product_id, '_wholesale_price', wc_format_decimal( wp_unslash( $_POST['_wholesale_price'] ) ) );
    }
}

This code will save the entered value with the product, using a custom meta key ‘_wholesale_price’.


Step Three – Frontend pricing filter

Now, to assign the wholesale price for ‘Editor’, we hook into the woocommerce_product_get_price filter. This filter replaced the old woocommerce_get_price filter in WooCommerce 3.0.

add_filter( 'woocommerce_product_get_price', 'w4dev_woocommerce_get_price', 10, 2 );
function w4dev_woocommerce_get_price( $price, $product ) {
    if ( w4dev_wholesale_applicable() && w4dev_get_wholesale_price( $product ) > 0 ) {
        $price = w4dev_get_wholesale_price( $product );
    }
    return $price;
}

All done. Now you can check how it works by logging in with any Editor’s credentials, and you should see the product priced with the wholesale price rather than the sale/regular price. All other users and customers get the regular pricing as usual.


Wholesale Pricing for Variable Product

The method described above is only for Simple Products. The same feature can be added for Variable Products too, read further below.

Step One – Adding the input field

add_action( 'woocommerce_product_after_variable_attributes', 'w4dev_woocommerce_product_after_variable_attributes', 10, 3 );
function w4dev_woocommerce_product_after_variable_attributes( $loop, $variation_data, $variation ){ ?>
    <tr class="wholesale_price_row">
        <td>
            <div>
                <label><?php _e( 'Wholesale Price:', 'woocommerce' ); ?></label>
                    <input type="text" size="5" name="variable_wholesale_price[<?php echo $loop; ?>]" value="<?php if ( isset( $variation_data['_wholesale_price'][0] ) ) echo esc_attr( $variation_data['_wholesale_price'][0] ); ?>" step="1" min="0" />
            </div>
        </td>
    </tr><?php
}
woocommerce-wholesale-price-variable-product

Step Two – Saving the price

add_action( 'woocommerce_save_product_variation', 'w4dev_woocommerce_save_product_variation', 10, 2 );
function w4dev_woocommerce_save_product_variation( $variation_id, $i ) {
    if ( isset( $_POST['variable_wholesale_price'][ $i ] ) ) {
        update_post_meta( $variation_id, '_wholesale_price', wc_format_decimal( wp_unslash( $_POST['variable_wholesale_price'][ $i ] ) ) );
    }
}

Step Three – Frontend pricing filter

Variations have their own price filter, woocommerce_product_variation_get_price. We can reuse the same w4dev_woocommerce_get_price() function from the simple product part.

add_filter( 'woocommerce_product_variation_get_price', 'w4dev_woocommerce_get_price', 10, 2 );

One more thing. The price range shown on a variable product page comes from a cached list of variation prices. We need to filter those cached prices, and also add our wholesale condition to the cache hash, otherwise the same cached range would be served to wholesale and regular users.

add_filter( 'woocommerce_variation_prices_price', 'w4dev_woocommerce_variation_price', 10, 3 );
function w4dev_woocommerce_variation_price( $price, $variation, $product ) {
    if ( w4dev_wholesale_applicable() && w4dev_get_wholesale_price( $variation ) > 0 ) {
        $price = w4dev_get_wholesale_price( $variation );
    }
    return $price;
}

add_filter( 'woocommerce_get_variation_prices_hash', 'w4dev_wholesale_variation_prices_hash' );
function w4dev_wholesale_variation_prices_hash( $hash ) {
    $hash[] = w4dev_wholesale_applicable() ? 'wholesale' : 'regular';
    return $hash;
}

Thanks.