Add Custom Order Status Dropdown in WooCommerce Admin
By default, WooCommerce provides a set of predefined order statuses such as Pending, Processing, Completed, and Cancelled. But sometimes store owners need to track additional states without creating a full new WooCommerce order status.
In this tutorial, you’ll learn how to add a custom dropdown to WooCommerce orders, display the value in the orders list, and save it for each order. This is useful for cases like “Order Dispatched” vs. “Not Dispatched”, or any internal tracking status your business needs.
Why Add a Custom Order Dropdown?
✅ Track internal states (e.g., “Dispatched”, “Packed”, “Awaiting Courier”).
✅ Improve order management in WooCommerce Admin.
✅ Provide staff with clear status updates without affecting the main WooCommerce order status flow.
Code Snippet
Add this code to your theme’s functions.php file or inside a custom plugin:
// Add custom column to orders list
add_filter('manage_edit-shop_order_columns', 'custom_shop_order_column', 20);
function custom_shop_order_column($columns) {
$new_columns = array();
foreach ($columns as $key => $column) {
$new_columns[$key] = $column;
if ('order_status' === $key) {
$new_columns['order_dispatched'] = __('Order Status', 'woocommerce');
}
}
return $new_columns;
}
// Display custom column content
add_action('manage_shop_order_posts_custom_column', 'custom_shop_order_column_content', 20, 2);
function custom_shop_order_column_content($column, $post_id) {
if ('order_dispatched' === $column) {
$dispatched = get_post_meta($post_id, '_order_dispatched', true);
echo $dispatched === 'yes' ? __('Απεσταλμένη', 'woocommerce') : __('Μη απεσταλμένη', 'woocommerce');
}
}
// Add the dropdown to the order edit page
add_action('woocommerce_admin_order_data_after_order_details', 'custom_order_dispatched_dropdown');
function custom_order_dispatched_dropdown($order) {
$dispatched = get_post_meta($order->get_id(), '_order_dispatched', true);
?>
<p class="form-field form-field-wide">
<label for="order_dispatched"><?php _e('Order Status', 'woocommerce'); ?></label>
<select id="order_dispatched" name="order_dispatched">
<option value="no" <?php selected($dispatched, 'no'); ?>><?php _e('Μη απεσταλμένη', 'woocommerce'); ?></option>
<option value="yes" <?php selected($dispatched, 'yes'); ?>><?php _e('Απεσταλμένη', 'woocommerce'); ?></option>
</select>
</p>
<?php
}
// Save the dropdown value
add_action('save_post_shop_order', 'save_order_dispatched_dropdown');
function save_order_dispatched_dropdown($post_id) {
$order = wc_get_order($post_id);
$dispatched = isset($_POST['order_dispatched']) ? sanitize_text_field($_POST['order_dispatched']) : 'no';
$order->update_meta_data('_order_dispatched', $dispatched);
$order->save();
}
// Modify order status display
add_filter('woocommerce_admin_order_actions', 'custom_order_status_display', 10, 2);
function custom_order_status_display($actions, $order) {
$dispatched = get_post_meta($order->get_id(), '_order_dispatched', true);
if ($dispatched === 'yes') {
$actions['dispatched'] = array(
'url' => '#',
'name' => __('Απεσταλμένη', 'woocommerce'),
'action' => 'dispatched',
);
}
return $actions;
}
// Enqueue and add inline script
function enqueue_admin_order_custom_script() {
wp_enqueue_script('jquery');
$inline_script = "
jQuery(document).ready(function($) {
$('.order-dispatched-checkbox').on('change', function() {
var orderId = $(this).data('order-id');
var dispatched = $(this).is(':checked') ? 'yes' : 'no';
$.ajax({
url: '".admin_url('admin-ajax.php')."',
method: 'POST',
data: {
action: 'save_order_dispatched_status',
order_id: orderId,
dispatched: dispatched
},
success: function(response) {
console.log('Order status updated');
}
});
});
});
";
wp_add_inline_script('jquery', $inline_script);
}
add_action('admin_enqueue_scripts', 'enqueue_admin_order_custom_script');
// Handle AJAX request
add_action('wp_ajax_save_order_dispatched_status', 'save_order_dispatched_status');
function save_order_dispatched_status() {
if (isset($_POST['order_id']) && isset($_POST['dispatched'])) {
$order_id = intval($_POST['order_id']);
$dispatched = sanitize_text_field($_POST['dispatched']);
update_post_meta($order_id, '_order_dispatched', $dispatched);
wp_send_json_success();
}
wp_send_json_error();
}
How It Works
A new Order Status dropdown is added to each order edit page.
The selected value is saved as order meta (
_order_dispatched).A custom column displays the value in the WooCommerce orders list.
Optionally, AJAX allows quick updates without opening each order.
Best Practices
✅ Use a child theme or custom plugin to store this code.
✅ Translate the labels if your store is multilingual.
✅ Use clear, simple terms for staff (e.g., “Shipped”, “Ready for Pickup”).