Admin Bar Hooks

Filters and actions for customizing the WordPress admin bar.

Actions

admin_bar_init

Fires after WP_Admin_Bar is initialized.

do_action( 'admin_bar_init' );

Location: WP_Admin_Bar::initialize()

Timing: After user data populated, scripts/styles enqueued, before menus added

Usage:

add_action( 'admin_bar_init', 'my_admin_bar_init' );

function my_admin_bar_init() {
    // Early initialization tasks
    // Note: $wp_admin_bar is not passed to this action
}

admin_bar_menu

Loads all admin bar items. Primary hook for adding/removing nodes.

do_action_ref_array( 'admin_bar_menu', array( &$wp_admin_bar ) );

Location: wp_admin_bar_render()

Timing: During render, after add_menus(), before _bind()

Parameters:

  • $wp_admin_bar (WP_Admin_Bar) – Passed by reference

Usage:

add_action( 'admin_bar_menu', 'my_admin_bar_items', 100 );

function my_admin_bar_items( $wp_admin_bar ) {
    $wp_admin_bar->add_node( array(
        'id'    => 'my-custom-item',
        'title' => 'My Item',
        'href'  => '#',
    ) );
}

Priority Guidelines:

Priority Use Case
0-10 Before WordPress logo
10-30 With site menus
30-70 Content area
70-200 After core menus
200+ Secondary items
999+ For removing existing items

add_admin_bar_menus

Fires after default menus are added via add_menus().

do_action( 'add_admin_bar_menus' );

Location: WP_Admin_Bar::add_menus()

Timing: After all add_action( 'admin_bar_menu', ... ) calls in add_menus()

Usage:

add_action( 'add_admin_bar_menus', 'remove_default_admin_bar_menus' );

function remove_default_admin_bar_menus() {
    // Remove specific menu callbacks before they run
    remove_action( 'admin_bar_menu', 'wp_admin_bar_comments_menu', 60 );
    remove_action( 'admin_bar_menu', 'wp_admin_bar_new_content_menu', 70 );
}

wp_before_admin_bar_render

Fires immediately before the admin bar is rendered.

do_action( 'wp_before_admin_bar_render' );

Location: wp_admin_bar_render()

Timing: After admin_bar_menu action, before render()

Global Available: $wp_admin_bar

Usage:

add_action( 'wp_before_admin_bar_render', 'final_admin_bar_modifications' );

function final_admin_bar_modifications() {
    global $wp_admin_bar;
    
    // Last chance to modify nodes before rendering
    $wp_admin_bar->remove_node( 'updates' );
    
    // Modify existing node
    $site_name = $wp_admin_bar->get_node( 'site-name' );
    if ( $site_name ) {
        $wp_admin_bar->add_node( array(
            'id'    => 'site-name',
            'title' => '🏠 ' . $site_name->title,
        ) );
    }
}

Best For: Modifications that don’t need a specific priority


wp_after_admin_bar_render

Fires immediately after the admin bar is rendered.

do_action( 'wp_after_admin_bar_render' );

Location: wp_admin_bar_render()

Timing: After HTML output complete

Usage:

add_action( 'wp_after_admin_bar_render', 'after_admin_bar_output' );

function after_admin_bar_output() {
    // Output additional content after admin bar
    echo '<style>#wpadminbar { background: #23282d; }</style>';
}

Filters

show_admin_bar

Filters whether to show the admin bar.

$show_admin_bar = apply_filters( 'show_admin_bar', $show_admin_bar );

Location: is_admin_bar_showing()

Parameters:

  • $show_admin_bar (bool) – Default based on user preference and context

Returns: bool

Usage:

// Hide admin bar for subscribers
add_filter( 'show_admin_bar', 'hide_admin_bar_for_subscribers' );

function hide_admin_bar_for_subscribers( $show ) {
    if ( current_user_can( 'subscriber' ) ) {
        return false;
    }
    return $show;
}

// Hide on specific pages
add_filter( 'show_admin_bar', 'hide_admin_bar_on_landing_pages' );

function hide_admin_bar_on_landing_pages( $show ) {
    if ( is_page( 'landing-page' ) ) {
        return false;
    }
    return $show;
}

// Always show (override user preference)
add_filter( 'show_admin_bar', '__return_true' );

// Always hide
add_filter( 'show_admin_bar', '__return_false' );

wp_admin_bar_class

Filters the admin bar class to instantiate.

$admin_bar_class = apply_filters( 'wp_admin_bar_class', 'WP_Admin_Bar' );

Location: _wp_admin_bar_init()

Parameters:

  • $wp_admin_bar_class (string) – Class name. Default ‘WP_Admin_Bar’

Returns: string (class name)

Usage:

add_filter( 'wp_admin_bar_class', 'use_custom_admin_bar' );

function use_custom_admin_bar( $class ) {
    require_once 'class-my-admin-bar.php';
    return 'My_Admin_Bar';
}

class My_Admin_Bar extends WP_Admin_Bar {
    public function render() {
        // Custom rendering
        parent::render();
    }
}

wp_admin_bar_show_site_icons

Filters whether to show site icons in the "My Sites" menu.

$show_site_icons = apply_filters( 'wp_admin_bar_show_site_icons', true );

Location: wp_admin_bar_my_sites_menu()

Parameters:

  • $show_site_icons (bool) – Default true

Returns: bool

Context: Multisite only

Usage:

// Disable for performance on large multisites
add_filter( 'wp_admin_bar_show_site_icons', '__return_false' );

// Conditional based on network size
add_filter( 'wp_admin_bar_show_site_icons', 'conditional_site_icons' );

function conditional_site_icons( $show ) {
    // Disable if user has more than 50 sites
    $user_blogs = get_blogs_of_user( get_current_user_id() );
    if ( count( $user_blogs ) > 50 ) {
        return false;
    }
    return $show;
}

Related Hooks

wp_head / admin_head

Admin bar adds callbacks to these hooks during initialization:

add_action( 'wp_head', 'wp_admin_bar_header' );
add_action( 'admin_head', 'wp_admin_bar_header' );

wp_body_open / wp_footer

Admin bar renders on these hooks:

// Primary (if theme supports)
add_action( 'wp_body_open', 'wp_admin_bar_render', 0 );

// Fallback for older themes
add_action( 'wp_footer', 'wp_admin_bar_render' );

Hook Execution Order

1. wp_loaded
   └── _wp_admin_bar_init()
       ├── wp_admin_bar_class filter
       ├── WP_Admin_Bar::initialize()
       │   └── admin_bar_init action
       └── WP_Admin_Bar::add_menus()
           └── add_admin_bar_menus action

2. wp_body_open or wp_footer
   └── wp_admin_bar_render()
       ├── admin_bar_menu action (all menu callbacks run)
       ├── wp_before_admin_bar_render action
       ├── WP_Admin_Bar::render()
       └── wp_after_admin_bar_render action

Common Patterns

Remove Multiple Items

add_action( 'admin_bar_menu', 'cleanup_admin_bar', 999 );

function cleanup_admin_bar( $wp_admin_bar ) {
    $remove = array(
        'wp-logo',
        'about',
        'wporg',
        'documentation',
        'support-forums',
        'feedback',
        'comments',
        'updates',
        'new-content',
    );
    
    foreach ( $remove as $id ) {
        $wp_admin_bar->remove_node( $id );
    }
}

Role-Based Menu Items

add_action( 'admin_bar_menu', 'role_based_admin_bar', 100 );

function role_based_admin_bar( $wp_admin_bar ) {
    $user = wp_get_current_user();
    
    if ( in_array( 'administrator', $user->roles ) ) {
        $wp_admin_bar->add_node( array(
            'id'    => 'admin-tools',
            'title' => 'Admin Tools',
            'href'  => admin_url( 'tools.php' ),
        ) );
    }
    
    if ( in_array( 'editor', $user->roles ) ) {
        $wp_admin_bar->add_node( array(
            'id'    => 'pending-posts',
            'title' => 'Pending Posts',
            'href'  => admin_url( 'edit.php?post_status=pending' ),
        ) );
    }
}

Complete Removal with Prevention

// Remove all default actions
add_action( 'add_admin_bar_menus', 'remove_all_admin_bar_menus' );

function remove_all_admin_bar_menus() {
    remove_all_actions( 'admin_bar_menu' );
}

// Then add only what you want
add_action( 'admin_bar_menu', 'minimal_admin_bar', 10 );

function minimal_admin_bar( $wp_admin_bar ) {
    $wp_admin_bar->add_node( array(
        'id'    => 'site-name',
        'title' => get_bloginfo( 'name' ),
        'href'  => home_url(),
    ) );
    
    $wp_admin_bar->add_node( array(
        'parent' => 'top-secondary',
        'id'     => 'logout',
        'title'  => 'Log Out',
        'href'   => wp_logout_url(),
    ) );
}

Dynamic Menu Based on Page Context

add_action( 'admin_bar_menu', 'context_aware_admin_bar', 80 );

function context_aware_admin_bar( $wp_admin_bar ) {
    if ( is_singular( 'product' ) ) {
        $wp_admin_bar->add_node( array(
            'id'    => 'woo-actions',
            'title' => 'Product Actions',
        ) );
        
        $wp_admin_bar->add_node( array(
            'parent' => 'woo-actions',
            'id'     => 'duplicate-product',
            'title'  => 'Duplicate',
            'href'   => admin_url( 'admin.php?action=duplicate&product=' . get_the_ID() ),
        ) );
    }
    
    if ( is_archive() ) {
        $wp_admin_bar->add_node( array(
            'id'    => 'archive-count',
            'title' => sprintf( '%d posts', $GLOBALS['wp_query']->found_posts ),
        ) );
    }
}

Add External Links Group

add_action( 'admin_bar_menu', 'add_external_links', 100 );

function add_external_links( $wp_admin_bar ) {
    $wp_admin_bar->add_node( array(
        'id'    => 'external-links',
        'title' => 'Resources',
    ) );
    
    $wp_admin_bar->add_group( array(
        'parent' => 'external-links',
        'id'     => 'external-links-main',
    ) );
    
    $links = array(
        'analytics' => array( 'Google Analytics', 'https://analytics.google.com/' ),
        'gsc'       => array( 'Search Console', 'https://search.google.com/search-console' ),
        'pagespeed' => array( 'PageSpeed', 'https://pagespeed.web.dev/' ),
    );
    
    foreach ( $links as $id => $link ) {
        $wp_admin_bar->add_node( array(
            'parent' => 'external-links-main',
            'id'     => 'external-' . $id,
            'title'  => $link[0],
            'href'   => $link[1],
            'meta'   => array(
                'target' => '_blank',
                'rel'    => 'noopener noreferrer',
            ),
        ) );
    }
}