WordPress admin notices are the coloured banners that appear at the top of the dashboard pages — you see them after activating a plugin, when a required setting is missing, or when an update is available. Adding your own admin notices is a simple and highly effective way to guide administrators through setup steps, warn about incompatible configurations, or confirm that a bulk action completed successfully. WordPress provides four CSS classes for notices: notice-success (green), notice-warning (yellow), notice-error (red), and notice-info (blue). Adding the is-dismissible class makes the notice closeable with an X button. The notice HTML is output inside the admin_notices action hook. For notices that should disappear once the user acknowledges them, you store a user meta flag and check it before displaying the notice — this requires a small AJAX handler to save the dismissal state when the user clicks the X, which is slightly more complex but produces a much better user experience. You can also add notices that appear only on specific admin pages by checking get_current_screen()->id. Notice content must always be escaped before output — use esc_html() for text and wp_kses_post() for HTML content. This is a useful technique to combine with the Theme Customizer to prompt users to complete required settings after plugin activation.
Problem: You want to display a custom admin notice after plugin activation, on specific admin pages, or as a persistent reminder until the user completes a required action.
Solution: Add the following code to your functions.php or plugin file:
/**
* Simple admin notice — shown to admins on all dashboard pages.
*/
add_action( 'admin_notices', 'helloadmin_simple_notice' );
function helloadmin_simple_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
echo '<div class="notice notice-info is-dismissible">
<p>' . esc_html__( 'Reminder: back up your database before running bulk updates.' ) . '</p>
</div>';
}
/**
* Persistent dismissible notice — stored in user meta so it disappears once dismissed.
*/
add_action( 'admin_notices', 'helloadmin_persistent_notice' );
function helloadmin_persistent_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( get_user_meta( get_current_user_id(), 'helloadmin_notice_dismissed', true ) ) {
return;
}
echo '<div class="notice notice-warning helloadmin-dismissible-notice" data-nonce="' . esc_attr( wp_create_nonce( 'helloadmin_dismiss_notice' ) ) . '">
<p><strong>Action required:</strong> Please <a href="' . esc_url( admin_url( 'options-general.php' ) ) . '">configure your API key</a> to enable all features.</p>
<button type="button" class="notice-dismiss"></button>
</div>';
}
// Handle AJAX dismissal
add_action( 'wp_ajax_helloadmin_dismiss_notice', 'helloadmin_handle_dismiss_notice' );
function helloadmin_handle_dismiss_notice() {
check_ajax_referer( 'helloadmin_dismiss_notice', 'nonce' );
update_user_meta( get_current_user_id(), 'helloadmin_notice_dismissed', true );
wp_die();
}
// Enqueue the dismiss handler JavaScript
add_action( 'admin_footer', 'helloadmin_notice_dismiss_js' );
function helloadmin_notice_dismiss_js() {
echo "<script>
jQuery(document).on('click', '.helloadmin-dismissible-notice .notice-dismiss', function() {
var nonce = jQuery(this).closest('.helloadmin-dismissible-notice').data('nonce');
jQuery.post(ajaxurl, { action: 'helloadmin_dismiss_notice', nonce: nonce });
});
</script>";
}
NOTE: Do not display admin notices to roles that cannot act on them — an editor who sees a notice about API keys they cannot configure will find it annoying and confusing. Always gate notices with current_user_can(). Also, the default WordPress dismissal (is-dismissible class) only hides the notice for the current page load — it reappears on the next page refresh. For truly persistent dismissal you need the AJAX approach shown above.