Blog, WordPress, WordPress Development

How To Create WordPress Custom Admin Page and Menu

Custom Admin Page is an option in WordPress to create a custom WordPress admin page for your own plugin or your theme.

Sometimes your plugin needs a menu in the admin panel for itself to display some reports or settings page. To do this we use Admin Pages. Creating an admin menu and admin page is not hard. Follow this tutorial to learn how to create a custom admin page and menu in WordPress CMS.

What are WordPress Custom Admin Pages and Menus?

After logging in to the admin panel you can see the menu on the left side and in RTL websites on the right side. This menu contains some basic menus like Appearance, Plugins, Settings, Users, etc.

You may also see new menu items after activating a theme or a plugin that redirects you to a new admin page. It can be a settings page for the plugin, a control panel of your theme, a page to show the status of your site or even a document page.

There are two types of menu entries: Top-level and sub-level. If users need to interact with your plugin daily you can use a top-level entry. If your admin page is just for settings, a sub-level entry in the Settings top-level menu is more appropriate.

How to Add WordPress custom Admin Pages and Menus

To add a custom admin page in WordPress, we need two things:

  • An admin menu (add_menu_page function)
  • Page content

To add the admin menu we use the add_menu_page function that we introduce to WordPress, the menu, and then the call back function to manage the admin page content.

Following code describe menu to WordPress.

add_menu_page( 
string $page_title, 
string $menu_title, 
string $capability, 
string $menu_slug, 
callable $function = '', 
string $icon_url = '', 
int $position = null )

The function takes seven arguments.

  • page_title (Required) The text to be displayed in the title tags of the page when the menu is selected.
  • menu_title (Required) is the title that shows up in the menu.
  • capability (Required) The capability required for this menu to be displayed to the user. For example, if it contains some general options for the site, manage_option could be the best choice. This can be used to restrict it to only admins, editors or authors. Just set it carefully to avoid any possible security issue.
  • menu_slug (Required) The slug name that refers to this menu. It should be unique for this menu page. This will be used as a parameter in the URL of your custom admin page.
  • function (Optional) The function to be called to show the output content for this page.
  • icon_url (Optional) The URL of the icon to be used for this menu. You can use an image, encoded SVG, or dash icons.
    • In order to use an image, simply pass the URL of the image.
    • Using existing WordPress icons.
    • You can use none value to leave div.wp-menu-image empty, so an icon can be added via CSS.
    • You can use the SVG file. Convert SVG file to base64 and add with data:image/svg+xml;base64code.
  • position (Optional) The position in the menu order should appear. Here is the list of numbers of default admin menus:
    • 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

Open the functions.php file of your theme or add it to your plugin. To do this we create a function hs_admin_menu to define the menu.

function hs_admin_menu() {
    add_menu_page(
        __( 'Page Title', 'my-textdomain' ),
        __( 'Menu Title', 'my-textdomain' ),
        'manage_options',
        'sample-page',
        'my_admin_page_contents',
        'dashicons-schedule',
        3
    );
}
add_action( 'admin_menu', 'hs_admin_menu' );

The next step is to create some content. All you need to do is create the function defined in argument five and echo some content. To add the function to WordPress, we use an action named admin_menu.

function hs_admin_page_contents() {
    ?>
    <h1>
        <?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?>
    </h1>
    <?php
}
WordPress Custom Admin Page

As you see, the page title, menu title, menu icon, and end of the URL are items that are introduced.

How to Add Sub Menu and Sub Level Page

We added a top level menu to the admin panel. We may want to add a sub-level menu to our own top level. Now we are going to add a submenu to that menu.

Sub menu structure will be like following.

add_submenu_page( 
string $parent_slug, 
string $page_title, 
string $menu_title, 
string $capability, 
string $menu_slug, 
callable $function = '' );

Put the following sub-menu code inside the hs_admin_menu function next to add_admin_menu.

add_submenu_page( 'sample-page',
    __( 'Page Title - Honar Systems', 'my-textdomain' ),
    __( 'Sub Menu Title', 'my-textdomain' ),
    'manage_options',
    'sample-page-sub-menu',
    'my_sub_menu_admin_page_contents');

And again, like the menu page, add the function below to display sub-menu page content.

function hs_sub_menu_admin_page_contents(){
    ?>
    <h1>
        <?php esc_html_e( 'Welcome to my custom sub menu admin page.', 'my-plugin-textdomain' ); ?>
    </h1>
    <?php
}
WordPress Custom Admin Page

If you are developing a custom plugin you can use your plugin address as parent slug like below code.

add_submenu_page(
   'myplugin/myplugin-admin-page.php',
    __('Page Title - Honar Systems', 'my-textdomain'),
    __('Sub Menu Title', 'my-textdomain'),
    'manage_options',
    'myplugin/myplugin-admin-sub-page.php',
    'my_sub_menu_admin_page_contents' );

You should know that it is possible to add a sub menu to existing menus. WordPress basic top level menus have there own functions to add sub level menu.

  • add_posts_page Adds a submenu under Posts menu
  • add_pages_page Adds a submenu under Pages menu
  • add_media_page Adds a submenu under Media menu
  • add_comments_page Adds a submenu under Comments menu
  • add_theme_page Adds a submenu under the Appearance menu
  • add_plugin_page Adds a submenu under Plugins menu
  • add_users_page Adds a submenu under Users menu
  • add_management_page Adds a submenu under Tools menu
  • add_options_page Adds a submenu under Settings menu

For example, to adding a sub menu to Comments top level menu.

add_comments_page( 
    $page_title, 
    $menu_title, 
    $capability, 
    $menu_slug, 
    $function);

If you don’t need top level menu, we recommend you to add in sub menu. Too many plugins add top-level entries, which end up polluting the admin heavily.

Adding Custom CSS and JS Files in Admin Pages and Menus

Sometimes we need to use our own style for our custom admin pages and menus. To do this we need to add our styles and js codes by the hook.

Following codes, adds our own style, WordPress color picker style, and our own JavaScript code.

We create a folder and name it assets. Insert style and js file inside it.

function hs_load_custom_wp_admin_style($hook)
{
    wp_enqueue_style('custom_wp_admin_css', get_template_directory_uri() . '/assets/style.css');
    // Load color picker styles.
    wp_enqueue_style('wp-color-picker');

    wp_enqueue_script('custom_wp_admin_js', get_template_directory_uri() . '/assets/script.js');
}

add_action('admin_enqueue_scripts', 'hs_load_custom_wp_admin_style');

In the above code, wp-color-picker is the WordPress build-in style and we consider that we writing our code inside the functions.php file. Otherwise, the above addresses should be changed to the existing address.

Load Styles Only in a Specific Page

If you add your styles like the previous section, you can see your style changing the whole admin panel’s style. To prevent that, we have to check if the current page is our page or not. Then we have to check our hook, like below. Our main menu hook will be toplevel_page_sample-page.

function hs_load_custom_wp_admin_style($hook) {
    // Load only on ?page=sample-page not in sub menu
    if( $hook != 'toplevel_page_sample-page') {
        return;
    }
    wp_enqueue_style( 'custom_wp_admin_css', get_template_directory_uri().'/assets/style.css' );
}
add_action( 'admin_enqueue_scripts', 'hs_load_custom_wp_admin_style' );

How to find our custom admin page’s hook? The answer is below code. This code will display the current page’s hook.

function hs_load_custom_wp_admin_style( $hook ) {
    wp_die( $hook );
}
add_action( 'admin_enqueue_scripts', 'hs_load_custom_wp_admin_style' );

Final Code

The final code will be like following.

function my_admin_menu()
{
    add_menu_page(
        __('Page Title - Honar Systems', 'my-textdomain'),
        __('Menu Title', 'my-textdomain'),
        'manage_options',
        'sample-page',
        'my_admin_page_contents',
        'dashicons-schedule',
        3
    );

    add_submenu_page('sample-page',
        __('Page Title - Honar Systems', 'my-textdomain'),
        __('Sub Menu Title', 'my-textdomain'),
        'manage_options',
        'sample-page-sub-menu',
        'my_sub_menu_admin_page_contents');
}

add_action('admin_menu', 'my_admin_menu');

function my_admin_page_contents()
{
    ?>
    <h1>
        <?php esc_html_e('Welcome to my custom admin page.', 'my-plugin-textdomain'); ?>
    </h1>
    <?php
}

function my_sub_menu_admin_page_contents()
{
    ?>
    <h1>
        <?php esc_html_e('Welcome to my custom sub menu admin page.', 'my-plugin-textdomain'); ?>
    </h1>
    <?php
}

function load_custom_wp_admin_style($hook)
{
    wp_enqueue_style('custom_wp_admin_css', get_template_directory_uri() . '/assets/style.css');
    // Load color picker styles.
    wp_enqueue_style('wp-color-picker');

    wp_enqueue_script('custom_wp_admin_js', get_template_directory_uri() . '/assets/script.js');
}

add_action('admin_enqueue_scripts', 'load_custom_wp_admin_style');

How to Create wordpress admin page without menu (hidden menu)

Sometimes we need to have an admin page but not having a menu or submenu in the list. For example, you created a plugin with an Edit page but you don’t want to show the Edit sub menu in the menu bar.

The definition of a hidden sub-menu is exactly like a normal sub-menu in items, but the value of items has a little bit different.

add_submenu_page(
    'null',
    __('Hidden Menu - Honar Systems', 'my-textdomain'),
    __('Hidden', 'my-textdomain'),
    'manage_options',
    'hidden-page-sub-menu',
    'my_hidden_sub_menu_admin_page_contents'
);

As you can see, the parent slug is null. It means that this sub-menu belongs to no item. But if you go URL below you can see your contents.

admin.php?page=hidden-page-sub-menu