add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '', string $icon_url = '', int $position = null )
Add a top-level menu page.
Contents
Description 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 Parameters
- $page_title
-
(string) (Required) The text to be displayed in the title tags of the page when the menu is selected.
- $menu_title
-
(string) (Required) The text to be used for the menu.
- $capability
-
(string) (Required) The capability required for this menu to be displayed to the user.
- $menu_slug
-
(string) (Required) 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().
- $function
-
(callable) (Optional) The function to be called to output the content for this page.
Default value: ''
- $icon_url
-
(string) (Optional) 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 value: ''
- $position
-
(int) (Optional) The position in the menu order this item should appear.
Default value: null
Return Return
(string) The resulting page's hook_suffix.
More Information More Information
Notes 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 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.
- 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) 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 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() . Check out the Settings API.
Example allowing an editor to save data:
// Register settings using the Settings API
function wpdocs_register_my_setting() {
register_setting( 'my-options-group', 'my-option-name', 'intval' );
}
add_action( 'admin_init', 'wpdocs_register_my_setting' );
// Modify capability
function wpdocs_my_page_capability( $capability ) {
return 'edit_others_posts';
}
add_filter( 'option_page_capability_my-options-group', 'wpdocs_my_page_capability' );
Menu Structure Menu Structure
Default: bottom of menu structure 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: 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 Source
File: wp-admin/includes/plugin.php
function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $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( $function ) && ! empty( $hookname ) && current_user_can( $capability ) ) {
add_action( $hookname, $function );
}
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 ) {
$menu[] = $new_menu;
} elseif ( isset( $menu[ "$position" ] ) ) {
$position = $position + substr( base_convert( md5( $menu_slug . $menu_title ), 16, 10 ), -5 ) * 0.00001;
$menu[ "$position" ] = $new_menu;
} else {
$menu[ $position ] = $new_menu;
}
$_registered_pages[ $hookname ] = true;
// No parent as top level.
$_parent_pages[ $menu_slug ] = false;
return $hookname;
}
Expand full source code Collapse full source code View on Trac
Changelog Changelog
| Version | Description |
|---|---|
| 1.5.0 | Introduced. |
User Contributed Notes User Contributed Notes
You must log in before being able to contribute a note or feedback.


Examples
Add a custom menu item to the WordPress admin menu, for a user with administrator capability:
Method 1:
/** * 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' );Expand full source codeCollapse full source code
With this method the page-generating code should be located in
myplugin/myplugin-admin.php:Method 2:
/** * 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' ); }Expand full source codeCollapse full source code
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
fillstyle attribute. The process is done bywp-admin/js/svg-painter.js.Feedback
I forgot to mention that this is about the icon to be used for this menu (
$icon_url). — By Felipe Elia —/** * 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'; }Expand full source codeCollapse full source code
Add Menu Pages with Dashicons. More dashicons check here https://developer.wordpress.org/resource/dashicons/#menu
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 ); }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.
If you try to directly access a page for which you don’t have required capabilities, you’ll get an error page.
A better example to peskyesky.
object oriented example.
TODO:
create includes/layout.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();Expand full source codeCollapse full source code
// 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();Expand full source codeCollapse full source code