When viewing the “Orders” list in WooCommerce, you’ll see a set of columns that will show you details about orders in your store. While you can remove columns easily using the “Screen options” tab, adding columns requires some custom code to determine what the column data should be.

Let’s take a look at adding some custom WooCommerce Orders list columns today. In this case, we’ll add a “Profit” column to show the order’s profit when used with WooCommerce Cost of Goods.

This tutorial requires beginner to intermediate PHP and WordPress development skills.

WooCommerce Orders List Column, Step 1: Add a Header

Adding a new column is straight-forward using the manage_edit-{$post_type}_columns filter from WordPress core. This will let us change the columns shown in the list table for orders so we can inject our own.

While this code could be as simple as:

function wc_new_order_column( $columns ) {
    $columns['my_column'] = 'My column';
    return $columns;
add_filter( 'manage_edit-shop_order_columns', 'wc_new_order_column' );

I’m going to take this a bit further to add my column in the position I want it in. I’ll add my new “Profit” column after the “total” column for the order.

 * Adds 'Profit' column header to 'Orders' page immediately after 'Total' column.
 * @param string[] $columns
 * @return string[] $new_columns
function sv_wc_cogs_add_order_profit_column_header( $columns ) {

    $new_columns = array();

    foreach ( $columns as $column_name => $column_info ) {

        $new_columns[ $column_name ] = $column_info;

        if ( 'order_total' === $column_name ) {
            $new_columns['order_profit'] = __( 'Profit', 'my-textdomain' );

    return $new_columns;
add_filter( 'manage_edit-shop_order_columns', 'sv_wc_cogs_add_order_profit_column_header', 20 );

Now I’ve got a new column!

WooCommerce Orders List Column: Add header

However, we haven’t told WordPress / WooCommerce what should go in the column yet, so we need to populate the column for each row in the list next.

Step 2: Populate the Column

To put data into our custom column, we’ll use another core hook: the manage_{$post_type}_posts_custom_column action, which will be fired each time our custom column is reached for a row.

We’ll need to do a couple things for our column: (1) get the profit from the order, and (2) output it in the column. That sounds easy, but there are a couple caveats:

  1. Cost of Goods stores cost, not profit. We’ll need to get the order total and cost, then determine profit.
  2. Cost of Goods stores cost as order meta. While we could use get_post_meta() to retrieve this, for the sake of completeness and compatibility with WooCommerce 3.0+ (and future versions), I’ll use core WooCommerce functions to get this meta.

As such, let’s first write ourselves a little helper to get order meta in multiple WooCommerce versions.

if ( ! function_exists( 'sv_helper_get_order_meta' ) ) :

     * Helper function to get meta for an order.
     * @param \WC_Order $order the order object
     * @param string $key the meta key
     * @param bool $single whether to get the meta as a single item. Defaults to `true`
     * @param string $context if 'view' then the value will be filtered
     * @return mixed the order property
    function sv_helper_get_order_meta( $order, $key = '', $single = true, $context = 'edit' ) {

        // WooCommerce > 3.0
        if ( defined( 'WC_VERSION' ) && WC_VERSION && version_compare( WC_VERSION, '3.0', '>=' ) ) {

            $value = $order->get_meta( $key, $single, $context );

        } else {

            // have the $order->get_id() check here just in case the WC_VERSION isn't defined correctly
            $order_id = is_callable( array( $order, 'get_id' ) ) ? $order->get_id() : $order->id;
            $value    = get_post_meta( $order_id, $key, $single );

        return $value;


Alright! Now we can use that to get the profit for the order and add it to the column. Notice I’ll also do a couple things here:

  1. The method to return order currency changed in WC 3.0, so I have an is_callable() check to determine how I should get it.
  2. I’ve cast the order cost and total as (float) since I’ll be doing some math with them in case they’re stored as strings, as PHP 7.1+ issues warnings when using strings in math functions.
 * Adds 'Profit' column content to 'Orders' page immediately after 'Total' column.
 * @param string[] $column name of column being displayed
function sv_wc_cogs_add_order_profit_column_content( $column ) {
    global $post;

    if ( 'order_profit' === $column ) {

        $order    = wc_get_order( $post->ID );
        $currency = is_callable( array( $order, 'get_currency' ) ) ? $order->get_currency() : $order->order_currency;
        $profit   = '';
        $cost     = sv_helper_get_order_meta( $order, '_wc_cog_order_total_cost' );
        $total    = (float) $order->get_total();

        // don't check for empty() since cost can be '0'
        if ( '' !== $cost || false !== $cost ) {

            // now we can cast cost since we've ensured it was calculated for the order
            $cost   = (float) $cost;
            $profit = $total - $cost;

        echo wc_price( $profit, array( 'currency' => $currency ) );
add_action( 'manage_shop_order_posts_custom_column', 'sv_wc_cogs_add_order_profit_column_content' );

Alright, we have some data in our profit column!

WooCommerce Orders List Column: column content

We could stop here if desired, but I’m going to take one final step. That column is pretty wide, so I’m going to add some CSS to the WooCommerce admin styles to make it more consistent.

Step 3: (Optional) Fix Column Styles

This is totally optional, but I’d like to make the “Profit” column the same width as the “Total” column. This is where the wp_add_inline_style function is handy, as it lets you add some additional CSS into an existing stylesheet. I’ll add this to the woocommerce_admin_styles:

 * Adjusts the styles for the new 'Profit' column.
function sv_wc_cogs_add_order_profit_column_style() {

    $css = '.widefat .column-order_date, .widefat .column-order_profit { width: 9%; }';
    wp_add_inline_style( 'woocommerce_admin_styles', $css );
add_action( 'admin_print_styles', 'sv_wc_cogs_add_order_profit_column_style' );

And now I’ve got a “Profit” WooCommerce Orders list column with data that looks consistent with the rest of my order admin:

WooCommerce Orders List Column: column styles

Published by Beka Rice

Beka leads product direction for SkyVerge and technical documentation. She spends a lot of time on research and interviews, but likes to write so she has an excuse to spend more time jamming out to anything from The Clash to Lady Gaga.


  1. Thanks for this! I literally today had just assigned changing the columns of the orders page to my developer for tomorrow. He hadn’t done it before so sent this to him, should make it easier to understand the logic for what I need him to do.

  2. Awesome! Just what I was looking for. Can you tell how to switch out Profit for Time?
    Thanks so much.

  3. Thank you.
    Is there a way to populate the filed from Tracking number from woocomerce tracking plugin meta data https://docs.woocommerce.com/document/shipment-tracking/ with meta reference _tracking_number

  4. Hello!!

    I do not want to show profit in the new column. I want to show the product name. How do I do that? You can tell me?

    Thank you.

  5. Hello.
    good post, it works but there is a little problem if you can solve it.
    your code calculate the profits including the shipping cost, is there a way to exclude the shipping cost from pofits.
    because logically shipping cost is paid by customer for shipping.

    Thank you in advance

  6. Hello,

    Thanks for this code, workls perfectly. I have an additional question. I would like to show the total sum (of one day) of this column in a dashboard widget. How can i add up the profit column of the actual day?

  7. hi,
    thanks , is there a way to make this comus sortable ?

  8. Hi Beka,

    Would it be possible to adjust this code to pull in the pickup date from the pickup plus plugin and make it sortable?


    • Possible, but definitely more complicated: pickup dates are stored on line items, not the order itself, so populating the column requires more complex code here; there can also potentially be more than one pickup date per order, it’s not something you could make sortable. Not something I have an example ready for, but doable with a small project from Codeable.


Leave a Reply

Your email address will not be published. Required fields are marked *