Steve Taylor photo

Customize the WordPress admin menus

NOTE: Forget these workarounds! We’ve now got core functions to do the trick :) Check out Justin Tadlock’s tutorial on using them.

Also, to disable theme and plugin editing, don’t just remove the menu links. You can use a constant in wp-config.php to completely switch that functionality off.

I’ve recently been looking at de-cluttering the WordPress admin interface. There’s some good plugins for this, such as Adminimize, WP-CMS Post Control (for hiding boxes on the post screen, according to user role) and White Label CMS (for extensive customization of logos, menus, etc.).

As ever, I’m also interested in getting just a particular aspect working with a bit of theme code—if only one aspect is needed, it’s sometimes nice to drop it into the theme and have one less plugin loading. The aspect I’m thinking of here is removing a few menu items.

So, with the usual caveat that this is code for theme developers, to be dropped into the active theme’s functions.php file, and a nod to for initial inspiration, here goes.

The code is as follows:

// Customize menus
function slt_customizeAdminMenus() {
	// Remove theme / plugin editors
	slt_removeSubmenu( 'themes.php', 'theme-editor.php' );
	slt_removeSubmenu( 'plugins.php', 'plugin-editor.php' );
	// Remove comments / categories / tags
	slt_removeMenu( 'edit-comments.php' );
	slt_removeSubmenu( 'edit.php', 'edit-tags.php?taxonomy=category' );
	slt_removeSubmenu( 'edit.php', 'edit-tags.php?taxonomy=post_tag' );
add_action( 'admin_head', 'slt_customizeAdminMenus' );

// Remove item from a submenu
function slt_removeSubmenu( $parentMenuItem, $item ) {
	global $submenu;
	//mail( "your@email.address", "$submenu", print_r( $submenu, true ) );
	foreach ( $submenu as $menuKey => $menuItem ) {
		if ( $menuKey == $parentMenuItem ) {
			foreach ( $menuItem as $submenuKey => $submenuItems ) {
				if ( $submenuItems[2] == $item ) {
					unset( $submenu[$menuKey][$submenuKey] );

// Remove item from the main menu
function slt_removeMenu( $item ) {
	global $menu;
	//mail( "your@email.address", "$menu", print_r( $menu, true ) );
	foreach ( $menu as $menuKey => $menuItem ) {
		if ( $menuItem[2] == $item ) {
			unset( $menu[$menuKey] );

The first function is added to the admin_head hook, to modify the arrays that have been set up containing the menu items remove the appropriate menus. If you’re curious, you can uncomment those two lines of mail() code in the other functions, and insert your email address—load a WP admin page and you should get two emails showing the contents of these global menu arrays. The way the rest of the above code works will then be much clearer.

So, basically the two following functions are there to remove specified items—either submenu items or entire top-level items. The first function just calls them as appropriate. My main two removals are getting rid of the Theme and Plugin Editor links—I never use these and never really want clients to use them. There’s also lines to remove the Categories, Tags, and Comments stuff. In my own themes, I have settings to globally turn these on or off, and these lines remove each item only if it’s been disabled. You can comment out / leave in whichever lines are appropriate, depending on what WP features your site uses.

Please note that this code does not disable or block the use of these features. People logged into WP, with the right permissions, could in theory type in the URL to, say, the Plugin Editor, and use it as normal. All the above is doing is tidying the menus up to give clients less unnecessary clutter.

Anyway, have fun with the code, and please post any suggestions here!

UPDATE 18/8/10: Improved code based on Mathias’ suggestion, to modify $menu and $submenu global variables within the second two functions themselves.


  1. Rich avatar Rich

    Nice code. Clean. But can you give an example using the //Remove item from main menu, please? For example, removing the main ‘links’ menu. I just can’t quite figure out which part of the code to change to specify which menu I want removed.

  2. Line 10 removes the comments menu. If you check the post I referred to for this, you’ll see a dump of the arrays that contain the menus. You should be able to figure anything else out from that. Though actually, it may be as simple as checking the page that the menu links to. As you can see from line 10, the item argument passed to slt_removeMenu is “edit-comments.php”—just the page that the comments menu links to. Following that logic should help, too.

  3. Mathias avatar Mathias

    What do you think of doing it this way:

    This makes it even simpler by placing the call to the global $submenu and $menu variables inside slt_removeMenu() and slt_removeSubmenu. This way you don’t need to pass them as a function parameter nor redefine them for each removed item.

    By the way, thanks for your code. : )


  4. Mathias avatar Mathias

    Just realized that you don’t need to call the global $menu variable inside slt_removeSubmenu(). Just calling global $submenu is fine (line 19).

  5. Mathias, you’re probably right – seems like a better-contained way of doing this. I’ll update the code above when I get a minute! Thanks.

  6. Shonda avatar Shonda

    I’m about to edit the functions.php file, but exactly where should I put the code you are suggesting? At the top or at the bottom? Does it matter? I do not have any experience with PHP. Thanks.

  7. Shonda avatar Shonda

    Hello Again… The code is working, because it’s mailing information to me, but there aren’t any changes taking place. I’m running 3.0.1 (Multisite – only 1 additional site that does not belong to the SuperAdmin) – do you think I need to do something different?

  8. Shonda, I’ve not tested this code on a multisite system, but on the other hand I’m not sure why it wouldn’t work.

    Maybe you’re better off with one of the plugins mentioned at the start of the post?

  9. I couldn’t get this to work either (3.0, Thematic theme). But for whatever reason, the github code worked a-okay.

  10. Shonda, Rich, everyone else, apologies. It seems a couple of typos have crept into the code, specifically at lines 21 and 35. The unset statements weren’t referencing the right arrays! It’s corrected now, should work :)

  11. Fantastic! WordPress has a lot more menu options than the average client looking for a CMS needs or wants. This makes it easier to streamline the admin and strip out tools that could inadvertently be used break the theme. Thank you!!

  12. Peter avatar Peter

    Hey Steve, good job! Any ideas on how to remove the post_tag submenu from a custom post type menu? Something like:

    slt_removeSubmenu( 'edit.php', 'edit-tags.php?taxonomy=post_tag&post_type=myproduct );

    doesn’t seem to do the trick.

  13. Huroman avatar Huroman

    Hi, is it possible to unset/disable some categories from the admin (adminroot/edit-tags.php?taxonomy=category)?

    Thank you.

  14. Huroman avatar Huroman

    Ok, never mind, i realized how to using:
    if($terms[$key]->term_id == 7){unset($terms[$key]);}

    but i have another question, is it possible to unset it (the cagetory) in post.php (categorydiv, the postbox)?

    Thank you.

  15. Hi to anyone subscribed to the comments here. Please check out the new notices I’ve added at the top of the post! Topic now closed :)

Comments are closed.