WordPress Plugin Documentation

WDD Drag & Drop Post Order

A fast, clean drag-and-drop interface to reorder posts, pages, and custom post types — with an optional feature to update publication dates to match the new order.

v1.0.0 WordPress 5.6+ GPL-2.0+ Author: WDD

What this plugin does

WDD Drag & Drop Post Order gives you a dedicated admin screen to drag posts into whatever order you want. Once you save, your site's front end will show posts in that exact order — no theme editing, no custom queries, no shortcodes.

It works by setting WordPress's built-in menu_order field on each post, then hooking into pre_get_posts to apply that order on the front end for any post type you've enabled.

Key features

  • Drag-and-drop reordering using jQuery UI Sortable
  • Works with Posts, Pages, and any registered Custom Post Type
  • Optional date update — automatically adjusts post dates to match the visual order
  • Three date-spacing options: per hour, per day, or per week
  • Live search with debounce and pagination for large libraries
  • One-click reset to restore default WordPress ordering
  • No configuration needed on the front end — ordering applies automatically

The plugin only modifies the front-end query order for post types you explicitly enable in Settings. All other post types are left completely untouched.


Requirements

RequirementMinimumNotes
WordPress 5.6 Tested up to 6.5
PHP 7.4 PHP 8.0+ recommended
User role manage_options Administrator access required
jQuery UI Bundled with WP Plugin enqueues jquery-ui-sortable automatically — nothing to install

Installation

Upload via WordPress admin (recommended)

  1. 1
    Go to Plugins → Add New
    In your WordPress dashboard navigate to Plugins → Add New Plugin.
  2. 2
    Click "Upload Plugin"
    Hit the Upload Plugin button at the top, then choose the wdd-drag-drop-post-order.zip file.
  3. 3
    Install & Activate
    Click Install Now, then Activate Plugin once it uploads.
  4. 4
    Configure Settings
    Go to Post Order → Settings to choose which post types to enable.

Manual installation (FTP)

  1. 1
    Extract the zip
    Unzip wdd-drag-drop-post-order.zip on your local machine.
  2. 2
    Upload via FTP
    Upload the wdd-drag-drop-post-order/ folder to /wp-content/plugins/ on your server.
  3. 3
    Activate in WordPress
    Go to Plugins → Installed Plugins and click Activate.

After activation a new Post Order item appears in your WordPress sidebar with two sub-pages: Reorder and Settings.


The Reorder screen

This is your main working area — go to Post Order → Reorder to open it.

Post type tabs

If you've enabled more than one post type in Settings, you'll see a tab row at the top. Click a tab to switch between post types. Each has its own completely separate order.

Switching tabs does not auto-save. If you have unsaved changes the browser will warn you. Always hit Save Order first.

Dragging posts

Each post row has a drag handle on the left (the dotted grid icon). Grab it and drag the row up or down. A blue placeholder shows where the post will land. You can re-drag as many times as you like before saving.

Search

Use the search box in the top-right to filter posts by title. Results update automatically after a short delay and pagination resets to page 1 on each search.

Saving

Once you're happy with the order, click Save Order. The button stays disabled until you make at least one drag. After saving the order is immediately applied on the front end.

Reset

The Reset button clears the custom menu_order for all posts of the current type, setting them back to 0. WordPress then falls back to its default sort (usually date descending). A confirmation dialog appears before anything changes.


The date update feature

When you toggle Update dates on the Reorder screen and save, the plugin rewrites the post_date of every post in the list to reflect the new order. This is useful when your theme or RSS feed displays dates and you want chronology to match visual order.

How the dates are calculated

The plugin uses the current time as a base and works backwards down the list:

  • First post in the list → gets right now as its date
  • Second post → gets now minus 1 interval
  • Third post → gets now minus 2 intervals
  • …and so on

The interval (hour, day, or week) is set under Settings → Date spacing. With "1 Day" spacing and 5 posts you'd get today, yesterday, the day before, and so on.

The toggle is per-save, not permanently sticky. Its default state is controlled by the Settings option. Leave it off for pure visual reordering — only switch it on when you actually want dates changed.

Date changes are permanent and cannot be undone from within the plugin. If you need to revert, restore post dates manually or from a database backup.


Settings reference

All settings live at Post Order → Settings and are stored in the wdd_ddpo_settings WordPress option as a serialised array.

SettingTypeDefaultDescription
post_types array ['post'] Which post types appear in the Reorder screen and get front-end ordering applied.
update_dates bool false Default state of the "Update dates" toggle on the Reorder screen.
date_spacing string 'hour' Time gap between posts when date updating is on. Accepts 'hour', 'day', or 'week'.

Reading settings programmatically

// Get all settings
$settings = get_option( 'wdd_ddpo_settings', [] );

// Or use the Settings class directly
$obj          = WDD_DDPO_Settings::get_instance();
$post_types   = $obj->get( 'post_types' );
$update_dates = $obj->get( 'update_dates' );
$spacing      = $obj->get( 'date_spacing' );

File structure

One class per file, all loaded from the main plugin entry point. No autoloader — simple and dependency-free.

wdd-drag-drop-post-order/
wdd-drag-drop-post-order.php← Entry point, constants, bootstrap
readme.txt← WordPress.org readme
documentation.html← This file
 
assets/
    css/
        admin.css← All admin UI styles
    js/
        admin.js← Drag/drop, AJAX, UI logic
 
includes/
    class-wdd-ddpo-settings.php← Option registration & sanitisation
    class-wdd-ddpo-admin.php← Menu pages, asset enqueueing
    class-wdd-ddpo-ajax.php← Three AJAX endpoints
    class-wdd-ddpo-query.php← Front-end query modifier
    views/
        main-page.php← Drag & drop screen HTML
        settings-page.php← Settings form HTML

Class responsibilities

ClassResponsibility
WDD_DDPO_Settings Singleton. Registers the WordPress option, sanitises input, and provides a get() helper for reading settings anywhere in the codebase.
WDD_DDPO_Admin Registers the admin menu and sub-pages, enqueues CSS/JS only on the plugin's own screens, and localises JS variables via wp_localize_script.
WDD_DDPO_Ajax Handles three wp_ajax_* actions: wdd_ddpo_save_order, wdd_ddpo_get_posts, and wdd_ddpo_reset_order. All require a valid nonce and manage_options capability.
WDD_DDPO_Query Hooks into pre_get_posts on the front end only, applying menu_order sorting for enabled post types on main queries.

Hooks & Filters

Use these hooks to customise the plugin's behaviour without editing its files. Add all custom code to your theme's functions.php or a site-specific plugin.

Filter
wdd_ddpo_enabled_post_types
Override which post types get front-end ordering applied, independently of the Settings option.
add_filter( 'wdd_ddpo_enabled_post_types', function( $post_types ) {
    $post_types[] = 'portfolio';
    return $post_types;
} );
Filter
wdd_ddpo_posts_per_page
Change how many posts load per page in the Reorder screen. Default is 50.
add_filter( 'wdd_ddpo_posts_per_page', function( $per_page ) {
    return 100;
} );
Action
wdd_ddpo_after_save_order
Fires after the order has been saved. Receives the ordered array of post IDs and the post type string.
add_action( 'wdd_ddpo_after_save_order', function( $post_ids, $post_type ) {
    // Example: clear a custom cache after reordering
    my_plugin_clear_cache( $post_type );
}, 10, 2 );
Filter
wdd_ddpo_query_args
Modify the WP_Query args used to fetch posts in the Reorder screen before the query runs.
add_filter( 'wdd_ddpo_query_args', function( $args, $post_type ) {
    if ( $post_type === 'product' ) {
        $args['post_status'] = 'publish';
    }
    return $args;
}, 10, 2 );

Never edit plugin files directly — your changes will be overwritten on update. Always use hooks in an external file.


Frequently asked questions

Yes. Once you save an order the plugin hooks into WordPress's pre_get_posts to sort those posts by menu_order on all main queries for that post type. Standard themes using WP_Query or get_posts() pick it up automatically.
It only modifies the query order for post types you enable. If your theme runs its own custom WP_Query with a hardcoded orderby those queries won't be affected — only the site's main query is modified.
Yes — any public custom post type registered on your site appears in Settings. Enable it there and it shows up as a tab in the Reorder screen.
Nothing at all. The date update feature is completely opt-in per save. Your original publication dates stay exactly as they are — only the menu_order value changes.
The menu_order values written to your posts stay in the database after deactivation — WordPress just won't apply them to queries without the plugin's hook. Reactivating restores full functionality immediately. Settings also persist unless you fully delete the plugin.
The Reorder screen loads 50 posts at a time via pagination so the initial load stays fast. Saving sends the current page's post IDs in a single AJAX call. For very large sets consider using the search filter to work with smaller subsets at a time.
WooCommerce products (product) will appear in Settings. The plugin sets menu_order correctly, but whether your shop pages respect it depends on WooCommerce's own sort setting. Go to WooCommerce → Settings → Products → Default product sorting and set it to Custom ordering.

Changelog

1.0.0 June 2025
NewInitial release — drag-and-drop reorder screen with jQuery UI Sortable
NewSupport for Posts, Pages, and all public custom post types
NewOptional date update on save with configurable hour / day / week spacing
NewLive search with debounce and pagination
NewReset button with confirmation modal
NewFront-end query modifier via pre_get_posts
NewSettings page with post type selector and date controls
WDD Drag & Drop Post Order — v1.0.0
Built by WDD · GPL-2.0+