Admin Post Navigation

Author:Scott Reilly
First released:2009-06-15
Last update:2016-04-14
Compatibility:WP 4.0 – 4.5.8
Download:[ zip ]

Adds links to navigate to the next and previous posts when editing a post in the WordPress admin.

Extended Description

This plugin adds “← Previous” and “Next →” links to the “Edit Post” admin page if a previous and next post are present, respectively. The link titles (visible when hovering over the links) reveal the title of the previous/next post. The links link to the “Edit Post” admin page for the previous/next posts so that you may edit them.

By default, a previous/next post is determined by the next lower/higher valid post based on relative sequential post ID and which the user can edit. Other post criteria such as post type (draft, pending, etc), publish date, post author, category, etc, are not taken into consideration when determining the previous or next post. How posts are navigated, and post types and post statuses to restrict navigation can be customized via filters (see Filters section).

NOTE: Be sure to save the post currently being edited before navigating away to the previous/next post.

Links: Plugin Homepage | Plugin Directory Page | Author Homepage


The plugin is further customizable via six filters. Typically, these customizations would be put into your active theme’s functions.php file, or used by another plugin.

c2c_admin_post_navigation_orderby (filter)

The ‘c2c_admin_post_navigation_orderby’ filter allows you to change the post field used in the ORDER BY clause for the SQL to find the previous/next post. By default this is ‘ID’ for non-hierarchical post types (such as posts) and ‘post_title’ for hierarchical post types (such as pages). If you wish to change this, hook this filter. This is not typical usage for most users.


  • $field (string) The current ORDER BY field
  • $post_type (string) The post type being navigated


 * Modify how Admin Post Navigation orders posts for navigation by ordering
 * pages by 'menu_order' and posts by 'post_date'.
 * @param string $field     The field used to order posts for navigation.
 * @param string $post_type The post type being navigated.
 * @return string
function custom_order_apn( $field, $post_type ) {
    if ( 'page' === $post_type ) {
        return 'menu_order';
    } else {
        return 'post_date';
add_filter( 'c2c_admin_post_navigation_orderby', 'custom_order_apn', 10, 2 );

c2c_admin_post_navigation_post_statuses (filter)

The ‘c2c_admin_post_navigation_post_statuses’ filter allows you to modify the list of post_statuses used as part of the search for the prev/next post. By default this array includes ‘draft’, ‘future’, ‘pending’, ‘private’, and ‘publish’. If you wish to change this, hook this filter. This is not typical usage for most users.


  • $post_statuses (array) The array of valid post_statuses


 * Modify Admin Post Navigation to allow and disallow certain post statuses from being navigated.
 * @param array $post_statuses Post statuses permitted for admin navigation.
 * @return array
function change_apn_post_status( $post_statuses ) {
    // Add a post status.
    // Note: by default these are already in the $post_statuses array: 'draft', 'future', 'pending', 'private', 'publish'
    $post_statuses[] = 'trash';

    // Remove post status(es).
    $post_statuses_to_remove = array( 'draft' ); // Customize here.
    foreach ( $post_statuses_to_remove as $remove ) {
        if ( false !== $index = array_search( $remove, $post_statuses ) ) {
            unset( $post_statuses[ $index ] );

    return $post_statuses;
add_filter( 'c2c_admin_post_navigation_post_statuses', 'change_apn_post_status' );

c2c_admin_post_navigation_post_types (filter)

The ‘c2c_admin_post_navigation_post_types’ filter allows you to modify the list of post_types used as part of the search for the prev/next post. By default this array includes all available post types. If you wish to change this, hook this filter.


  • $post_types (array) The array of valid post_types


 * Modify Admin Post Navigation to only allow navigating strictly for posts.
 * @param array $post_types Post types that should have admin post navigation.
 * @return array
function change_apn_post_types( $post_types ) {
    return array( 'post' );
add_filter( 'c2c_admin_post_navigation_post_types', 'change_apn_post_types' );

 * Modify Admin Post Navigation to disallow navigation for the 'recipe' post type.
 * @param array $post_types Post types that should have admin post navigation.
 * @return array
function remove_recipe_apn_post_types( $post_types ) {
    if ( isset( $post_types['recipe'] ) ) {
        unset( $post_types['recipe'] ); // Removing a post type
    return $post_types;
add_filter( 'c2c_admin_post_navigation_post_types', 'remove_recipe_apn_post_types' );

c2c_admin_post_navigation_prev_text (filter)

The ‘c2c_admin_post_navigation_prev_text’ filter allows you to change the link text used for the ‘Previous’ link. By default this is ‘← Previous’.


  • $text (string) The ‘previous’ link text.


 * Changes the text for the 'previous' link to 'Older' output by the Admin Post Navigation plugin.
 * @param string $text The text used to indicate the 'next' post.
 * @return string
function my_c2c_admin_post_navigation_prev_text( $text ) {
    return 'Older';
add_filter( 'c2c_admin_post_navigation_prev_text', 'my_c2c_admin_post_navigation_prev_text' );

c2c_admin_post_navigation_next_text (filter)

The ‘c2c_admin_post_navigation_next_text’ filter allows you to change the link text used for the ‘Next’ link. By default this is ‘Next →’.


  • $text (string) The ‘next’ link text.


 * Changes the text for the 'next' link to 'Newer' output by the Admin Post Navigation plugin.
 * @param string $text The text used to indicate the 'next' post.
 * @return string
function my_c2c_admin_post_navigation_next_text( $text ) {
    return 'Newer';
add_filter( 'c2c_admin_post_navigation_next_text', 'my_c2c_admin_post_navigation_next_text' );

c2c_admin_post_navigation_display (filter)

The ‘c2c_admin_post_navigation_display’ filter allows you to customize the output links for the post navigation.


  • $text (string) The current output for the prev/next navigation link


 * Change the markup displayed by the Admin Post Navigation plugin.
 * @param string $text The text being output by the plugin.
 * @return string
function override_apn_display( $text ) {
    // Simplistic example. You could preferably make the text bold using CSS.
    return '<strong>' . $text . '</strong>';
add_filter( 'c2c_admin_post_navigation_display', 'override_apn_display' );

Find out more at the plugin’s WordPress Plugin Repository page.


Click to see full-size image.


  1. Unzip inside the /wp-content/plugins/ directory for your site (or install via the built-in WordPress plugin installer)
  2. Activate the plugin through the ‘Plugins’ admin menu in WordPress
  3. See documentation for available customizations, if so inclined

Frequently Asked Questions

Q. How do I change it so the previous/next links find the adjacent post according to post_date?
A. See the Filters section for the c2c_admin_post_navigation_orderby filter, which has just such an example.

Q. Can I change the link text to something other than “← Previous” and/or “Next →”?
A. Yes. See the Filters section for the c2c_admin_post_navigation_prev_text and/or c2c_admin_post_navigation_next_text filters, which have just such examples. To change or amend the overall markup for the links, look into the c2c_admin_post_navigation_display filter.

Release Log

2.0 (2016-01-14)

  • New: Add support for RTL display.
  • New: Enable post navigation for media when viewed/edited from list mode.
  • New: Move CSS into enqueuable .css file.
  • New: Move JS into enqueueable .js file.
  • Bugfix: Navigate non-hierarchical posts by post_date by default for more expected ordering.
  • Change: Use the_title_attribute() to get post title for use in attribute.
  • Remove: Delete add_css() and add_js().
  • Change: Add support for language packs:
    • Don’t load plugin translations from file.
    • Remove .pot file and /lang subdirectory.
  • Change: Note compatibility through WP 4.4+.
  • Change: Remove support for WordPress older than 4.0.
  • Change: Explicitly declare methods in unit tests as public.
  • Change: Update copyright date (2016).
  • New: Add inline documentation for class variables.
  • New: Create empty index.php to prevent files from being listed if web server has enabled directory listings.

1.9.2 (2015-08-19)

  • Bugfix: Fix so navigation links appear in WordPress 4.3 (by targeting h1 instead of h2). Backwards compatibility maintained.
  • Update: Note compatibility through WP 4.3+

1.9.1 (2015-07-08)

  • Bugfix: Fix JS placement of navigation links to target the desired h2, which may not always be the first on the page
  • Update: Add additional unit test using example for customizing post status navigation
  • Update: Fix incorrect example for excluding post statuses via filter
  • Update: Improve example for using hook to define custom order for navigation
  • Update: Remove unused line of code.
  • Update: Note compatibility through WP 4.2+

1.9 (2015-03-14)

  • Fix to only append navigation to the first h2 on the page. props @pomegranate
  • Add filter ‘c2c_admin_post_navigation_prev_text’ to allow customization of the previous navigation link text. props @pomegranate
  • Add filter ‘c2c_admin_post_navigation_next_text’ to allow customization of the next navigation link text. props @pomegranate
  • Restrict orderby value to be an actual posts table field
  • Add unit tests
  • Prevent querying for a post if there isn’t a global post_ID set or if no valid post_statuses were set
  • Cast result of ‘c2c_admin_post_navigation_post_statuses’ filter to an array to avoid potential PHP warnings with improper use
  • Improved sanitization of values returned via the ‘c2c_admin_post_navigation_post_statuses’ filter
  • Add docs for new filters
  • Documentation improvements
  • Reformat plugin header
  • Note compatibility through WP 4.1+
  • Update copyright date (2015)
  • Minor code reformatting (bracing, spacing)
  • Change documentation links to to be https
  • Add plugin icon
  • Regenerate .pot

1.8 (2013-12-29)

  • Hide screen option checkbox for metabox if JS hides metabox for inline use
  • Improve spacing within its metabox (when shown if JS is disabled)
  • Note compatibility through WP 3.8+
  • Update copyright date (2014)
  • Change donate link
  • Minor readme.txt tweaks (mostly spacing)
  • Update banner
  • Update screenshots


  • Add check to prevent execution of code if file is directly accessed
  • Note compatibility through WP 3.5+
  • Update copyright date (2013)
  • Move screenshots into repo’s assets directory


  • Use string instead of variable to specify translation textdomain
  • Re-license as GPLv2 or later (from X11)
  • Add ‘License’ and ‘License URI’ header tags to readme.txt and plugin file
  • Add banner image for plugin page
  • Remove ending PHP close tag
  • Minor documentation tweaks
  • Note compatibility through WP 3.4+


  • Add support for localization
  • Use post type label instead of post type name, when possible, in link title attribute
  • Use larr/rarr characters to denote direction of navigation instead of larquo/rarquo
  • Enhanced styling of navigation links
  • Hook ‘admin_enqueue_scripts’ action instead of ‘admin_head’ to output CSS
  • Hook ‘load-post.php’ to add actions for the post.php page rather than using $pagenow
  • Add version() to return plugin version
  • Add register_post_page_hooks()
  • Remove admin_init() and hook ‘do_meta_boxes’ in register_post_page_hooks() instead
  • Update screenshots for WP 3.3
  • Note compatibility through WP 3.3+
  • Drop compatibility with versions of WP older than 3.0
  • Update screenshots for WP 3.3
  • Tweak plugin description
  • Add link to plugin directory page to readme.txt
  • Minor code reformatting
  • Minor readme.txt reformatting
  • Update copyright date (2012)


  • Use ucfirst() instead of strtoupper() to capitalize post type name for metabox title
  • Note compatibility through WP 3.2+
  • Minor code formatting changes (spacing)
  • Add FAQ section to readme.txt
  • Fix plugin homepage and author links in description in readme.txt


  • Add support for navigation in other post types
    • Add filter ‘c2c_admin_post_navigation_post_types’ for customizing valid post_types for search
    • Enable navigation for all post types by default
    • Allow per-post_type sort order for navigation by adding $post_type argument when applying filters for ‘c2c_admin_post_navigation_orderby’
    • Pass additional arguments ($post_type and $post) to functions hooking ‘c2c_admin_post_navigation_post_statuses’
  • Ensure post navigation only appears on posts of the appropriate post_status
  • For hierarchical post types, order by ‘post_title’, otherwise order by ‘ID’ (filterable)
  • Move application of filters from admin_init() into new do_meta_box(), which is hooking ‘do_meta_box’ action, so they only fire when actually being used
  • Output JavaScript via ‘admin_print_footer_scripts’ action rather than ‘admin_footer’
  • Rename class from ‘AdminPostNavigation’ to ‘c2c_AdminPostNavigation’
  • Switch from object instantiation to direct class invocation
  • Explicitly declare all functions public static and class variables private static
  • Documentation tweaks
  • Note compatibility through WP 3.1+
  • Update copyright date (2011)


  • Change post search ORDER BY from ‘post_date’ to ‘ID’
  • Add filter ‘c2c_admin_post_navigation_orderby’ for customizing search ORDER BY field
  • Add filter ‘c2c_admin_post_navigation_post_statuses’ for customizing valid post_statuses for search
  • Deprecate (but still support) ‘admin_post_nav’ filter
  • Add filter ‘c2c_admin_post_navigation_display’ filter as replacement to ‘admin_post_nav’ filter to allow modifying output
  • Retrieve post title via get_the_title() rather than directly from object
  • Also strip tags from the title prior to use in tag attribute
  • Don’t navigate to auto-saves
  • Check for is_admin() before defining class rather than during constructor
  • esc_sql() on SQL strings that have potentially been filtered
  • Use esc_attr() instead of attribute_escape()
  • Store plugin instance in global variable, $c2c_admin_post_navigation, to allow for external manipulation
  • Fix localization of the two strings
  • Instantiate object within primary class_exists() check
  • Note compatibility with WP 3.0+
  • Drop compatibility with version of WP older than 2.8
  • Minor code reformatting (spacing)
  • Remove docs from top of plugin file (all that and more are in readme.txt)
  • Remove trailing whitespace in header docs
  • Add Upgrade Notice and Filters sections to readme.txt
  • Add package info to top of plugin file


  • Add PHPDoc documentation
  • Note compatibility with WP 2.9+
  • Update copyright date
  • Update readme.txt (including adding Changelog)


  • Add offset and limit arguments to query()
  • Only get ID and post_title fields in query, not *
  • Change the previous/next post query to ensure it only gets posts the user can edit
  • Note compatibility with WP 2.8+


  • Initial release

Copyright & Disclaimer

Copyright © 2009-2017 by Scott Reilly (aka coffee2code)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Discussion / Support

Have any questions, comments, or suggestions? Please provide them via the plugin’s support forum. I’ll do my best to reply in a timely fashion and help as best I can.

Unfortunately, I cannot provide guaranteed support, nor do I provide support via any other means.

Was this plugin useful useful to you? Consider giving it a rating. If you’re inclined to give it a poor rating, please first post to the support forum to give me a chance to address or explain the situation.