How to automatically hide Draft and Private links from WordPress menu

One of my clients was updating his website content. Since website is public, client needed to temporary hide few pages from visitors until the new content is ready. The issue was that these pages also show up in website menu, and showing broken links in popular website’s menu is not a user-friendly solution.

So after some digging in I came up with a simple solution. I added a function which automatically hides Draft and Private posts and pages from WordPress menu. Here you’ll find super simple tutorial how to add this function to your websites too.

How to automatically hide Draft and Private pages (or posts) from any WordPress menu without CSS

To hide private and draft posts and pages from WordPress menu you need to go to Appearance >> Theme Editor in WordPress admin menu, and open theme’s functions.php file.

Here is the function which you need to the end of the functions.php file:

function imakeitwork_hide_unpublished_from_menu($items, $args) {
	 foreach ($items as $itemID => $object) {
	  	if ( (get_post_status($object->object_id)=='draft') || (get_post_status($object->object_id)=='private') )  {
	   		unset ($items[$itemID]);
	  }
 	}
 return $items;
}
add_filter ('wp_nav_menu_objects', 'imakeitwork_hide_unpublished_from_menu', 10, 2);

This function runs through every single WordPress frontend menu item, and checks if menu item has status draft or private. If it has one of these statuses, it gets removed from menu.

It only makes changes to client side of the website, so pages show up in the menu again once they change their status to published.

If you only want to hide draft pages and posts from WordPress menu, replace line this line

if ( (get_post_status($object->object_id)=='draft') || (get_post_status($object->object_id)=='private') )  {

with

if (get_post_status($object->object_id)=='draft') {

line.

If you only want to hide private posts and pages from WordPress menu, replace the same line with this:

if (get_post_status($object->object_id)=='private') {

That should do the trick!

If you can’t see changes after adding the function, check your WordPress cache plugin. After clearing cache you should see the updated menu.