MdMasud

WordPress, Laravel, Flutter

Category: WooCommerce

  • The Ultimate Guide to WooCommerce Order Status Tweaks: Custom Statuses, Editable Orders, Custom Fields and Order Table Columns

    Managing orders in WooCommerce is flexible, but many developers need extra control beyond the default workflow. This guide brings together several advanced yet practical customisations you can apply to WooCommerce, including adding custom order statuses, setting a default status, making custom statuses editable, adding custom fields to the order details page, and creating custom columns in the order list table.

    This is a complete, step-by-step guide with real working code. All examples use standard WordPress and WooCommerce hooks, and are written for small and medium-sized custom shop workflows.


    1. Adding Custom Order Statuses in WooCommerce

    WooCommerce has built-in statuses such as Pending, Processing, Completed and Cancelled. However, many businesses need more tailored stages, such as Price Request or Customer Visit.

    To add custom statuses, use register_post_status():

    add_action('init', 'add_more_status_to_order');
    
    function add_more_status_to_order()
    {
        register_post_status('wc-price-request', [
            'label'                     => _x('Price request', 'Order status', 'my-domain'),
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop('Price request <span class="count">(%s)</span>', 'Price request <span class="count">(%s)</span>', 'my-domain'),
        ]);
    
        register_post_status('wc-quoted', [
            'label'                     => _x('Quoted', 'Order status', 'my-domain'),
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop('Quoted <span class="count">(%s)</span>', 'Quoted <span class="count">(%s)</span>', 'my-domain'),
        ]);
    }


    These statuses behave just like normal WooCommerce statuses, including appearing in reports and the admin table if configured.


    2. Displaying Custom Statuses in the WooCommerce Status Dropdown


    After registering new statuses, WooCommerce will not show them in the order dropdown unless you merge them manually.

    add_filter('wc_order_statuses', 'show_new_statuses_in_dropdown', 99, 1);
    
    function show_new_statuses_in_dropdown($statuses)
    {
        return array_merge(
            ['wc-price-request' => __('Price request', 'my-domain')],
            ['wc-pending-pricing' => __('Pending pricing', 'my-domain')],
            ['wc-quoted' => __('Quoted', 'my-domain')],
            ['wc-customer-visit' => __('Customer visit', 'my-domain')],
            $statuses
        );
    }


    This ensures your statuses appear alongside the built-in ones on the order details screen.


    3. Setting a Custom Default Order Status


    By default, new orders in WooCommerce start as Pending Payment. For some businesses, this is not suitable. You can override this behaviour and set your own default status.

    add_action('woocommerce_new_order', 'set_default_order_status', 99, 1);
    
    function set_default_order_status($order_id)
    {
        $order = wc_get_order($order_id);
    
        if ($order && $order->get_status() === 'pending') {
            $order->update_status('price-request', 'Default status.');
        }
    }


    Now, every new order will automatically be marked as Price Request instead of Pending.


    4. Allowing Orders with Custom Statuses to Be Editable

    Many custom statuses cannot be edited by default. WooCommerce only allows editing in a few core statuses.

    Use this filter to allow editing in your custom statuses:

    add_filter('wc_order_is_editable', 'add_statuses_to_order_be_editable',10, 2);
    
    function add_statuses_to_order_be_editable($editable, $order)
    {
        $editable_status = [
            'price-request' => true,
            'pending-pricing' => true,
            'quoted'=> true,
            'customer-visit' => true
        ];
    
        if ( current_user_can("manage_options")) {
            if ($order && $editable_status[$order->get_status()]) {
                return true;
            }
        }
    
        return $editable;
    }


    This allows administrators to make changes to orders using these statuses.


    5. Adding Custom Fields to the WooCommerce Order Details Page


    Sometimes you need to store extra data per order, such as a visit date. You can add a custom field directly to the order details box inside the admin area.


    Display the custom field

    add_action( 'woocommerce_admin_order_data_after_order_details', 'add_custom_field_for_order_details', 10, 1 );
    
    function add_custom_field_for_order_details($order)
    {
        $meta_key = '_customer_visit_date_time';
        $prev_value = get_post_meta($order->get_id(), $meta_key, true);
    
        $field_value_date = '';
        $field_value_hour = '';
        $field_value_minute = '';
    
        if ($prev_value) {
            $field_value_date = date('Y-m-d', strtotime($prev_value));
            $field_value_hour = date('h', strtotime($prev_value));
            $field_value_minute = date('i', strtotime($prev_value));
        }
        ?>
        <p class="form-field form-field-wide wc-order-vist-date">
            <label for="customer_visit_date">Visit Date:</label>
            <input type="text" class="date-picker" placeholder="yyyy-mm-dd" 
                   name="visit_date_date" maxlength="10" value="<?= $field_value_date ?>">
            @
            <input type="number" class="hour" placeholder="h"
                   name="visit_date_hour" min="0" max="23"
                   value="<?= $field_value_hour ?>">
            :
            <input type="number" class="minute" placeholder="m"
                   name="visit_date_minute" min="0" max="59"
                   value="<?= $field_value_minute ?>">
            <br/><span class="description">Select a date and time (24h format)</span>
        </p>
        <?php
    }


    Saving the custom field

    add_action('woocommerce_process_shop_order_meta', 'save_custom_fields_for_order_details');
    
    function save_custom_fields_for_order_details($order_id)
    {
        $order = wc_get_order($order_id);
    
        $visit_date_date = wc_clean($_POST['visit_date_date']);
        $visit_date_hour = wc_clean($_POST['visit_date_hour']);
        $visit_date_minute = wc_clean($_POST['visit_date_minute']);
    
        $visit_date_time = $visit_date_date.' '.$visit_date_hour.':'.$visit_date_minute;
    
        $order->update_meta_data('_customer_visit_date_time', $visit_date_time);
        $order->save();
    }


    This stores the value as standard order meta.


    6. Adding Custom Columns in the WooCommerce Orders List Table


    To make your workflow faster, you may want to see custom information directly in the orders list in the admin dashboard. You can add new columns and populate them with meta values.


    Add a new column

    add_filter('manage_edit-shop_order_columns', 'update_shop_order_columns', 20, 1);
    
    function update_shop_order_columns($columns)
    {
        $new_columns = array();
    
        foreach ($columns as $key => $label) {
            if ('order_date' === $key) {
                $label = __('Order Date', 'my-domain');
            }
    
            $new_columns[$key] = $label;
    
            if ('order_status' === $key) {
                $new_columns['visit_date'] = __('Visit Date', 'my-domain');
            }
        }
    
        return $new_columns;
    }


    Display the value in the column

    add_filter('manage_shop_order_posts_custom_column', 'update_shop_order_columns_content', 20, 2);
    
    function update_shop_order_columns_content($column, $order_post_id)
    {
        if ('visit_date' !== $column) {
            return;
        }
    
        $visit_date = get_post_meta($order_post_id, '_customer_visit_date_time', true);
    
        if (!$visit_date) {
            echo '<span>Add now</span>';
            return;
        }
    
        $timestamp = strtotime($visit_date);
    
        if ($timestamp) {
            echo '<span style="color:#008a00;">'.date('Y-m-d @ H:i', $timestamp).'</span>';
        } else {
            echo '<span style="color:#d63638;">Not valid</span>';
        }
    }


    This displays the date in green when valid, and a warning in red if not.

    This guide brings together a full set of WooCommerce order management enhancements that you can use to build a more tailored workflow:

    • Adding custom order statuses
    • Showing them in the admin dropdown
    • Setting a custom default order status
    • Keeping orders editable in specific statuses
    • Adding custom fields to order details
    • Showing those fields in the order list table

  • How to add and save Custom Fields in the WooCommerce Order Details page


    Sometimes you need to store extra information for an order, such as a customer visit date. WooCommerce allows you to add your own fields to the order edit screen and save that information as order meta.


    Adding a Custom Date and Time Field

    add_action( 'woocommerce_admin_order_data_after_order_details', 'add_custom_field_for_order_details', 10, 1 );
    
    function add_custom_field_for_order_details($order)
    {
        $meta_key = '_customer_visit_date_time';
        $prev_value = get_post_meta($order->get_id(), $meta_key, true);
    
        $field_value_date = '';
        $field_value_hour = '';
        $field_value_minute = '';
    
        if ($prev_value) {
            $field_value_date = date('Y-m-d', strtotime($prev_value));
            $field_value_hour = date('h', strtotime($prev_value));
            $field_value_minute = date('i', strtotime($prev_value));
        }
        ?>
        <p class="form-field form-field-wide wc-order-vist-date">
            <label for="customer_visit_date">Visit Date:</label>
            <input type="text" class="date-picker" placeholder="yyyy-mm-dd"
                   name="visit_date_date" maxlength="10" value="<?= $field_value_date ?>">
            @
            <input type="number" class="hour" placeholder="h" name="visit_date_hour"
                   min="0" max="23" value="<?= $field_value_hour ?>">
            :
            <input type="number" class="minute" placeholder="m" name="visit_date_minute"
                   min="0" max="59" value="<?= $field_value_minute ?>">
            <br/><span class="description">Select a date and time (24h format)</span>
        </p>
        <?php
    }


    Saving the Custom Field

    add_action('woocommerce_process_shop_order_meta', 'save_custom_fields_for_order_details');
    
    function save_custom_fields_for_order_details($order_id)
    {
        $order = wc_get_order($order_id);
    
        $visit_date_date = wc_clean($_POST['visit_date_date']);
        $visit_date_hour = wc_clean($_POST['visit_date_hour']);
        $visit_date_minute = wc_clean($_POST['visit_date_minute']);
    
        $visit_date_time = $visit_date_date.' '.$visit_date_hour.':'.$visit_date_minute;
    
        $order->update_meta_data('_customer_visit_date_time', $visit_date_time);
        $order->save();
    }


    Adding custom fields to the WooCommerce order details screen is straightforward and allows you to store important data directly with each order.

  • How to Allow WooCommerce Orders with Custom Statuses to Stay Editable

    By default custom statuses prevent the order from being edited.
    WooCommerce only allows editing in a few built-in statuses, but you can override this and allow editing for your own workflow.


    Allow Editing in Custom Statuses

    add_filter('wc_order_is_editable', 'add_statuses_to_order_be_editable',10, 2);
    
    function add_statuses_to_order_be_editable($editable, $order)
    {
        $editable_status = [
            'price-request' => true,
            'pending-pricing' => true,
            'quoted'=> true,
            'customer-visit' => true
        ];
    
        if ( current_user_can("manage_options")) {
            if ($order && $editable_status[$order->get_status()]) {
                return true;
            }
        }
        return $editable;
    }


    This allows users with admin rights to edit orders even when they are in one of the custom statuses.


    If your order lifecycle requires edits at different steps, enabling edit access for custom statuses ensures your workflow stays smooth.

  • How to add WooCommerce custom Order Statuses and display them in the dropdown


    WooCommerce will not automatically show your custom statuses in the admin dropdown unless you explicitly add them. Below you can find how to register the statuses and make them appear in the status selection dropdown inside the order details screen.


    Showing Your Statuses in the Admin Dropdown

    add_filter('wc_order_statuses', 'show_new_statuses_in_dropdown', 99, 1);
    
    function show_new_statuses_in_dropdown($statuses)
    {
        return array_merge(
            ['wc-price-request' => __('Price request', 'my-domain')],
            ['wc-pending-pricing' => __('Pending pricing', 'my-domain')],
            ['wc-quoted' => __('Quoted', 'my-domain')],
            ['wc-customer-visit' => __('Customer visit', 'my-domain')],
            $statuses
        );
    }


    This merges your custom statuses with the existing ones in a clean way.


    Once your statuses are registered and added to the dropdown, your WooCommerce order management becomes more flexible and easier to track.

  • How to add a custom Order Status in WooCommerce and set it as the default

    WooCommerce has default order statuses such as Pending Payment, Processing, and Completed.
    However, Some online businesses need their own custom workflow. For example, you may want new orders to start in a “Price Request” status instead of “Pending”.

    In this guide, I explain how to register new order statuses and set one of them as the default when an order is created.


    Registering custom Order Statuses

    WooCommerce uses register_post_status() to add new statuses.
    Below we add four custom statuses to WordPress:

    add_action('init', 'add_more_status_to_order');
    
    function add_more_status_to_order()
    {
        register_post_status('wc-price-request', [
            'label'                     => _x('Price request', 'Order status', 'my-domain'),
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop('Price request <span class="count">(%s)</span>', 'Price request <span class="count">(%s)</span>', 'my-domain'),
        ]);
    
        register_post_status('wc-quoted', [
            'label'                     => _x('Quoted', 'Order status', 'my-domain'),
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop('Quoted <span class="count">(%s)</span>', 'Quoted <span class="count">(%s)</span>', 'my-domain'),
        ]);
    
        register_post_status('wc-pending-pricing', [
            'label'                     => _x('Pending pricing', 'Order status', 'my-domain'),
            'public'                    => true,
            'exclude_from_search'       => false,
            'show_in_admin_all_list'    => true,
            'show_in_admin_status_list' => true,
            'label_count'               => _n_noop('Pending pricing <span class="count">(%s)</span>', 'Pending pricing <span class="count">(%s)</span>', 'my-domain'),
        ]);
    }


    Setting a Custom Default Order Status

    By default, WooCommerce sets all new orders to “Pending”.
    If you want every new order to start as “Price Request”, use this hook:

    add_action('woocommerce_new_order', 'set_default_order_status', 99, 1);
    
    function set_default_order_status($order_id)
    {
        $order = wc_get_order($order_id);
        if ($order && $order->get_status() === 'pending') {
            $order->update_status('price-request', 'Default status.');
        }
    }


    This helps when your business process is different from a standard retail store.


    By registering custom statuses and setting one as the default, you can build an order workflow that matches the business requirements.