Recommended Free Tools
You can add conditional logic to a WordPress menu in three practical ways: switch the entire menu assigned to a theme location, show or hide individual items with a visibility plugin, or filter menu items with PHP. Choose based on whether the condition applies to the whole navigation set or to specific links. Whatever method you use, treat menu logic as presentation only—the linked page still needs its own access control.
Choose the right type of conditional menu
| Requirement | Best starting point | What it does |
|---|---|---|
| Different menus for pages, categories, posts, or archives | Conditional Menus | Replaces the menu assigned to a theme location when its documented conditions match. |
| Show one item to logged-in visitors and another to logged-out visitors | IF Menu Visibility | Adds per-item visibility choices in Appearance > Menus. |
| Custom rules or site-specific behavior | PHP filters | Changes menu objects or the generated list-item HTML at a chosen WordPress hook. |
First identify whether you are replacing a complete navigation set or changing individual links. That decision determines both the plugin and the code hook you need.
Check the theme location and assigned menu first
WordPress renders a menu through wp_nav_menu(). The theme_location argument identifies a location registered by the theme, and the function displays the menu assigned to that location. If the location or menu is unavailable, WordPress uses the function’s documented fallback behavior, which can make a conditional change appear not to work.
- Open Appearance > Menus (or the menu management screen provided by your site).
- On Manage Locations, note the location used by the header or other navigation area and the menu assigned to it.
- Confirm that the front end is actually rendering that location through the standard menu function. Plugin compatibility descriptions generally assume this implementation.
For the function’s location, menu, and fallback arguments, see the wp_nav_menu() reference.
#1 Best Overall
Switch an entire menu with Conditional Menus
Conditional Menus is designed to assign different menus at theme locations according to conditions such as posts, pages, categories, and archive pages. Its controls are described under Appearance > Menus, particularly Manage Locations.
When this approach fits
- A blog archive needs category-specific navigation.
- A section of a site needs a different set of top-level links.
- You want administrators to manage the alternatives in the menu editor rather than maintain PHP.
Setup sequence
- Install and activate Conditional Menus from WordPress.org or your normal plugin workflow.
- Open Appearance > Menus > Manage Locations.
- Select the theme location used by the navigation.
- Assign the menu that should be the default, then configure the documented page, post, category, or archive conditions for alternatives.
- Save, then test each relevant URL type, including a single post, a page, a category archive, and any other condition you configured.
The listing describes compatibility with themes using the standard WordPress menu function; it does not establish that every block-navigation implementation behaves identically.
Show or hide individual links with IF Menu Visibility
IF Menu Visibility is intended for item-level rules. Its documented choices include showing an item to all visitors, logged-in visitors, or logged-out visitors.
Configure a visibility rule
- Install and activate IF Menu Visibility.
- Go to Appearance > Menus and expand the menu item you want to control.
- Choose the visibility setting for all, logged-in, or logged-out visitors.
- Save the menu and test in both an authenticated session and a private or logged-out browser window.
The plugin directory notes that a theme or plugin overriding the navigation-menu admin walker can prevent the visibility field from appearing. That is an integration caveat, not evidence that the feature fails on every site. If the field is missing, temporarily identify other menu-admin customizations and confirm that the theme is using the expected menu editor.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
Use PHP when the condition is custom
WordPress exposes filters at several stages. Use the stage that matches your requirement:
wp_get_nav_menu_itemsfilters the retrieved menu-item post objects.wp_nav_menu_objectsreceives sorted menu-item objects before HTML generation.wp_nav_menu_itemsreceives the final list-item HTML and thewp_nav_menu()arguments.
References: wp_get_nav_menu_items, wp_nav_menu_objects documentation in wp_nav_menu(), and wp_nav_menu_items.
Rank #4
Example: append a login or logout link to one location
This example changes only the location named primary. Add it to a site-specific plugin or a child theme’s functions.php, not a parent theme you update regularly.
<?php
add_filter( 'wp_nav_menu_items', function ( $items, $args ) {
if ( empty( $args->theme_location ) || 'primary' !== $args->theme_location ) {
return $items;
}
if ( is_user_logged_in() ) {
$items .= '<li class="menu-item menu-item-logout"><a href="' . esc_url( wp_logout_url( home_url( '/' ) ) ) . '">Log out</a></li>';
} else {
$items .= '<li class="menu-item menu-item-login"><a href="' . esc_url( wp_login_url() ) . '">Log in</a></li>';
}
return $items;
}, 10, 2 );
wp_nav_menu_items is an HTML-stage filter: return the complete list markup you want rendered. Because the callback receives the arguments object, checking theme_location prevents the rule from affecting every menu on the site.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsBest Value
Example: remove marked items before HTML is generated
For rules that remove or alter menu items, object-level filtering is usually easier to maintain. Add a CSS class such as members-only to selected items in the menu editor, then filter those objects:
<?php
add_filter( 'wp_nav_menu_objects', function ( $items, $args ) {
if ( empty( $args->theme_location ) || 'primary' !== $args->theme_location ) {
return $items;
}
foreach ( $items as $key => $item ) {
$classes = (array) $item->classes;
if ( in_array( 'members-only', $classes, true ) && ! is_user_logged_in() ) {
unset( $items[ $key ] );
}
}
return $items;
}, 10, 2 );
This hook receives sorted menu-item objects, so the callback can inspect item properties before WordPress builds the list HTML. Keep the location check if the class should have meaning in only one navigation.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Verify the result and troubleshoot failures
- Nothing changes: recheck the exact
theme_location, the assigned menu, and whether the theme callswp_nav_menu()for that area. - The wrong menus change: narrow the callback by location or by a specific menu identifier before returning the value.
- Items appear for everyone: test while logged in and logged out, clear page or object caches, and inspect the rendered HTML to confirm which menu is being output.
- The visibility control is absent: investigate a custom admin walker supplied by the theme or another plugin, as noted in the IF Menu Visibility listing.
- The code causes a fatal error: remove the snippet through hosting file access or a recovery-safe plugin workflow, then restore it with the correct callback arguments and PHP syntax.
Test every context covered by the rule: the relevant page type, archive, menu location, and authentication state. Also test keyboard navigation and mobile menu markup if your theme renders separate navigation structures.
Do not confuse hidden links with access control
Conditional navigation only changes what visitors see in the menu. A visitor who knows or discovers a URL may still request it directly. Protect private content with the site’s authentication, authorization, membership, or server-level controls, and verify those controls independently of the menu.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

