Admin UX PHP Beginner

Add a Custom Admin Dashboard Widget

Last updated: May 6, 2026

The WordPress admin dashboard is often the first thing a client sees when they log in. By default it’s filled with widgets that are either useless to non-technical users, the WordPress news feed, the quick draft, site health, or presented without context. Adding a custom branded widget that greets the user by name and provides direct links to the tasks they actually perform creates a much more professional and client-friendly experience.

The Code

Add this to your functions.php or a site-specific plugin. It registers a new dashboard widget using wp_add_dashboard_widget() and then repositions it to the top of the dashboard using a global meta box manipulation, so it’s the first thing the client sees, not buried below the default widgets.

How wp_add_dashboard_widget Works

wp_add_dashboard_widget() takes three required arguments: a unique widget ID, the widget title shown in the header bar, and the name of the callback function that renders the widget content. Optional fourth and fifth arguments accept a control callback and control arguments for widgets that need settings forms, which most simple widgets don’t need.

Moving the Widget to the Top

Dashboard widgets are stored in the global $wp_meta_boxes array. After registering the widget, the snippet extracts it from its default position in the normal/core group, unsets it from the array, and then re-inserts it at the beginning of the array using array_merge(). This ensures it renders at the top of the left column when the dashboard loads.

The Widget Content

The example widget renders a personalised greeting using wp_get_current_user(), a short list of quick-action links, and a simple stat line showing the number of published posts and pages from wp_count_posts(). All output is escaped, esc_html() for the display name and esc_url() for links.

Removing Default Widgets

A custom welcome widget works best when paired with removal of the cluttered default widgets. You can remove them on the same wp_dashboard_setup hook using remove_meta_box(). Common ones to remove for client sites include dashboard_primary (WordPress news), dashboard_quick_press (quick draft), and dashboard_activity. Removing dashboard_site_health is also common for clients who don’t need to manage technical site health checks.

Role-Specific Content

The render callback can include current_user_can() checks to show different content to different roles. An administrator might see database stats and plugin update counts, while an editor sees only content-related links. This makes a single widget serve multiple user types without requiring separate registrations.

functions.php
add_action( 'wp_dashboard_setup', function() {
    wp_add_dashboard_widget(
        'nahnu_welcome_widget',
        'Welcome to Your Website',
        'nsl_render_welcome_widget'
    );

    // Move our widget to the top of the dashboard
    global $wp_meta_boxes;
    $widget = $wp_meta_boxes['dashboard']['normal']['core']['nahnu_welcome_widget'];
    unset( $wp_meta_boxes['dashboard']['normal']['core']['nahnu_welcome_widget'] );
    $wp_meta_boxes['dashboard']['normal']['core'] = array_merge(
        [ 'nahnu_welcome_widget' => $widget ],
        $wp_meta_boxes['dashboard']['normal']['core']
    );
} );

function nsl_render_welcome_widget() {
    $user      = wp_get_current_user();
    $post_count = wp_count_posts()->publish;
    $page_count = wp_count_posts( 'page' )->publish;
    ?>
    <p>Hello, <strong><?php echo esc_html( $user->display_name ); ?></strong>! Here are a few quick links to get started.</p>
    <ul style="margin:12px 0;padding-left:18px">
        <li><a href="<?php echo esc_url( admin_url( 'post-new.php' ) ); ?>">Write a new post</a></li>
        <li><a href="<?php echo esc_url( admin_url( 'media-new.php' ) ); ?>">Upload media</a></li>
        <li><a href="<?php echo esc_url( admin_url( 'customize.php' ) ); ?>">Customise the site</a></li>
    </ul>
    <p style="margin-top:12px;padding-top:12px;border-top:1px solid #f0f0f0;font-size:13px;color:#64748b">
        <?php echo $post_count; ?> published posts · <?php echo $page_count; ?> pages
    </p>
    <?php
}

Built by Nahnu Plugins

Need something more powerful than a snippet?

Our commercial plugins go further, built for serious WordPress sites with full support, updates, and documentation included.

Browse All Plugins →

This website uses cookies to enhance your browsing experience and ensure the site functions properly. By continuing to use this site, you acknowledge and accept our use of cookies.

Accept All Accept Required Only