WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm planning to use a couple of custom post types for a plugin of mine. The whole plugin should reside under 1 toplevel menu item. Thus I would prefer a menu structure like so:

  • Dashboard
  • Posts
  • [...]
  • My Plugin

    • Custom Post Type #1
    • Custom Post Type #2
    • [...]

This is possible by including 'show_in_menu' => 'my_plugin_toplevel_menu_item_slug' in register_post_type when registering my custom post types. Howerer, there are a few issues I've come across using this method.

  • I have no say in how the title should be outputted. I would prefer to use <h2 class="nav-tab-wrapper"> ... </h2>, but now post.php prints the h2 output for me, and I don't know an easy way of overriding this. It is possible to do this with javascript as soon as the page is loaded, but this is a bit ugly in my opinion.
  • When using 'show_in_menu', the submenu page order cannot be altered. The custom post types are placed at the top automatically, because I guess Wordpress just gets to it quicker than I do.
  • The h2 icon disappears for some reason (I haven't really looked into this yet though, it might be very easy to solve).

Does anybody have an idea how to tackle these issues elegantly?


See temporary solution in my answer below.

share|improve this question
AFAIK, manipulating the global $submenu is the only way to do this. You should add your solution as an Answer. – brasofilo Feb 28 '13 at 5:56
I might come back and write an answer later, but I wonder if this would work: 1) set show_in_menu to true (for compatibility with other CPT-related plugins), use remove_menu_page() to remove menu item, use add_submenu_page() to add back to the correct location and with a custom page title. – mrwweb Aug 18 '14 at 23:45

The (temporary?) solution I've settled for, is the following:

  1. Use the show_in_menu parameter of register_post_type
  2. Use javascript to display custom title after page load
  3. Solve the submenu page order (which automatically puts the custom post types at the top, which is not my intention), with the following helper function:


// Sort the children of a given toplevel menu item
// Keep original order intact as much as possible, while
//  enforcing the [before => after] rules given by $force_order
function help_sort_submenu_items($toplevel_slug, $force_order) {
  global $submenu;

  $done = array();
  $hold = array();
  $newmenu = array();

  foreach ($submenu[$toplevel_slug] as $i => $item) {
    $force_after = array_search($item[2], $force_order);
    if ($force_after !== false && empty($done[$force_after])) {
      $hold[$item[2]] = $item;
    } else {
      $newmenu []= $item;
      $done[$item[2]] = true;

      $just_added_id = $item[2];
      while ($just_added_id = $force_order[$just_added_id]) {
        $next = $hold[$just_added_id];
        $newmenu []= $next;
        $done[$just_added_id] = true;

  $submenu[$toplevel_slug] = $newmenu;

Usage like so:

help_sort_submenu_items('my_plugin_toplevel_menu_item_slug', array(
  'submenu_page_with_this_slug_comes_before' => 'submenu_page_with_this_slug',
  'another' => 'rule'
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.