Reordering content in WordPress can be surprisingly awkward if you rely on default dates, titles, or manual menu settings. Specifically, if you want to change the sequence of pages, posts, or products quickly, a drag-and-drop approach is the most intuitive solution.
By using a code snippet, you can enable a visual sorting interface directly within your admin area. This allows you to architect your store and site layouts with surgical precision, ensuring the most important content always appears first. 🏎️💨
What Drag and Drop Ordering Actually Does 🏛️
Manual sorting allows you to set the sequence of items in the WordPress admin area by clicking, holding, and moving them into place. Instead of being restricted by rigid default sorting rules, you gain total editorial control.
Common default rules often include:
- Publish Date: Great for news, but bad for featured products.
- Alphabetical Order: Useful for directories, but rarely for marketing.
- ID Order: Purely technical and often irrelevant to the user experience.
Where You Can Apply This Logic 🤝
This “New Way” of manual sorting is versatile. Furthermore, it can be applied across almost every WordPress content type, including:
- Pages & Posts: For curated reading lists.
- WooCommerce Products: To highlight bestsellers or seasonal items.
- Custom Post Types: Perfect for portfolios, team members, or testimonials.
The Setup: Enabling Visual Sorting 🛠️
1. Activate Your Snippet
To get started, add the reordering snippet to your Code Snippets Pro dashboard. Because this feature is handled via a snippet, you avoid the overhead of a dedicated “reorder plugin.” Consequently, your site remains lean while gaining professional-grade functionality.
2. Toggle Reorder Mode
Once the snippet is active, a new “Reorder” option will appear in your admin list screens. Specifically, this switches the view into a sortable mode, allowing you to move items freely.
3. Align Your Front-End Queries 🔐
This is the most critical architectural step. Rearranging items in the admin area only helps if your website is set to respect that manual order. Therefore, you must ensure your loop grids, archives, or widgets are configured to sort by “Menu Order” or “Manual Order” rather than date or title.
Why This Approach is the “New Way” 🚀
Using a code snippet for reordering is popular among developers because it is:
- Fast: Move dozens of items in seconds.
- Visual: See the exact sequence as you arrange it.
- Persistent: Your chosen order remains saved even after you log out.
- Bloat-Free: No extra plugin files or unnecessary database tables.
Common Mistakes to Avoid 🚫
- Ignoring the Query: Many users assume the front end will update automatically. Specifically, you must verify your display settings to ensure they follow the new order.
- Wrong Content Type: Remember that product order does not affect page order. You must enable the logic for each specific post type.
- Widget Overrides: Some page builders use their own internal sorting logic. Consequently, you may need to adjust those specific widget settings to “Manual.”
Final Takeaway 💎
If you want to curate your WordPress site with surgical precision, drag-and-drop sorting is the answer. It provides the visual control needed to highlight your best work and products instantly. Architect your site your way—simple, fast, and bloat-free.
Ready to reorder? Save your snippet and start curating your content today. 🚀
/**
* Universal Admin Reorder (PATCHED)
* Fixes:
* - DO NOT force posts_per_page = -1 (keeps pagination fast)
* - DO NOT interfere with admin-ajax (Quick Edit / inline-save)
* - Save Quick Edit menu_order WITHOUT wp_update_post recursion
* - Minor hardening + cleanup for columns/bulk actions across supported post types
*/
/**
* 1) Enable menu_order support for all public post types including WooCommerce Products
*/
add_action('init', function () {
$post_types = get_post_types(['public' => true], 'names');
foreach ($post_types as $pt) {
// Add "page-attributes" support (menu_order lives here in WP UI)
if (!post_type_supports($pt, 'page-attributes')) {
add_post_type_support($pt, 'page-attributes');
}
// Ensure products also have it (some setups omit it)
if ($pt === 'product' && !post_type_supports($pt, 'page-attributes')) {
add_post_type_support($pt, 'page-attributes');
}
}
}, 20);
/**
* 2) Default admin post order by menu_order when supported and no explicit sort selected
* PATCH: do NOT set posts_per_page = -1, and do NOT run during AJAX (Quick Edit)
*/
add_action('pre_get_posts', function ($q) {
if (!is_admin() || !$q->is_main_query()) return;
// Critical: do not touch admin-ajax requests (Quick Edit / inline-save etc.)
if (wp_doing_ajax()) return;
// Only on list table screens (edit.php)
if (!function_exists('get_current_screen')) return;
$screen = get_current_screen();
if (!$screen || $screen->base !== 'edit') return;
$post_type = $q->get('post_type');
if (!$post_type) return;
// Some admin screens provide array post_type – normalize
if (is_array($post_type)) {
$post_type = reset($post_type);
}
if (!post_type_supports($post_type, 'page-attributes')) return;
// If user chose an orderby that isn't menu_order, respect it
$orderby = isset($_GET['orderby']) ? sanitize_key($_GET['orderby']) : '';
if ($orderby && $orderby !== 'menu_order') return;
$q->set('orderby', 'menu_order');
$q->set('order', 'ASC');
// PATCH: keep pagination (no posts_per_page = -1)
}, 20);
/**
* 3) Enqueue jQuery UI Sortable
*/
add_action('admin_enqueue_scripts', function () {
wp_enqueue_script('jquery-ui-sortable');
});
/**
* 4) Add reorder toggle button and script (edit.php only)
*/
add_action('admin_footer-edit.php', function () {
if (!function_exists('get_current_screen')) return;
$screen = get_current_screen();
if (!$screen || empty($screen->post_type)) return;
if (!post_type_supports($screen->post_type, 'page-attributes')) return;
$nonce = wp_create_nonce('universal_order_nonce');
$post_type = esc_js($screen->post_type);
?>
Reorder Mode Active: Drag the handles to reorder items. Changes save automatically. Click "Toggle Reorder" again when done.
Saving order...
$post_type,
'posts_per_page' => -1,
'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
'orderby' => 'menu_order',
'order' => 'ASC',
'fields' => 'ids',
];
$all_ids = get_posts($args);
if (!in_array($post_id, $all_ids, true)) {
wp_send_json_error('Post ID not found');
}
$from = array_search($post_id, $all_ids, true);
array_splice($all_ids, $from, 1);
array_splice($all_ids, $new_index, 0, $post_id);
// Fast update (avoid triggering save_post hooks repeatedly)
global $wpdb;
foreach ($all_ids as $index => $id) {
$wpdb->update(
$wpdb->posts,
['menu_order' => (int) $index],
['ID' => (int) $id],
['%d'],
['%d']
);
clean_post_cache((int) $id);
}
wp_send_json_success('Order saved');
});
/**
* 6) WooCommerce respects menu_order when selected
*/
add_filter('woocommerce_default_catalog_orderby_options', function ($options) {
$options['menu_order'] = 'Default sorting';
return $options;
});
add_filter('woocommerce_get_catalog_ordering_args', function ($args) {
if (isset($_GET['orderby']) && $_GET['orderby'] === 'menu_order') {
$args['orderby'] = 'menu_order title';
$args['order'] = 'ASC';
}
return $args;
});
/**
* 7) Add drag handle and "Order" columns to admin tables
* PATCH: avoid duplicate manage_edit-{$pt}_columns filters by using one filter to add both
*/
add_action('admin_init', function () {
$post_types = get_post_types(['public' => true], 'names');
foreach ($post_types as $pt) {
if (!post_type_supports($pt, 'page-attributes')) continue;
// Add drag handle + Order column
add_filter("manage_edit-{$pt}_columns", function ($columns) {
// Insert handle at start
$columns = array_merge(['reorder_handle' => ''], $columns);
// Add order column (near end)
$columns['menu_order'] = 'Order';
return $columns;
});
// Populate columns
add_action("manage_{$pt}_posts_custom_column", function ($column, $post_id) {
if ($column === 'menu_order') {
$order = (int) get_post_field('menu_order', $post_id);
echo '' . esc_html($order + 1) . '';
} elseif ($column === 'reorder_handle') {
echo '';
}
}, 10, 2);
// Make Order column sortable
add_filter("manage_edit-{$pt}_sortable_columns", function ($columns) {
$columns['menu_order'] = 'menu_order';
return $columns;
});
}
});
/**
* 8) Add bulk actions for order management (ALL supported post types)
* PATCH: apply to every page-attributes-supported post type, not just post/page.
*/
add_filter('bulk_actions-edit-post', 'universal_order_add_bulk_actions');
add_filter('bulk_actions-edit-page', 'universal_order_add_bulk_actions');
add_action('admin_init', function () {
$post_types = get_post_types(['public' => true], 'names');
foreach ($post_types as $pt) {
if (in_array($pt, ['post', 'page'], true)) continue;
if (!post_type_supports($pt, 'page-attributes')) continue;
add_filter("bulk_actions-edit-{$pt}", 'universal_order_add_bulk_actions');
}
});
function universal_order_add_bulk_actions($bulk_actions) {
if (!function_exists('get_current_screen')) return $bulk_actions;
$screen = get_current_screen();
if ($screen && !empty($screen->post_type) && post_type_supports($screen->post_type, 'page-attributes')) {
$bulk_actions['reset_order'] = 'Reset Order';
$bulk_actions['reverse_order'] = 'Reverse Order';
}
return $bulk_actions;
}
/**
* 9) Handle bulk actions (ALL supported post types)
*/
add_filter('handle_bulk_actions-edit-post', 'universal_order_handle_bulk_actions', 10, 3);
add_filter('handle_bulk_actions-edit-page', 'universal_order_handle_bulk_actions', 10, 3);
add_action('admin_init', function () {
$post_types = get_post_types(['public' => true], 'names');
foreach ($post_types as $pt) {
if (in_array($pt, ['post', 'page'], true)) continue;
if (!post_type_supports($pt, 'page-attributes')) continue;
add_filter("handle_bulk_actions-edit-{$pt}", 'universal_order_handle_bulk_actions', 10, 3);
}
});
function universal_order_handle_bulk_actions($sendback, $doaction, $post_ids) {
if ($doaction !== 'reset_order' && $doaction !== 'reverse_order') {
return $sendback;
}
if (!function_exists('get_current_screen')) return $sendback;
$screen = get_current_screen();
if (!$screen || empty($screen->post_type)) return $sendback;
$args = [
'post_type' => $screen->post_type,
'posts_per_page' => -1,
'post_status' => ['publish', 'draft', 'pending', 'future', 'private'],
'orderby' => $doaction === 'reverse_order' ? 'menu_order' : 'date',
'order' => $doaction === 'reverse_order' ? 'DESC' : 'ASC',
'fields' => 'ids',
];
$all_ids = get_posts($args);
global $wpdb;
foreach ($all_ids as $index => $id) {
$wpdb->update(
$wpdb->posts,
['menu_order' => (int) $index],
['ID' => (int) $id],
['%d'],
['%d']
);
clean_post_cache((int) $id);
}
$sendback = add_query_arg('bulk_order_updated', count($all_ids), $sendback);
return $sendback;
}
/**
* 10) Display admin notice for bulk actions
*/
add_action('admin_notices', function () {
if (!empty($_REQUEST['bulk_order_updated']) && !empty($_REQUEST['_wp_http_referer'])) {
$count = (int) $_REQUEST['bulk_order_updated'];
echo '';
echo sprintf('Order updated for %d item%s.', $count, $count !== 1 ? 's' : '');
echo '
';
?>
update(
$wpdb->posts,
['menu_order' => $new_order],
['ID' => (int) $post_id],
['%d'],
['%d']
);
clean_post_cache((int) $post_id);
}, 10, 1);

Huge thanks to Imran Siddiq - Web Squadron for architecting this tutorial!
❓FAQ:
Can I reorder WooCommerce products manually?
🛠️ Yes. This is a powerful way to ensure your most profitable products appear at the top of your shop grid without changing their publish dates.
Does this work for custom post types?
💎 Absolutely. Whether it’s a portfolio or a team list, the snippet can be configured to work with any registered post type.
Why is my new order not showing on the site?
🔍 The most likely reason is that your front-end query is still sorting by another rule (like date). Change the “Order By” setting in your widget or template to “Menu Order.”
Do I need a premium plugin for this?
❌ No. By using Code Snippets Pro, you can add this functionality with a lightweight snippet, keeping your site fast and clean. 🏎️💨