I have tried to add custom li to my wordpress header menu using functions.php. Here is my code in function file.

function register_header_menu() {
   register_nav_menu('header-menu',__( 'Header Menu' ));
add_action( 'init', 'register_header_menu' );

add new element to header menu

function add_new_item($items, $args) {
   if( $args->theme_location == 'header-menu' ){
    $items .= '<li> <a>Show whatever</a></li>';
    return $items;
add_filter('wp_nav_menu_items', 'add_new_item');

I'm using below code to add menu into header.php

wp_nav_menu( array(
  'theme_location' => 'header-menu',
  'container'    => 'ul',
  'menu_class' => 'menu',
) ); ?>

Menu is visible on header, but my new item is not visible in the menu. How can I fix it?

  • 1
    Your callback function is missing the $args arg because you didn't set the proper number of args passed to the function via add_filter(). add_filter('wp_nav_menu_items', 'add_new_item', 10, 2); would fix it.
    – Sally CJ
    Feb 26, 2019 at 7:06
  • @SallyCJ Thanks for your answer, I have tried it but it's not working.
    – Udara
    Feb 26, 2019 at 7:13
  • What is the output of var_dump( $args ); ? But you could also use the items_wrap option when you call wp_nav_menu().
    – Sally CJ
    Feb 26, 2019 at 7:20
  • 1
    @SallyCJ Thank you very much, it's working now. Seems something wrong with my menu. I have deleted it and create a new one. Now it's working.
    – Udara
    Feb 26, 2019 at 7:43

2 Answers 2


Default usage of add_filter looks like this:

add_filter( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1 )

As you can see, the default priority is 10 and by default only one param is passed.

In your code you need your filter to get 2 params, because wp_nav_menu_items takes 2 params ($items and $args) and you need both of them in your filter. So you have to pass 2 as number of params, when you add your filter:

function add_new_item_to_menu( $items, $args ) {
    if ( 'header-menu' == $args->theme_location ) {
        $items .= '<li><a>Show whatever</a></li>';
    return $items;
add_filter( 'wp_nav_menu_items', 'add_new_item_to_menu', 10, 2 );
  • 1
    Sometimes I wish that the number of callback input arguments would just be automatically counted as a default :-)
    – birgire
    Feb 26, 2019 at 7:58

In addition to Krzysiek Dróżdż's answer:

If you show menu in Elementor widget, you can't check $args->theme_location So, I check by $args->menu == 'primary-menu'

Also it will be helpful if you show a menu in more then one place, this way, you can show it everywhere where menu with primary-menu is displayed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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