Viewed   206 times

I am using WooCommerce plugin for one of my ecommerce WordPress websites. I want to add some columns to my order listing page in the WooCommerce admin area. I am not able to find out where to add that.

Can anyone advise which template page I need to amend in order to meet my requirement?



Updated: 2018-03-30 - added positioning feature to the new columns

So you if you want to add some columns in the orders Admin list page (in backend):


In the example below, we add 2 new custom columns, before existing "Total" and "Actions" columns.

// ADDING 2 NEW COLUMNS WITH THEIR TITLES (keeping "Total" and "Actions" columns at the end)
add_filter( 'manage_edit-shop_order_columns', 'custom_shop_order_column', 20 );
function custom_shop_order_column($columns)
    $reordered_columns = array();

    // Inserting columns to a specific location
    foreach( $columns as $key => $column){
        $reordered_columns[$key] = $column;
        if( $key ==  'order_status' ){
            // Inserting after "Status" column
            $reordered_columns['my-column1'] = __( 'Title1','theme_domain');
            $reordered_columns['my-column2'] = __( 'Title2','theme_domain');
    return $reordered_columns;

// Adding custom fields meta data for each new column (example)
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 20, 2 );
function custom_orders_list_column_content( $column, $post_id )
    switch ( $column )
        case 'my-column1' :
            // Get custom post meta data
            $my_var_one = get_post_meta( $post_id, '_the_meta_key1', true );
                echo $my_var_one;

            // Testing (to be removed) - Empty value case
                echo '<small>(<em>no value</em>)</small>';


        case 'my-column2' :
            // Get custom post meta data
            $my_var_two = get_post_meta( $post_id, '_the_meta_key2', true );
                echo $my_var_two;

            // Testing (to be removed) - Empty value case
                echo '<small>(<em>no value</em>)</small>';


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

Related answer (for products): Add custom columns to admin producs list in WooCommerce backend

Friday, October 14, 2022

Here is the complete way to make your functionality work on bulk order list action selection, instead of date range:

// Adding to admin order list bulk dropdown a custom action 'custom_downloads'
add_filter( 'bulk_actions-edit-shop_order', 'downloads_bulk_actions_edit_product', 20, 1 );
function downloads_bulk_actions_edit_product( $actions ) {
    $actions['write_downloads'] = __( 'Download orders', 'woocommerce' );
    return $actions;

// Make the action from selected orders
add_filter( 'handle_bulk_actions-edit-shop_order', 'downloads_handle_bulk_action_edit_shop_order', 10, 3 );
function downloads_handle_bulk_action_edit_shop_order( $redirect_to, $action, $post_ids ) {
    if ( $action !== 'write_downloads' )
        return $redirect_to; // Exit

    global $attach_download_dir, $attach_download_file; // ???

    $processed_ids = array();

    foreach ( $post_ids as $post_id ) {
        $order = wc_get_order( $post_id );
        $order_data = $order->get_data();

        // Your code to be executed on each selected order
            $order_data['date_created']->date('d/M/Y') . '; ' .
            '#' . ( ( $order->get_type() === 'shop_order' ) ? $order->get_id() : $order->get_parent_id() ) . '; ' .
            '#' . $order->get_id()
        $processed_ids[] = $post_id;

    return $redirect_to = add_query_arg( array(
        'write_downloads' => '1',
        'processed_count' => count( $processed_ids ),
        'processed_ids' => implode( ',', $processed_ids ),
    ), $redirect_to );

// The results notice from bulk action on orders
add_action( 'admin_notices', 'downloads_bulk_action_admin_notice' );
function downloads_bulk_action_admin_notice() {
    if ( empty( $_REQUEST['write_downloads'] ) ) return; // Exit

    $count = intval( $_REQUEST['processed_count'] );

    printf( '<div id="message" class="updated fade"><p>' .
        _n( 'Processed %s Order for downloads.',
        'Processed %s Orders for downloads.',
    ) . '</p></div>', $count );

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

In the returned url I have something like (for 2 selected / processed orders): wp-admin/edit.php?post_type=shop_order&paged=1&write_downloads=1&processed_count=2&processed_ids=847%2C846

I can't test your included script but it's the way to do it on Woocommerce Orders Admin list.


The available variables are set by add_query_arg() function as you will see. When the action is triggered, you get those variables in the URL through GET method…

You can set any variable yourself too…

In this example you can use $_GET or $_REQUEST with:

  • $_GET['write_downloads'] (the name action: true or false)
  • $_GET['processed_count'] (the number of selected orders)
  • $_GET['processed_ids'] (the Order Ids separated by an url-encoded coma %2C)

So you can either execute your script:

  • inside my code function (like in my code) … or …
  • outside it, using the available variables once the action is triggered…

To remove a specific action from the dropdown orders bulk actions

For example we want to remove "On hold" status change:

add_filter( 'bulk_actions-edit-shop_order', 'remove_a_bulk_order_action', 20, 1 );
function remove_a_bulk_order_action( $actions ) {

    return $actions;

All statuses change keys start with mark_ + the status slug (without wc-).

Sunday, October 23, 2022

The main mistake is on last function where $display_value should be replaced with just $value and then return $value; should be located at the end before last closing bracket.

I have also revisited all your code:

add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
    $supplier_url = $values['data']->get_meta( 'supplier_url' ); // Get product custom field value
    // add product custom field as custom order item meta data
    if ( ! empty($supplier_url) ){
        $item->update_meta_data( '_supplier', $supplier_url );

add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 20, 3 );
function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {

    // Change displayed label for specific order item meta key
    if( is_admin() && $item->get_type() === 'line_item' && $meta->key === '_supplier' ) {
        $display_key = __("Supplier", "woocommerce" );
    return $display_key;

add_filter( 'woocommerce_order_item_display_meta_value', 'change_order_item_meta_value', 20, 3 );
function change_order_item_meta_value( $value, $meta, $item ) {

    // Change displayed value for specific order item meta key
    if( is_admin() && $item->get_type() === 'line_item' && $meta->key === '_supplier' ) {
        $value = __('<a class="button" target="_blank" href="'.$value.'">Order</a>', 'woocommerce' );
    return $value;

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

Monday, December 19, 2022

You can remove Free order it by using parse_query filter with $pagenow global variable.

add_filter('parse_query', 'wh_alterAdminPostList');

function wh_alterAdminPostList($query)
    global $pagenow;
    if (is_admin() && $pagenow == 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] == 'shop_order')
        $query->query_vars['meta_query'] = [
                'key' => '_order_total',
                'value' => 0.00,
                'compare' => '>',
                'type' => 'DECIMAL',

Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
Code is tested and works.

Hope this helps!

Sunday, December 11, 2022

Here is the way to do it with that 2 custom functions hooked. The first one create the column with the title, the second one populate the column with the products data. But you will need to set in that second function, the correct corresponding meta_key to get the data.

Here is that code:

add_filter( 'manage_edit-product_columns', 'custom_product_column',11);
function custom_product_column($columns)
   //add columns
   $columns['delivery'] = __( 'Delivery time','woocommerce'); // title
   return $columns;

add_action( 'manage_product_posts_custom_column' , 'custom_product_list_column_content', 10, 2 );
function custom_product_list_column_content( $column, $product_id )
    global $post;

    // HERE get the data from your custom field (set the correct meta key below)
    $delivery_time = get_post_meta( $product_id, '_delivery_time', true );

    switch ( $column )
        case 'delivery' :
            echo $delivery_time; // display the data

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Tested and works.

How to get the correct meta_key slug:

To find the correct meta_key slug corresponding to the "delivery time", you should need to make search in your database using PhpMyAdmin. You will have to search for delivery term in wp_postmeta table this way:

Then you will get this kind of results (here there is just 1 line with a fake slug):

So now you should be able to get the correct slug name (like this fake "_delivery_date" one)

Related answer (for orders): Add custom columns to admin orders list in WooCommerce backend

Tuesday, September 27, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :