Skip to main content
Blog|
How-to guides

How to customize the WordPress dashboard

|
May 22, 2026|12 min read
HOW-TO GUIDESHow to customize the WordPressdashboardHOSTNEYhostney.comMay 22, 2026

Short answer: The WordPress dashboard is customizable on two levels. For a quick cleanup, use the Screen Options tab at the top right of the dashboard to hide widgets you do not use, and drag the remaining widgets into the order you want. For a permanent setup that applies to everyone (or to specific user roles), add code to a small plugin: remove_meta_box() strips the default widgets, wp_add_dashboard_widget() adds your own, and both hook into wp_dashboard_setup . The screen-options approach is per-user and instant; the code approach is site-wide and survives logins, theme changes, and new users.

The dashboard is the first screen everyone sees after logging in to WordPress. By default it is a noticeable amount of clutter – a welcome panel, an activity feed, a “Quick Draft” box, WordPress news, and whatever every plugin you installed decided to add. For your own site that is mildly annoying. For a site you built for a client, it is a support problem: the person you handed the site to logs in, sees ten boxes they do not understand, and emails you to ask what they are.

This guide covers both the five-minute personal cleanup and the proper code-based customization, including how to give different user roles different dashboards.

Customize the dashboard with Screen Options (no code)#

The fastest way to tidy the dashboard needs no code and no plugin. Log in, land on the dashboard, and look at the very top right of the screen. There are two tabs there: Screen Options and Help.

Click Screen Options. A panel slides down with a checkbox for every dashboard widget that is currently registered:

  • Welcome – the big panel with “Get started” buttons
  • At a Glance – post, page, and comment counts
  • Activity – recently published and recent comments
  • Quick Draft – a mini post editor
  • WordPress Events and News – feed from wordpress.org
  • Any widgets added by plugins (Yoast SEO, Jetpack, WooCommerce, and similar)

Untick anything you do not want to see. The widget disappears immediately – no save button. Tick it again to bring it back.

Below the checkboxes, the panel also lets you set the number of columns the dashboard uses (1 to 4) and toggle the screen layout.

You can also rearrange the widgets that remain. Hover over a widget’s title bar, and the cursor becomes a move cursor. Drag the widget up, down, or into another column and drop it. WordPress saves the new position.

The important limitation: Screen Options changes are per-user. They are stored in that user’s metadata, not in the site. Your cleaned-up dashboard is yours alone. Every other user – and every new user you add later – still gets the default cluttered dashboard. If you are setting up a site for someone else, screen options will not solve the problem. You need the code approach below.

How the dashboard is built: the wp_dashboard_setup hook#

To customize the dashboard for everyone, it helps to know how WordPress assembles it.

When the dashboard page loads, WordPress fires an action hook called wp_dashboard_setup . Every default widget, and every plugin widget, is registered on that hook. Because it is a hook, you can attach your own function to it and:

  • Remove widgets that core or plugins registered, with remove_meta_box()
  • Add your own widgets, with wp_add_dashboard_widget()

Both calls have to run inside a function hooked to wp_dashboard_setup , because that is the only point in the page load where the full list of widgets exists and can still be changed.

One detail worth knowing: the Welcome panel is not a normal meta box. It is added through a separate hook ( welcome_panel ), so it is removed differently. We will cover that below.

Where to put the code#

Put dashboard customization code in a small site-specific plugin, not in your theme’s functions.php .

The reason is the same one that applies to most “make WordPress behave differently” code: if the customization lives in the theme, it disappears the moment someone switches themes, and a clean dashboard is not a visual feature – it should not depend on which theme is active. A tiny plugin keeps the customization independent of the theme and easy to switch off if something goes wrong. The same argument is laid out in more detail in our guide on how to create a custom post type in WordPress, and it holds here too.

Create a file at wp-content/plugins/site-dashboard/site-dashboard.php with this header:

<?php
/*
Plugin Name: Site Dashboard Customizations
Description: Cleans up and customizes the WordPress admin dashboard.
Version: 1.0
*/

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Block direct access.
}

Activate it from Plugins, then add the code from the sections below into the same file.

Remove the default dashboard widgets#

To strip the widgets you do not want, hook a function to wp_dashboard_setup and call remove_meta_box() for each one.

remove_meta_box() takes three arguments: the widget’s ID, the screen it lives on ( dashboard ), and the context ( normal , side , or column3 / column4 ).

function site_remove_dashboard_widgets() {
    // Core widgets.
    remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' );
    remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
    remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );   // WordPress news
    remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' ); // At a Glance

    // Plugin widgets are removed the same way - just match their IDs.
    // remove_meta_box( 'yoast_db_widget', 'dashboard', 'normal' );
}
add_action( 'wp_dashboard_setup', 'site_remove_dashboard_widgets' );

The core widget IDs are:

WidgetMeta box IDContext
At a Glance dashboard_right_now normal
Activity dashboard_activity normal
Quick Draft dashboard_quick_press side
WordPress Events and News dashboard_primary side
Site Health Status dashboard_site_health normal
PHP Update Recommendation dashboard_php_nag normal

For a plugin’s widget, the ID is not always obvious. The reliable way to find it: load the dashboard, open your browser’s developer tools, and inspect the widget’s outer container – its id attribute is the meta box ID you pass to remove_meta_box() .

The Welcome panel is the exception, because it is not a meta box:

function site_remove_welcome_panel() {
    remove_action( 'welcome_panel', 'wp_welcome_panel' );
}
add_action( 'admin_init', 'site_remove_welcome_panel' );

Add your own dashboard widget#

Removing clutter is half the job. The other half is putting something useful in its place – a short welcome message, a list of support links, the client’s brand details, or quick links to the pages they edit most.

Use wp_add_dashboard_widget() . It takes a widget ID, a title, and the name of a function that prints the widget’s content:

function site_add_help_widget() {
    wp_add_dashboard_widget(
        'site_help_widget',          // Widget ID.
        'Need help with your site?', // Title shown in the widget bar.
        'site_help_widget_content'   // Function that prints the content.
    );
}
add_action( 'wp_dashboard_setup', 'site_add_help_widget' );

function site_help_widget_content() {
    echo '<p>Welcome back. Here are the things you will use most:</p>';
    echo '<ul>';
    echo '<li><a href="' . esc_url( admin_url( 'edit.php?post_type=page' ) ) . '">Edit your pages</a></li>';
    echo '<li><a href="' . esc_url( admin_url( 'post-new.php' ) ) . '">Write a new post</a></li>';
    echo '<li><a href="mailto:support@example.com">Email support</a></li>';
    echo '</ul>';
}

The content function can output any HTML. Always escape output – use esc_url() for links and esc_html() for text – so a stray value can never break the page or inject markup. If the widget prints a date, format it with wp_date() rather than PHP’s date() , for the same timezone reasons explained in how to customize the WordPress date format.

Your widget will appear at the bottom of the dashboard. To pin it to the top, give it priority when you register it:

function site_add_help_widget() {
    global $wp_meta_boxes;

    wp_add_dashboard_widget(
        'site_help_widget',
        'Need help with your site?',
        'site_help_widget_content'
    );

    // Move the new widget to the top of the "normal" column.
    $normal = $wp_meta_boxes['dashboard']['normal']['core'];
    $widget = array( 'site_help_widget' => $normal['site_help_widget'] );
    unset( $normal['site_help_widget'] );
    $wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $widget, $normal );
}

Give different user roles different dashboards#

This is where the dashboard customization becomes genuinely useful for agencies and anyone running a multi-author site. The clutter that confuses a client is fine for you as the administrator – so the goal is usually not “remove everything for everyone” but “remove everything except for administrators“.

Every removal and addition call can be wrapped in a capability check. current_user_can() tests what the logged-in user is allowed to do. Administrators have manage_options ; editors and authors do not. So:

function site_role_based_dashboard() {
    // Administrators keep the full dashboard - skip the cleanup for them.
    if ( current_user_can( 'manage_options' ) ) {
        return;
    }

    // Everyone else (editors, authors, custom client roles) gets the clean version.
    remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' );
    remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
    remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
    remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' );

    // Then add the simple client widget.
    wp_add_dashboard_widget(
        'site_help_widget',
        'Welcome',
        'site_help_widget_content'
    );
}
add_action( 'wp_dashboard_setup', 'site_role_based_dashboard' );

For finer control, check capabilities other than manage_options . current_user_can( 'edit_posts' ) is true for authors and up; current_user_can( 'publish_pages' ) is true for editors and up. And if you created a dedicated client role – which is the cleanest approach for agency sites – you can test for a capability that only that role has, or check the role directly:

$user = wp_get_current_user();
if ( in_array( 'client', (array) $user->roles, true ) ) {
    // Customizations for the "client" role only.
}

If you are not yet using custom roles to separate clients from staff, that is the foundation worth building first – our guide to WordPress user roles and user management covers creating a tailored role with exactly the capabilities a client needs and nothing more. A clean dashboard and a scoped role together turn the WordPress admin into something you can hand over without a training session.

Building a client dashboard: putting it together#

A practical “client dashboard” is the combination of the pieces above:

  1. Create a client role with only the capabilities the client needs (often just editing pages and posts). See the user roles guide linked above.
  2. Remove the default widgets for any non-administrator, so the client never sees Activity, Quick Draft, Site Health, or the WordPress news feed.
  3. Add one welcome widget with the client’s branding, a short instruction, and links to the two or three screens they actually use.
  4. Optionally, trim the admin menu so the left-hand sidebar is just as focused (covered next).

The result is a dashboard that shows the client a friendly welcome and a couple of buttons, while you as the administrator still see the complete WordPress dashboard when you log in. One plugin file, no clutter, nothing for the client to misunderstand.

Trimming the admin menu too#

The dashboard widgets are only the centre of the screen. The left-hand admin menu is often the bigger source of confusion – Tools, Settings, Plugins, and Appearance are all places a client can break something.

Hide menu items with remove_menu_page() , hooked to admin_menu , and wrapped in the same capability check:

function site_trim_admin_menu() {
    if ( current_user_can( 'manage_options' ) ) {
        return; // Administrators keep the full menu.
    }

    remove_menu_page( 'tools.php' );        // Tools
    remove_menu_page( 'edit-comments.php' ); // Comments
    remove_menu_page( 'themes.php' );        // Appearance
}
add_action( 'admin_menu', 'site_trim_admin_menu', 999 );

The 999 priority makes this run after plugins have registered their menus, so plugin menu items can be removed the same way (pass the plugin’s menu slug). Hiding a menu page is a convenience, not a security control – if a client guesses the URL they could still load the page – so for anything that genuinely must be off-limits, the real fix is to remove the capability from their role, not just hide the link.

Common mistakes#

  • Expecting Screen Options to apply to everyone. Screen Options is per-user and stored in user metadata. It cleans up your dashboard only. For a site-wide or client-facing dashboard you must use code.
  • Putting the code in the theme’s functions.php. A clean dashboard is not a theme feature. If it lives in the theme it vanishes on the next theme switch. Use a small site-specific plugin.
  • Removing widgets for administrators by accident. If you do not wrap the remove_meta_box() calls in a current_user_can( 'manage_options' ) check, you strip the dashboard for yourself as well. Almost always you want administrators to keep the full view.
  • Guessing plugin widget IDs. Core widget IDs are documented, but plugin widgets are not. Inspect the widget’s container in your browser’s developer tools to read the real id before calling remove_meta_box() .
  • Trying to remove the Welcome panel with remove_meta_box(). The Welcome panel is not a meta box. Use remove_action( 'welcome_panel', 'wp_welcome_panel' ) instead.
  • Treating a hidden menu item as locked. remove_menu_page() hides a link; it does not block the URL. If a client must not reach a screen, remove the capability from their role.
  • Not escaping output in a custom widget. Anything your widget prints should pass through esc_html() , esc_url() , or esc_attr() . An unescaped value is an avoidable security hole.

How Hostney handles this#

Dashboard customization is WordPress-level work – it happens inside wp-admin regardless of where the site is hosted – but a couple of things make it smoother on Hostney.

Because every Hostney site runs in its own isolated container, you can build and test a dashboard plugin without any risk to other sites. The file manager includes a code editor, so you can create the site-dashboard.php plugin file directly in the control panel, and its syntax checking will flag a missing brace or semicolon before you ever activate the plugin and see a white screen.

When you build sites for clients, Hostney’s delegate access fits the same model as a role-scoped dashboard. You can give a client access to manage their own site through the control panel without handing over your full account, which mirrors what a trimmed dashboard and a custom role do inside WordPress: each person sees only what they need. The two layers – control panel access and the WordPress dashboard itself – work best when you scope both.

For the WordPress side, the plugin file is small enough that a daily snapshot backup means you can always roll back if a remove_meta_box() call removes one widget too many. Build the customization, check the dashboard, and if it looks wrong, restore and adjust.

Summary#

The WordPress dashboard is customizable two ways. Screen Options is the instant, no-code, per-user cleanup – good for tidying your own view. For anything that has to apply to other users, especially clients, you need code: a small site-specific plugin that hooks wp_dashboard_setup , calls remove_meta_box() to clear the default clutter, and wp_add_dashboard_widget() to add a useful welcome widget. Wrap those calls in a current_user_can() check so administrators keep the full dashboard while everyone else gets the simplified version. Pair that with a custom user role and a trimmed admin menu, and you have a WordPress admin you can hand to a client without a training call.