Blog

Add a WooCommerce Orders List Column

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;
    }

endif;

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

Submit a Comment