Title: add_menu_page
Published: April 25, 2014
Last modified: August 20, 2026

---

# add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $callback = '', string $icon_url = '', int|float $position = null ): string

## In this article

 * [Description](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#description)
 * [Parameters](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#return)
 * [More Information](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#more-information)
    - [Notes](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#notes)
    - [Menu Structure](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#menu-structure)
 * [Source](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#wp--skip-link--target)

Adds a top-level menu page.

## 󠀁[Description](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#description)󠁿

This function takes a capability which will be used to determine whether or not 
a page is included in the menu.

The function which is hooked in to handle the output of the page must check that
the user has the required capability as well.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#parameters)󠁿

 `$page_title`stringrequired

The text to be displayed in the title tags of the page when the menu is selected.

`$menu_title`stringrequired

The text to be used for the menu.

`$capability`stringrequired

The capability required for this menu to be displayed to the user.

`$menu_slug`stringrequired

The slug name to refer to this menu by. Should be unique for this menu page and 
only include lowercase alphanumeric, dashes, and underscores characters to be compatible
with [sanitize_key()](https://developer.wordpress.org/reference/functions/sanitize_key/).

`$callback`callableoptional

The function to be called to output the content for this page.

Default:`''`

`$icon_url`stringoptional

The URL to the icon to be used for this menu.

 * Pass a base64-encoded SVG using a data URI, which will be colored to match the
   color scheme. This should begin with `'data:image/svg+xml;base64,'`.
 * Pass the name of a Dashicons helper class to use a font icon, e.g. `'dashicons-
   chart-pie'`.
 * Pass `'none'` to leave div.wp-menu-image empty so an icon can be added via CSS.

Default:`''`

`$position`int|floatoptional

The position in the menu order this item should appear.

Default:`null`

## 󠀁[Return](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#return)󠁿

 string The resulting page’s hook_suffix.

## 󠀁[More Information](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#more-information)󠁿

### 󠀁[Notes](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#notes)󠁿

 * **Important Note:** Since WordPress 4.4, you do not need to worry about making
   the position number unique to avoid conflicts. See trac ticket [ #23316](https://core.trac.wordpress.org/ticket/23316)
   for more information.
 * If you’re running into the “You do not have sufficient permissions to access 
   this page” error, then you’ve hooked too early. The hook you should use is [admin_menu](https://developer.wordpress.org/reference/hooks/admin_menu/).
 * If you only want to move existing admin menu items to different positions, you
   can use the admin_menu hook to unset menu items from their current positions 
   in the global $menu and $submenu variables (which are arrays), and reset them
   elsewhere in the array.
 * This function takes a ‘capability’ (see [Roles and Capabilities](https://codex.wordpress.org/Roles_and_Capabilities))
   which will be used to determine whether or not a page is included in the menu.
   The function which is hooked in to handle the output of the page must check that
   the user has the required ‘capability’ as well.
 * If you are using the [Settings API](https://codex.wordpress.org/Settings_API)
   to save data, and need the user to be other than the administrator, will need
   to modify the permissions via the hook option_page_capability_{$option_group},
   where $option_group is the same as option_group in [register_setting()](https://developer.wordpress.org/reference/function/register_setting/).
   Check out the [Settings API](https://codex.wordpress.org/Settings_API).

### 󠀁[Menu Structure](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#menu-structure)󠁿

#### 󠀁[Default: bottom of menu structure](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#default-bottom-of-menu-structure)󠁿

 * 2 – Dashboard
 * 4 – Separator
 * 5 – Posts
 * 10 – Media
 * 15 – Links
 * 20 – Pages
 * 25 – Comments
 * 59 – Separator
 * 60 – Appearance
 * 65 – Plugins
 * 70 – Users
 * 75 – Tools
 * 80 – Settings
 * 99 – Separator

#### 󠀁[For the Network Admin menu, the values are different:](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#for-the-network-admin-menu-the-values-are-different)󠁿

 * 2 – Dashboard
 * 4 – Separator
 * 5 – Sites
 * 10 – Users
 * 15 – Themes
 * 20 – Plugins
 * 25 – Settings
 * 30 – Updates
 * 99 – Separator

## 󠀁[Source](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#source)󠁿

    ```php
    function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) {
    	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;

    	$menu_slug = plugin_basename( $menu_slug );

    	$admin_page_hooks[ $menu_slug ] = sanitize_title( $menu_title );

    	$hookname = get_plugin_page_hookname( $menu_slug, '' );

    	if ( ! empty( $callback ) && ! empty( $hookname ) && current_user_can( $capability ) ) {
    		add_action( $hookname, $callback );
    	}

    	if ( empty( $icon_url ) ) {
    		$icon_url   = 'dashicons-admin-generic';
    		$icon_class = 'menu-icon-generic ';
    	} else {
    		$icon_url   = set_url_scheme( $icon_url );
    		$icon_class = '';
    	}

    	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );

    	if ( null !== $position && ! is_numeric( $position ) ) {
    		_doing_it_wrong(
    			__FUNCTION__,
    			sprintf(
    				/* translators: %s: add_menu_page() */
    				__( 'The seventh parameter passed to %s should be numeric representing menu position.' ),
    				'<code>add_menu_page()</code>'
    			),
    			'6.0.0'
    		);
    		$position = null;
    	}

    	if ( null === $position || ! is_numeric( $position ) ) {
    		$menu[] = $new_menu;
    	} elseif ( isset( $menu[ (string) $position ] ) ) {
    		$collision_avoider = (int) base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001;
    		$position          = (string) ( $position + $collision_avoider );
    		$menu[ $position ] = $new_menu;
    	} else {
    		/*
    		 * Cast menu position to a string.
    		 *
    		 * This allows for floats to be passed as the position. PHP will normally cast a float to an
    		 * integer value, this ensures the float retains its mantissa (positive fractional part).
    		 *
    		 * A string containing an integer value, eg "10", is treated as a numeric index.
    		 */
    		$position          = (string) $position;
    		$menu[ $position ] = $new_menu;
    	}

    	$_registered_pages[ $hookname ] = true;

    	// No parent as top level.
    	$_parent_pages[ $menu_slug ] = false;

    	return $hookname;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-admin/includes/plugin.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.1/src/wp-admin/includes/plugin.php#L1392)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.1/src/wp-admin/includes/plugin.php#L1392-L1453)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#related)󠁿

| Uses | Description | 
| [get_plugin_page_hookname()](https://developer.wordpress.org/reference/functions/get_plugin_page_hookname/)`wp-admin/includes/plugin.php` |

Gets the hook name for the administrative page of a plugin.

  | 
| [sanitize_title()](https://developer.wordpress.org/reference/functions/sanitize_title/)`wp-includes/formatting.php` |

Sanitizes a string into a slug, which can be used in URLs or HTML attributes.

  | 
| [set_url_scheme()](https://developer.wordpress.org/reference/functions/set_url_scheme/)`wp-includes/link-template.php` |

Sets the scheme for a URL.

  | 
| [plugin_basename()](https://developer.wordpress.org/reference/functions/plugin_basename/)`wp-includes/plugin.php` |

Gets the basename of a plugin.

  | 
| [current_user_can()](https://developer.wordpress.org/reference/functions/current_user_can/)`wp-includes/capabilities.php` |

Returns whether the current user has the specified capability.

  | 
| [__()](https://developer.wordpress.org/reference/functions/__/)`wp-includes/l10n.php` |

Retrieves the translation of $text.

  | 
| [_doing_it_wrong()](https://developer.wordpress.org/reference/functions/_doing_it_wrong/)`wp-includes/functions.php` |

Marks something as being incorrectly called.

  | 
| [add_action()](https://developer.wordpress.org/reference/functions/add_action/)`wp-includes/plugin.php` |

Adds a callback function to an action hook.

  |

[Show 4 more](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#)

| Used by | Description | 
| [add_object_page()](https://developer.wordpress.org/reference/functions/add_object_page/)`wp-admin/includes/deprecated.php` |

Add a top-level menu page in the ‘objects’ section.

  | 
| [add_utility_page()](https://developer.wordpress.org/reference/functions/add_utility_page/)`wp-admin/includes/deprecated.php` |

Add a top-level menu page in the ‘utility’ section.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#changelog)󠁿

| Version | Description | 
| [1.5.0](https://developer.wordpress.org/reference/since/1.5.0/) | Introduced. |

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#user-contributed-notes)󠁿

 1.   [Skip to note 12 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-408)
 2.    [Codex](https://profiles.wordpress.org/codex/)  [  11 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-408)
 3.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-408)
     Vote results for this note: 17[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-408)
 4.  **Examples**
      Add a custom menu item to the WordPress admin menu, for a user with
     administrator capability:
 5.  _Method 1:_
 6.      ```php
         /**
          * Register a custom menu page.
          */
         function wpdocs_register_my_custom_menu_page() {
         	add_menu_page(
         		__( 'Custom Menu Title', 'textdomain' ),
         		'custom menu',
         		'manage_options',
         		'myplugin/myplugin-admin.php',
         		'',
         		plugins_url( 'myplugin/images/icon.png' ),
         		6
         	);
         }
         add_action( 'admin_menu', 'wpdocs_register_my_custom_menu_page' );
         ```
     
 7.  With this method the page-generating code should be located in `myplugin/myplugin-
     admin.php`:
 8.      ```php
         <?php esc_html_e( 'Admin Page Test', 'textdomain' ); ?>
         ```
     
 9.  _Method 2:_
 10.     ```php
         /**
          * Register a custom menu page.
          */
         function wpdocs_register_my_custom_menu_page(){
         	add_menu_page( 
         		__( 'Custom Menu Title', 'textdomain' ),
         		'custom menu',
         		'manage_options',
         		'custompage',
         		'my_custom_menu_page',
         		plugins_url( 'myplugin/images/icon.png' ),
         		6
         	); 
         }
         add_action( 'admin_menu', 'wpdocs_register_my_custom_menu_page' );
     
         /**
          * Display a custom menu page
          */
         function my_custom_menu_page(){
         	esc_html_e( 'Admin Page Test', 'textdomain' );	
         }
         ```
     
 11.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D408%23feedback-editor-408)
 12.  [Skip to note 13 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-4771)
 13.   [surwan](https://profiles.wordpress.org/surwan/)  [  6 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-4771)
 14. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-4771)
     Vote results for this note: 10[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-4771)
 15. To add a top-level menu item which resolves to a sub-menu item, the menu slugs
     of each _add\_menu\_page_ and _add\_submenu\_page_ calls need to match. **This
     is useful for when you need the top-level menu item label to be different to the
     first sub-level item**. Otherwise the top-level item label is repeated as the 
     first sub-level item.
 16. Minimal example –
 17.     ```php
         $menu_slug = 'wpdocs-orders-slug';
         add_menu_page( 'WP Docs Orders', 'WP Docs Orders', 'read', $menu_slug, false );
         add_submenu_page( $menu_slug, 'Existing WP Docs Orders', 'Existing WP Docs Orders', 'read', $menu_slug, 'wpdocs_orders_function' );
         ```
     
 18. In this example; when the ‘WP Docs Orders’ top-level item is selected, it will
     trigger the submenu item.
 19.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D4771%23feedback-editor-4771)
 20.  [Skip to note 14 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-2686)
 21.   [Felipe Elia](https://profiles.wordpress.org/felipeelia/)  [  8 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-2686)
 22. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-2686)
     Vote results for this note: 9[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-2686)
 23. If you pass a base64-encoded SVG using a data URI, it will only be colored to 
     match the color scheme **IF** it has a `fill` style attribute. The process is 
     done by `wp-admin/js/svg-painter.js`.
 24.  * I forgot to mention that this is about the icon to be used for this menu (`
        $icon_url`).
      * [Felipe Elia](https://profiles.wordpress.org/felipeelia/) [8 years ago](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-2702)
 25.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D2686%23feedback-editor-2686)
 26.  [Skip to note 15 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-5845)
 27.   [5Diraptor](https://profiles.wordpress.org/5diraptor/)  [  4 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-5845)
 28. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-5845)
     Vote results for this note: 9[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-5845)
 29. **Adding custom SVG icons.**
 30. I wrestled with this a bit and wanted to add in some notes when using the $icon_url
     parameter. From my experience and from looking on forums, using your custom icon
     isn’t as easy as just creating your SVG and encoding it. Here’s the step by step
     process to add custom SVG icon to the admin menu:
 31.  a. First, get or create your SVG icon in any way you want.
      b. Next, clean up the SVG file and format it correctly
      c. Then base64 encode the file
      d. Prefix the base64 string with `'data:image/svg+xml;base64,'`
      e. …and that will give you a valid $icon_url string.
 32. So let me expand on those steps.
 33. **Step 1**
 34. You can create your SVG graphic in any way you want as far as I can see. I created
     mine in Adobe Illustrator, but anything like Inkscape, Corel draw, even hardcoding
     it is ok.
 35. **Step 2**
 36. The painful part is cleaning up your SVG. After a lot of testing and experimenting
     I found that the cleaner the SVG is, the more likely it is to work. Basically,
     a lot of graphics programs will add in metadata and other fluff to make the SVG
     more widely compatible. That’s great 99% of the time, but when using it for a 
     wordpress menu icon, it just breaks it.
 37. This is an example of an SVG exported normally from Adobe Illustrator:
 38.     ```javascript
         <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg&quot; viewBox="0 0 
         15.7 16"><defs><style>.d{fill:#070707;}</style></defs><g id="a"/><g id="b"><g id="c"><path
          class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5
         ,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,
         7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/><path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,
         3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.
         4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/></g>
         </g></svg>
         ```
     
 39. Messy, very messy. Even when we add some line breaks and indent it, there’s a 
     lot going on.
 40.     ```javascript
         <?xml version="1.0" encoding="UTF-8"?>
         <svg xmlns="http://www.w3.org/2000/svg&quot; viewBox="0 0 15.7 16">
         	<defs>
         		<style>
         			.d{fill:#070707;}
         		</style>
         	</defs>
         	<g id="a"/>
         	<g id="b">
         		<g id="c">
         			<path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/>
         			<path class="d" d="M15.4,6.5H7.9v3h4.4c-.4,2.1-2.3,3.5-4.4,3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7,2-5,4.7-5.1,1.1,0,2.2,.4,3.1,1.2l2.3-2.2c-1.4-1.4-3.4-2.1-5.3-2.1C3.6,0,0,3.6,0,8s3.6,8,8,8,7.7-3.2,7.7-7.8c-.1-.6-.1-1.1-.3-1.7Z"/>
         		</g>
         	</g>
         </svg>
         ```
     
 41. So what we want to do is clean this up a lot and get rid of unnecessary data. 
     You may find that the above will load if you add it as an image source but it 
     won’t color properly with the GUI and it will probably be the wrong size. So there’s
     a few things we need to do:
 42.  * Remove the `<?xml` tag, this won’t help
      * Then you will have to hardcode each style into the path, rather than using 
        the tag. For each path, work out which classes apply to the path from the tag,
        and add the CSS from those classes into the path.
      * Once that’s done, you can remove the `defs` element completely.
      * You can also remove the elements and leave the elements at the root of the 
        SVG.
      * To ensure your SVG is colored in line with the GUI, you will need to add `fill
        ="black"` to each path.
      * And then, to ensure your SVG is the right width and height, add `width="20"
        height="20"` into the opening element
 43. Once that’s done, you’ll end up with an SVG file that looks more like this:
 44.     ```javascript
         <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"&gt;
         	<path fill="black" d="M17.6 8.5h-7.5v3h4.4c-.4 2.1-2.3 3.5-4.4 3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7 2-5 4.7-5.1 1.1 0 2.2.4 3.1 1.2l2.3-2.2C14.1 2.7 12.1 2 10.2 2c-4.4 0-8 3.6-8 8s3.6 8 8 8c4.6 0 7.7-3.2 7.7-7.8-.1-.6-.1-1.1-.3-1.7z" fillrule="evenodd" cliprule="evenodd">
         	</path>
         </svg>
         ```
     
 45. **Step 3**
 46. Now you want to base64 encode your SVG. The way I did it was to pass the file 
     into PHP’s default encoding mechanism, and copy the path into my PHP as an absolute
     path. You don’t want PHP to read the SVG file, base64 encode it, and pass it to
     the menu every time the user reloads the page, that’s just a waste of resources
     and time.
 47.     ```php
         // load the SVG data by loading the file or including the XML directly.
         $svg = file_get_contents( '/path/to/icon.svg' );
         // or
         $svg = '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill="black" d="M17.6 8.5h-7.5v3h4.4c-.4 2.1-2.3 3.5-4.4 3.4-2.6-.1-4.6-2.1-4.7-4.7-.1-2.7 2-5 4.7-5.1 1.1 0 2.2.4 3.1 1.2l2.3-2.2C14.1 2.7 12.1 2 10.2 2c-4.4 0-8 3.6-8 8s3.6 8 8 8c4.6 0 7.7-3.2 7.7-7.8-.1-.6-.1-1.1-.3-1.7z" fillrule="evenodd" cliprule="evenodd"></path></svg>';
     
         // then encode it and echo it out
         echo base64_encode( $svg );
         // will give you a long string that looks like this:
         // PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg==
     
         // thats your base64 encoded SVG file! 
         ```
     
 48. **Step 4**
 49. Add ‘data:image/svg+xml;’ in front of the base64 SVG so it looks like this:
 50.     ```php
         "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg=="
         ```
     
 51. and that there, sir, is a perfectly valid `$icon_url` string. I would hard code
     that string to a variable and simply add it into your plugin every time.
 52.     ```php
         add_menu_page( __( 'WPDocs Plugin page name' ), __( 'WPDocs Plugin' ), 'manage_options', 'slug', 'callback','data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdib3g9IjAgMCAyMCAyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsPSIjYTdhYWFkIiBkPSJNMTcuNiA4LjVoLTcuNXYzaDQuNGMtLjQgMi4xLTIuMyAzLjUtNC40IDMuNC0yLjYtLjEtNC42LTIuMS00LjctNC43LS4xLTIuNyAyLTUgNC43LTUuMSAxLjEgMCAyLjIuNCAzLjEgMS4ybDIuMy0yLjJDMTQuMSAyLjcgMTIuMSAyIDEwLjIgMmMtNC40IDAtOCAzLjYtOCA4czMuNiA4IDggOGM0LjYgMCA3LjctMy4yIDcuNy03LjgtLjEtLjYtLjEtMS4xLS4zLTEuN3oiIGZpbGxydWxlPSJldmVub2RkIiBjbGlwcnVsZT0iZXZlbm9kZCI+PC9wYXRoPjwvc3ZnPg==' );
         ```
     
 53. I hope that helps someone else, because that would have saved me several hours
     this morning!
 54.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D5845%23feedback-editor-5845)
 55.  [Skip to note 16 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-2169)
 56.   [Sophy](https://profiles.wordpress.org/sophy/)  [  10 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-2169)
 57. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-2169)
     Vote results for this note: 4[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-2169)
 58. Add Menu Pages with Dashicons. More dashicons check here [https://developer.wordpress.org/resource/dashicons/#menu](https://developer.wordpress.org/resource/dashicons/#menu)
 59.     ```php
         add_action( 'admin_menu', 'register_my_custom_menu_page' );
         function register_my_custom_menu_page() {
           // add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
           add_menu_page( 'Custom Menu Page Title', 'Custom Menu Page', 'manage_options', 'custom.php', '', 'dashicons-welcome-widgets-menus', 90 );
         }
         ```
     
 60.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D2169%23feedback-editor-2169)
 61.  [Skip to note 17 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-1266)
 62.   [Aamer Shahzad](https://profiles.wordpress.org/talentedaamer/)  [  11 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-1266)
 63. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-1266)
     Vote results for this note: 3[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-1266)
 64.     ```php
         /**
          * Create admin Page to list unsubscribed emails.
          */
          // Hook for adding admin menus
          add_action('admin_menu', 'wpdocs_unsub_add_pages');
     
          // action function for above hook
     
         /**
          * Adds a new top-level page to the administration menu.
          */
         function wpdocs_unsub_add_pages() {
              add_menu_page(
         	 	__( 'Unsub List', 'textdomain' ),
         		__( 'Unsub Emails','textdomain' ),
         		'manage_options',
         		'wpdocs-unsub-email-list',
         		'wpdocs_unsub_page_callback',
         		''
         	);
         }
     
         /**
          * Disply callback for the Unsub page.
          */
          function wpdocs_unsub_page_callback() {
              echo 'Unsubscribe Email List';
          }
         ```
     
 65.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D1266%23feedback-editor-1266)
 66.  [Skip to note 18 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-4227)
 67.   [eliran](https://profiles.wordpress.org/elirant3/)  [  6 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-4227)
 68. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-4227)
     Vote results for this note: 2[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-4227)
 69. A better example to **peskyesky**.
 70. object oriented example.
 71. _TODO:
      create includes/layout.php
 72.     ```php
         class WPDocs_EB_EbtechModules {
             public static function init() {
                 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'adminAssets' ) );
                 add_action( 'admin_menu', array( __CLASS__, 'adminMenu' ) );
             }
     
             public static function adminMenu() {
                 add_menu_page(
                     __( 'WPDocs Ebtech Menu', 'wpdocs-webnail-modules' ),
                     __( 'WPDocs Ebtech modules', 'wpdocs-webnail-modules' ),
                     'manage_options',
                     'wpdocs-ebtech-modules',
                     array( __CLASS__, 'menuPage' ),
                     'dashicons-tagcloud',
                     6
                 );
             }
     
             public static function menuPage() {
                 if ( is_file( plugin_dir_path( __FILE__ ) . 'includes/layout.php' ) ) {
                     include_once plugin_dir_path( __FILE__ ) . 'includes/layout.php';
                 }
             }
     
             public static function getSettings() {
                 return get_option( 'wpdocs_ebtech_modules_option' );
             }
     
             public static function adminAssets() {
                 if ( isset( $_GET['page'] ) && ! empty( $_GET['page'] ) && 'wpdocs-ebtech-modules' === $_GET['page'] ) {
     
                 }
             }
         }
     
         WPDocs_EB_EbtechModules::init();
         WPDocs_EB_EbtechModules::getSettings();
         ```
     
 73.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D4227%23feedback-editor-4227)
 74.  [Skip to note 19 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-3492)
 75.   [Vincent Dubroeucq](https://profiles.wordpress.org/vincentdubroeucq/)  [  7 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-3492)
 76. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-3492)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-3492)
 77. The callback function used to display the contents of the page **isn’t necessarily
     required to check current user’s capabilities**, since the callback is not even
     hooked in if the user doesn’t have the right capabilities.
 78. If you try to directly access a page for which you don’t have required capabilities,
     you’ll get an error page.
 79.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D3492%23feedback-editor-3492)
 80.  [Skip to note 20 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-6596)
 81.   [angelbouklis](https://profiles.wordpress.org/angelbouklis/)  [  3 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-6596)
 82. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-6596)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-6596)
 83. Quick example on how to add a menu entry with an icon.
 84.     ```php
         <?php
     
         add_action( 'admin_menu', 'wpdocs_add_artist_menu' );
         function wpdocs_add_artist_menu(): void {
             add_menu_page(
                 'Artists',
                 'Artists',
                 'manage_options',
                 'admin-artists',
                 '...',
                 'data:image/svg+xml;base64,' . base64_encode(
                     'svg goes here, unfortunately I can't paste one because it is automatically removed'
                 )
             );
         }
         ```
     
 85.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D6596%23feedback-editor-6596)
 86.  [Skip to note 21 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-6994)
 87.   [Sarankumar](https://profiles.wordpress.org/sarankumar/)  [  2 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-6994)
 88. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-6994)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-6994)
 89. When incorporating additional menu items using **add_menu_page**, the main page
     automatically becomes the first entry in the submenu. However, if you wish to 
     assign a different name to the first item in the list, you can utilize the following
     code.
 90.     ```php
         add_action( 'admin_menu', 'wpdocs_menu_pages' );
         function wpdocs_menu_pages() {
             add_menu_page( 'My Page Title', 'My Page Title', 'manage_options', 'wpdocs-menu', 'wpdocs_menu_output','dashicons-whatsapp',6 );
             add_submenu_page( 'wpdocs-menu', 'Submenu Page Title', 'Submenu Page Title', 'manage_options', 'wpdocs-menu' );
             add_submenu_page( 'wpdocs-menu', 'Submenu Page Title2', 'Submenu Page Title 2', 'manage_options', 'wpdocs-menu2' );
         }
         ```
     
 91.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D6994%23feedback-editor-6994)
 92.  [Skip to note 22 content](https://developer.wordpress.org/reference/functions/add_menu_page/?output_format=md#comment-content-1593)
 93.   [peskyesky](https://profiles.wordpress.org/peskyesky/)  [  10 years ago  ](https://developer.wordpress.org/reference/functions/add_menu_page/#comment-1593)
 94. [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-1593)
     Vote results for this note: -5[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%23comment-1593)
 95.     ```php
         // For those who are object orientated. Add a class 
         // function as the menu callback and setup the 
         // menus automatically. 
     
         // Exit if accessed directly
         if ( !defined( 'ABSPATH' ) ) exit;
     
         class MyMenuSetterUpper {
     
             private static $instance;
     
             /**
              * Main Instance
              *
              * @staticvar 	array 	$instance
              * @return 		The one true instance
              */
             public static function instance() {
                  if ( ! isset( self::$instance ) ) {
                      self::$instance = new self;
         	     self::$instance->addMyAdminMenu();
         	}
     
                 return self::$instance;
             }
     
             public function addMyAdminMenu() {
     
                  add_menu_page(
                     'My Page Title',
                     'My Page',
                     'read',
                     'my-menu-page-slug',
                     array(
                         $this,
                         'myAdminPage'
                     ),
                     'to/icon/file.svg',
                     '2.1'
                 );
             }
     
             public function myAdminPage() {
                  // Echo the html here...
             }
     
         }
         // Call the class and add the menus automatically. 
         $MyMenuSetterUpper = MyMenuSetterUpper::instance();
         ```
     
 96.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F%3Freplytocom%3D1593%23feedback-editor-1593)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fadd_menu_page%2F)
before being able to contribute a note or feedback.