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.

  9. I’d like to know how to add a column to the order admin page that show the total number of orders and another that shows the total spent by a customer. This would assist with vetting orders.

  10. Beka, it’s the second time today that I found one of your gems, and I gotta say that you saved me hours of trial-and-error. Thank you very much!

  11. Hi,
    My profit field value is equal to the total value. Its like the cost is zero.
    Since i know my COG is updated for all items and orders, any idea why it not working for me?

    Do i need to change anything in the code you wrote?

  12. Hello,

    Thank you for the great guide! I was able to create a column to show a custom field for orders created from the front-end. I’d like to ask, how can I make that column sortable so my clients can quickly view all the front-end orders at the top?

    • Hey Wallace, while this is do-able, it’s a more substantial project, and not something I have an example for. You’d need to add the sorting links to add URL parameters for sorting arguments, then filter the orders query based on those arguments to adjust how they’re listed. If this isn’t something you’ve done before, I’d recommend reaching out to Codeable for help with this project.

      • Hi Beka, thanks for your help. I was able to create a column for showing the custom field “Origin type” which differentiates the order by “web”, “manual”, or “phone”.

        I’d like to know, is it possible to also create a column and display customer’s notes as texts like the shipping address?

        Thank you!

  13. Thank-You Beka! Excellent and easy to follow article.

  14. HI Beka,

    The profit field shows the same value as my total order field… any suggestions?

  15. Very cool. One question: we’d like to display the contents of the Order notes field on the checkout page. We tried replacing billing_country in your code with order_comments which seems to break the Orders page. Does anyone know the correct field name for order notes? Thank you.

Hmm, looks like this article is quite old! Its content may be outdated, so comments are now closed.