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




