Last Updated:

Additional fields for the WP_Nav_Menu menu

From version WordPress 5.4 there are new hooks that allow you to more flexibly customize the WordPress menu (WP Nav Menu). In particular, it has become possible to easily add custom (additional) fields to the WordPress menu.

We are talking about hooks wp_nav_menu_item_custom_fields and wp_nav_menu_item_custom_fields_customize_template. With their help, you can now easily add your own arbitrary fields to menu items both on the menu editing page in the admin panel and in the Customizer panel.

In this post, we'll look at using the wp_nav_menu_item_custom_fields hook to add your own custom fields to menu items. Also consider plugins that allow you to do the same thing without writing code.

Let's add fields to the menu using PHP code

The code below uses two hooks to create a new field in the menu:_menu_item_svg_icon

  • wp_nav_menu_item_custom_fields - allows you to display HTML code in the admin panel menu.
  • wp_update_nav_menu_item - allows you to save the added fields in the metafields of the menu item (let me remind you that menu items are stored in the wp_posts table and use the standard metapoles of posts).

Two hooks are also used to process the output of the created field. Here in the field is stored the name of the SVG icon file. When displaying the menu and a little crutch, but in a simple way, we add the placeholder to the basic HTML markup of the element and then replace it with an SVG image.

<?php final class WP_Nav_Menu_Custom_Fields { public static array $field_keys = [ '_menu_item_svg_icon' => [ 'title' => 'SVG Icon Name', 'desc' => 'Set svg icon name (not url)' , ], 'test_number_field' => [ 'title' => 'Number One', 'type' => 'number', 'size' => 'thin',  thin | wide  'desc' => 'some text',  ], 'test_number_field_two' => [ 'title' => 'Number Two', 'type' => 'number', 'size' => 'thin',  thin | wide  'desc' => 'some text', ], ]; public static function init(): void { if( is_admin() ){ add_action( 'wp_nav_menu_item_custom_fields', [ __CLASS__, 'add_fileds' ], 10,  2 ); add_action( 'wp_update_nav_menu_item', [ __CLASS__, 'save_fields' ], 10, 2 ); } // front else { add_filter( 'walker_nav_menu_start_ el', [ __CLASS__, 'nav_menu_start_el' ], 10, 2 ); add_filter( 'wp_nav_menu_args', [ __CLASS__, 'nav_menu_args' ] ); }  } public static function add_fileds( $item_id, $item ) { foreach( self::$field_keys as $meta_key => $data ){ $value =  get_post_meta( $item_id, $meta_key, true ); $title = $data['title']; $type = $data['type'] ? ? 'text'; $size = $data['size'] ? ? 'wide'; $desc = empty( $data['desc'] ) ? '' : '<span class='description'>'. $data['desc'] . '</span>'; ?> <p class="field-<?= $meta_key ?> description description-<?=  $size ?>"> <?= $title ?> <br /> <input class="widefat edit-menu-item-<?= $meta_key ?>" type="<?= $type ?>" name="<?= sprintf( '%s[%s]', $meta_key , $item_id ) ?>" id="menu-item-<?= $item_id ?>" value="<?= esc_attr( $value ) ?>"/> <?= $desc ? > </p> <?php } } public static function save_fields( $menu_id, $item_id ) { foreach( self::$field_keys as $meta_key => $data ) { self::save_field( $menu_id, $item_id, $meta_key ); } } private static function save_field( $menu_id, $item_id, $meta_key ) { if( ! isset( $_POST[ $meta_key ][ $item_id ] ) ){ return; } $val = $_POST[ $meta_key ][ $item_id ]; if( $val ){ update_post_meta( $item_id, $meta_key, sanitize_text_field( $val ) ); } else{ delete_post_meta( $item_id, $meta_key ); } }  public static function nav_menu_start_el( $item_output, $post ){ $svg = $post->_menu_item_svg_icon ? : ''; if( $svg ){ $svg = get_svg( $svg ); } return str_replace( '{SVG}', $svg, $item_output ); }  public static function nav_menu_args( $args ){ if( empty( $args['link_before'] ) ){ $args['link_before'] = '{SVG}'; } return $args; } }

After installing this code (create a file from this code and connect it to functions.php), you need to run it with this line in the functions file.php:


Now when we go to the admin panel page "Appearance > > Menus" we will see new fields there:


Retrieving Fields

To get the fields on the output, use the get_post_meta() function:

$field_value = get_post_meta( $item_id, $field_key, true );

You can use such code, for example, in the start_el() method when you create your own class to handle menu output. Or in hooks that change the output of the navigation menu.

Add fields to the menu using the Advanced Custom Fields (ACF) plugin

The very popular and versatile Advanced Custom Fields plugin once again demonstrates its flexibility by allowing you to add custom fields to the WordPress menu.

After installing and activating the plugin, open it and click on the "Add New" button to add fields. Select 'Menu Item' in the location rules. Follow the instructions and update the fields as needed.


After publishing the field, you can go to the WordPress menu from the admin area to see the new field you created. Pretty simple!

Let's add fields to the menu using the WP Menu Custom Fields plugin

The WP Menu Custom Fields plugin is a relatively new plugin that, as the name suggests, will help you add custom fields to your menu items. You can add custom text, image, shortcode, or custom HTML.

Instead of creating custom menu items through the plugin's special interface (as is done with Advanced Custom Fields), WP Menu Custom Fields adds editable parameters directly to any menu item in the admin menu editing area.

Custom menu

It's pretty easy to use and is a handy way to add custom fields and other content to menu items. The plugin documentation also provides plugin hooks that you can use to further customize the HTML generation of each feature.