In wooCommerce admin product pages, on variable products you can have product variations. See below the "variations" settings section:

enter image description here

What Im trying to achieve:

I have already been able to add a text field for regular price and sales price for simple products on admin "product data" metabox under "General" section. Now I need to add a new text field "Cost price" for variable products under "variations" section, but I had no idea how to add this.

So I started searching the scripts/reading WooCommerce documentation and I Managed to add the new text field by editing includes/admin/metabox/html-variation-admin.php, adding the code below to it:

        'id'            => "variable_cost_price{$loop}",
        'name'          => "variable_cost_price[{$loop}]",
        'value'         => wc_format_localized_price( $variation_object->get_cost_price( 'edit' ) ),
        'data_type'     => 'price',
        'label'         => $label ,
        'wrapper_class' => 'form-row form-row-last',

I knew this was going to work as I cloned this from "Regular Price" form field.

My problem: Of course having the text field there is pointless if it does not save to the database and bring back the data to display on page load. Again I'm not 100% sure but I thought I had to make some more additions.

What I have tried: I have add the the method get_cost_price to the class-wc-ajax.php script as i saw one there already for get_regular_price. I also saw lines in class-wc-meta-box-product-data.php which referred to regular_price so I added an entry for my new cost_price, see below to what I added (I added the cost_price line):

$errors = $variation->set_props(
        'status'            => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private',
        'menu_order'        => wc_clean( $_POST['variation_menu_order'][ $i ] ),
        'regular_price'     => wc_clean( $_POST['variable_regular_price'][ $i ] ),
        'sale_price'        => wc_clean( $_POST['variable_sale_price'][ $i ] ),
        'cost_price'        => wc_clean( $_POST['variable_code_price'][ $i ] ),
        // .. more code here..

What have I missed, did I need to make a change in yet another script?

Again, the text field is displaying but entering data and clicking save changes doesn't actually seem to be adding anything to the postmeta table.

EDIT: I do not need this displaying on the front end website, this is purely for backend data for me to store

2 Answers 2


Overriding core files is really something to avoid absolutely for many reasons.

To add a custom field to product variations options prices and save the value on save, use this:

// Admin: Add custom field in product variations options pricing
add_action( 'woocommerce_variation_options_pricing', 'add_variation_custom_option_pricing', 10, 3 );
function add_variation_custom_option_pricing( $loop, $variation_data, $variation ){

   woocommerce_wp_text_input( array(
        'id'            => '_cost_price['.$loop.']',
        'label'         => __("Cost Price", "woocommerce") . ' (' . get_woocommerce_currency_symbol() . ')',
        'class' => 'short wc_input_price',
        'data_type'     => 'price',
        'wrapper_class' => 'form-row form-row-first',
        'value'         => wc_format_localized_price( get_post_meta( $variation->ID, '_cost_price', true ) )
    ) );

// Admin: Save custom field value from product variations options pricing
add_action( 'woocommerce_save_product_variation', 'save_variation_custom_option_pricing', 10, 2 );
function save_variation_custom_option_pricing( $variation_id, $i ){
    if( isset($_POST['_cost_price'][$i]) ){
        update_post_meta( $variation_id, '_cost_price', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_cost_price'][$i]) ) ) );

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here

USAGE - If you need to use it to get the value:

1) From the variation ID

$cost_price = update_post_meta( $variation_id, '_cost_price', true );

2) From the product variation object

$cost_price = $variation->get_meta('_cost_price');

You need to make use of the WordPress hooks and filters the system provides for you.

Put this code in your functions.php of your current theme. Make sure your theme has woocommerce_support enabled via "add_theme_support('woocommerce');"

// Add the textfield to the backend
    function se_add_extra_price_field() {
            'id'            => 'cost-price',
            'class'         => 'short wc_input_price cost-price',
            'label'         => __('Cost-Price (€)', 'yourtextdomain'),
           'description'    => 'Cost-price description...',
           'placeholder'    => '50 Cent'

// Enable to save the extra field
function se_save_extra_price_field($post_id) {
    $product = wc_get_product($post_id);
    $title = isset( $_POST['cost-price'] ) ? $_POST['cost-price'] : '';
    $product->update_meta_data( 'cost-price', sanitize_text_field( $title ) );
    if(isset($_POST['cost-price'])) {
                update_post_meta($product_id, 'cost-price', $_POST['cost-price']);
add_action('save_post', 'se_save_extra_price_field');

I have tested this code and it should work - just copy and paste (more or less..).

Please accept the answer as correct if it worked for you. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.