# Cost Price Field and Margin Column for Products

> Adds a "Cost price" field to simple products and variations and a Margin column to the Products list showing profit per sale and margin percent.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, products, profit, admin
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-product-cost-and-margin/

## Code

```php
add_action( 'woocommerce_product_options_pricing', function () {
    global $product_object;

    woocommerce_wp_text_input( array(
        'id'        => '_wpide_cost',
        'label'     => 'Cost price (' . get_woocommerce_currency_symbol() . ')',
        'data_type' => 'price',
        'value'     => $product_object instanceof WC_Product ? $product_object->get_meta( '_wpide_cost' ) : '',
    ) );
} );

add_action( 'woocommerce_variation_options_pricing', function ( $loop, $data, $variation ) {
    woocommerce_wp_text_input( array(
        'id'            => '_wpide_cost[' . $loop . ']',
        'label'         => 'Cost price (' . get_woocommerce_currency_symbol() . ')',
        'data_type'     => 'price',
        'wrapper_class' => 'form-row form-row-full',
        'value'         => get_post_meta( $variation->ID, '_wpide_cost', true ),
    ) );
}, 10, 3 );

add_action( 'woocommerce_admin_process_product_object', function ( $product ) {
    // phpcs:ignore WordPress.Security.NonceVerification -- WooCommerce verifies the product save nonce.
    if ( isset( $_POST['_wpide_cost'] ) && ! is_array( $_POST['_wpide_cost'] ) ) {
        $product->update_meta_data( '_wpide_cost', wc_format_decimal( wp_unslash( $_POST['_wpide_cost'] ) ) );
    }
} );

add_action( 'woocommerce_save_product_variation', function ( $variation_id, $i ) {
    // phpcs:ignore WordPress.Security.NonceVerification -- WooCommerce verifies the variations save nonce.
    if ( isset( $_POST['_wpide_cost'][ $i ] ) && current_user_can( 'edit_product', $variation_id ) ) {
        update_post_meta( $variation_id, '_wpide_cost', wc_format_decimal( wp_unslash( $_POST['_wpide_cost'][ $i ] ) ) );
    }
}, 10, 2 );

add_filter( 'manage_edit-product_columns', function ( $columns ) {
    $new = array();

    foreach ( $columns as $key => $label ) {
        $new[ $key ] = $label;

        if ( 'price' === $key ) {
            $new['wpide_margin'] = 'Margin';
        }
    }

    return $new;
}, 20 );

add_action( 'manage_product_posts_custom_column', function ( $column, $post_id ) {
    if ( 'wpide_margin' !== $column ) {
        return;
    }

    $product = wc_get_product( $post_id );
    $target  = $product && $product->is_type( 'variable' ) ? wc_get_product( current( $product->get_visible_children() ) ) : $product;
    $cost    = $target ? (float) $target->get_meta( '_wpide_cost' ) : 0;
    $price   = $target && '' !== $target->get_price() ? (float) wc_get_price_excluding_tax( $target ) : 0;

    if ( $cost <= 0 || $price <= 0 ) {
        echo '–';
        return;
    }

    $profit = $price - $cost;
    printf( '<span style="color:%1$s">%2$s (%3$s%%)</span>', esc_attr( $profit >= 0 ? '#008a20' : '#d63638' ), wp_kses_post( wc_price( $profit ) ), esc_html( number_format_i18n( $profit / $price * 100, 1 ) ) );
}, 10, 2 );
```

## Notes

Cost prices are never shown to customers, and the margin uses the current price (sale price when on sale) excluding tax.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Cost Price Field and Margin Column for Products" 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/
