In one of my past WordPress projects, I faced a common but crucial challenge: creating a conditional login/logout menu item that dynamically changes based on whether a user is logged in or out. The client needed a professional menu that would show “Login” and “Register” options to visitors, but switch to “Logout” and “Profile” for authenticated users.
While there are plugins like Login Logout Menu by Adnan that can handle this task, I prefer minimizing plugin dependencies in my custom WordPress theme development. Excessive plugins can lead to maintenance headaches, performance issues, and security vulnerabilities. Plus, understanding the underlying code gives me more control over the functionality and user experience.
This case study walks through my custom implementation process, showing how I built this functionality from scratch without relying on third-party plugins.
Prerequisites
For this demonstration, I’m using:
- GeneratePress theme
- GeneratePress child theme
These themes provide a clean starting point, but the techniques apply to most WordPress themes with standard navigation.

Step 1: Creating the Login/Logout Meta Box
The first step involves adding a custom meta box to the WordPress menu editor. This meta box will contain our login/logout menu items that administrators can add to any navigation menu.
Here’s a peek at the function that adds our custom meta box:
function add_login_logout_meta_box() {
add_meta_box(
'login_logout_menu',
'Login Logout Menu',
'login_logout_meta_box_callback',
'nav-menus',
'side',
'default'
);
}
add_action('admin_head-nav-menus.php', 'add_login_logout_meta_box');
This function hooks into admin_head-nav-menus.php
to create a meta box in the WordPress menu editor. The meta box appears in the sidebar, making it easy for administrators to add these special menu items.

Step 2: Building the Meta Box Content
Once we’ve registered our meta box, we need to define its content. This involves creating an array of menu items (Login, Logout, Register, Profile) and rendering them as checkboxes in the meta box.
The callback function login_logout_meta_box_callback()
handles this by:
- Defining an array of menu items with special URL patterns (e.g.,
#loginpress-login#
) - Setting up default properties for each menu item
- Converting these items into objects for the WordPress menu system
- Rendering the meta box HTML with checkboxes
The special URL patterns are crucial as they serve as markers that our code will later detect and replace with the actual login/logout URLs.

Step 3: Processing Menu Functionality
With the meta box in place, we need to process these special menu items when they’re added to a navigation menu. This involves:
- Detecting our custom menu items by their URL patterns
- Extracting any redirect parameters
- Replacing the placeholder URLs with actual WordPress login/logout URLs
Here’s a snippet showing how we hook into wp_setup_nav_menu_item
:
function login_logout_setup_menu($menu_item) {
global $pagenow;
// Only process our custom menu items on the front-end
if ($pagenow != 'nav-menus.php' && !defined('DOING_AJAX') &&
isset($menu_item->url) && strpos($menu_item->url, '#loginpress-') !== false) {
// Process different item types based on URL pattern
// ...
}
return $menu_item;
}
add_filter('wp_setup_nav_menu_item', 'login_logout_setup_menu');
This function detects our special URL patterns and replaces them with the appropriate WordPress functions:
#loginpress-login#
becomeswp_login_url()
#loginpress-logout#
becomeswp_logout_url()
#loginpress-register#
becomeswp_registration_url()
#loginpress-profile#
becomesget_edit_profile_url()
Step 4: Controlling Menu Item Visibility
The final step is ensuring that menu items only appear when appropriate. For example, the “Login” item should be hidden when a user is already logged in.
We accomplish this by filtering the menu items before they’re displayed:
function login_logout_menu_objects($sorted_menu_items) {
foreach ($sorted_menu_items as $key => $item) {
// Skip non-login/logout menu items
if (strstr($item->url, '#loginpress') === false) {
continue;
}
// Hide login/register when logged in
if (is_user_logged_in()) {
if (strstr($item->url, '#loginpress-login#') ||
strstr($item->url, '#loginpress-register#')) {
unset($sorted_menu_items[$key]);
}
} else {
// Hide logout/profile when logged out
if (strstr($item->url, '#loginpress-logout#') ||
strstr($item->url, '#loginpress-profile#')) {
unset($sorted_menu_items[$key]);
}
}
}
return $sorted_menu_items;
}
add_filter('wp_nav_menu_objects', 'login_logout_menu_objects');
This function uses is_user_logged_in()
to determine which items should be visible and removes the others from the menu array.


Step 5: Testing Your Implementation
After implementing all four functions, it’s crucial to test the functionality:
- Add all login/logout items to your navigation menu
- View your site while logged out – you should only see Login and Register
- Log in to your site – the menu should switch to show Logout and Profile
- Test that clicking these links correctly performs the expected actions
Conclusion: Benefits of This Implementation
This custom implementation offers several advantages over using a plugin:
- Lightweight solution: No additional plugin overhead
- Full control: Easy to customize or extend the functionality
- Better security: Fewer dependencies means fewer potential vulnerabilities
- Learning opportunity: Deeper understanding of WordPress menu APIs
- Client satisfaction: Professional user experience with seamless navigation
By building this functionality directly into the theme, I’ve created a more maintainable solution that perfectly meets the project requirements while avoiding unnecessary dependencies.