WordPress Plugin-Specific Hooks

This document covers hooks specifically related to plugin lifecycle, management, and pluggable function customization. For the general action/filter system, see the hooks-api documentation.

Plugin Activation Hooks

activate_plugin

Fires before a plugin is activated (non-silent only).

add_action( 'activate_plugin', function( $plugin, $network_wide ) {
    error_log( "Activating: $plugin" );
}, 10, 2 );

Parameters:

  • $plugin (string) – Plugin path relative to plugins directory
  • $network_wide (bool) – Network activation (Multisite)

activate_{$plugin}

Fires for a specific plugin during activation.

This is the hook used by register_activation_hook().

// For plugin 'my-plugin/my-plugin.php'
add_action( 'activate_my-plugin/my-plugin.php', function( $network_wide ) {
    // Activation logic
} );

Parameters:

  • $network_wide (bool) – Network activation (Multisite)

activated_plugin

Fires after a plugin has been activated (non-silent only).

add_action( 'activated_plugin', function( $plugin, $network_wide ) {
    // Clear any caches
    wp_cache_flush();
}, 10, 2 );

Parameters:

  • $plugin (string) – Plugin path relative to plugins directory
  • $network_wide (bool) – Network activation

Plugin Deactivation Hooks

deactivate_plugin

Fires before a plugin is deactivated (non-silent only).

add_action( 'deactivate_plugin', function( $plugin, $network_deactivating ) {
    error_log( "Deactivating: $plugin" );
}, 10, 2 );

Parameters:

  • $plugin (string) – Plugin path relative to plugins directory
  • $network_deactivating (bool) – Network deactivation

deactivate_{$plugin}

Fires for a specific plugin during deactivation.

This is the hook used by register_deactivation_hook().

// For plugin 'my-plugin/my-plugin.php'
add_action( 'deactivate_my-plugin/my-plugin.php', function( $network_deactivating ) {
    // Cleanup scheduled tasks, transients, etc.
    wp_clear_scheduled_hook( 'my_plugin_cron_job' );
} );

deactivated_plugin

Fires after a plugin has been deactivated (non-silent only).

add_action( 'deactivated_plugin', function( $plugin, $network_deactivating ) {
    // Post-deactivation tasks
}, 10, 2 );

Plugin Deletion Hooks

delete_plugin

Fires before a plugin deletion attempt.

add_action( 'delete_plugin', function( $plugin_file ) {
    // Log deletion attempt
    error_log( "Deleting plugin: $plugin_file" );
} );

Parameters:

  • $plugin_file (string) – Plugin path relative to plugins directory

deleted_plugin

Fires after a plugin deletion attempt.

add_action( 'deleted_plugin', function( $plugin_file, $deleted ) {
    if ( $deleted ) {
        error_log( "Successfully deleted: $plugin_file" );
    }
}, 10, 2 );

Parameters:

  • $plugin_file (string) – Plugin path
  • $deleted (bool) – Whether deletion was successful

Plugin Loading Hooks

muplugins_loaded

Fires after must-use plugins have loaded.

add_action( 'muplugins_loaded', function() {
    // All mu-plugins are now loaded
    // Regular plugins not yet loaded
} );

plugins_loaded

Fires after all plugins have loaded.

add_action( 'plugins_loaded', function() {
    // All plugins are now available
    // Good place for plugin compatibility checks
    if ( class_exists( 'WooCommerce' ) ) {
        // WooCommerce integration
    }
} );

Priority considerations:

  • Default: 10
  • Early (before most plugins): 0-5
  • Late (after most plugins): 20+

plugin_loaded

Fires after a single plugin is loaded.

add_action( 'plugin_loaded', function( $plugin ) {
    // $plugin is the full path to the plugin file
} );

Parameters:

  • $plugin (string) – Full path to plugin file

Plugin Update Hooks

upgrader_process_complete

Fires when plugin/theme/core update completes.

add_action( 'upgrader_process_complete', function( $upgrader, $options ) {
    if ( 'plugin' === $options['type'] ) {
        // Plugin was updated
        $plugins = $options['plugins'] ?? array();
    }
}, 10, 2 );

Parameters:

  • $upgrader (WP_Upgrader) – Upgrader instance
  • $options (array) – Contains ‘type’, ‘action’, ‘plugins’/’themes’

Email Hooks (Pluggable)

wp_mail

Filters all wp_mail() arguments.

add_filter( 'wp_mail', function( $args ) {
    // Modify any email argument
    $args['subject'] = '[SITE] ' . $args['subject'];
    return $args;
} );

Parameters:

  • $args (array) – ‘to’, ‘subject’, ‘message’, ‘headers’, ‘attachments’, ’embeds’

pre_wp_mail

Short-circuits wp_mail() to prevent sending.

add_filter( 'pre_wp_mail', function( $return, $atts ) {
    // Log instead of sending
    error_log( "Would send email to: " . print_r( $atts['to'], true ) );
    return true; // Pretend it was sent
}, 10, 2 );

Returns: Non-null value to short-circuit


wp_mail_from

Filters the "from" email address.

add_filter( 'wp_mail_from', function( $from_email ) {
    return '[email protected]';
} );

wp_mail_from_name

Filters the "from" name.

add_filter( 'wp_mail_from_name', function( $from_name ) {
    return 'My Website';
} );

wp_mail_content_type

Filters the content type.

add_filter( 'wp_mail_content_type', function( $content_type ) {
    return 'text/html';
} );

wp_mail_charset

Filters the character set.

add_filter( 'wp_mail_charset', function( $charset ) {
    return 'UTF-8';
} );

phpmailer_init

Customize PHPMailer directly.

add_action( 'phpmailer_init', function( $phpmailer ) {
    // Use SMTP
    $phpmailer->isSMTP();
    $phpmailer->Host = 'smtp.example.com';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 587;
    $phpmailer->Username = '[email protected]';
    $phpmailer->Password = 'secret';
} );

Parameters:

  • $phpmailer (PHPMailer) – Passed by reference

wp_mail_succeeded

Fires after successful email send.

add_action( 'wp_mail_succeeded', function( $mail_data ) {
    // Log successful email
    error_log( "Email sent to: " . implode( ', ', $mail_data['to'] ) );
} );

wp_mail_failed

Fires when email sending fails.

add_action( 'wp_mail_failed', function( $error ) {
    error_log( 'Email failed: ' . $error->get_error_message() );
} );

Parameters:

  • $error (WP_Error) – Contains message and mail data

Authentication Hooks

authenticate

Filters user authentication.

// Custom authentication source
add_filter( 'authenticate', function( $user, $username, $password ) {
    if ( ! $user && my_custom_auth( $username, $password ) ) {
        return get_user_by( 'login', $username );
    }
    return $user;
}, 30, 3 );

Parameters:

  • $user (null|WP_User|WP_Error) – Current authentication result
  • $username (string) – Username or email
  • $password (string) – Password

Default Handlers (priority):

  • 20: wp_authenticate_username_password
  • 20: wp_authenticate_email_password
  • 30: wp_authenticate_spam_check

wp_login_failed

Fires after failed login attempt.

add_action( 'wp_login_failed', function( $username, $error ) {
    // Track failed attempts
    $attempts = get_transient( 'login_attempts_' . $username ) ?: 0;
    set_transient( 'login_attempts_' . $username, $attempts + 1, HOUR_IN_SECONDS );
}, 10, 2 );

wp_login

Fires after successful login.

add_action( 'wp_login', function( $user_login, $user ) {
    // Log successful login
    update_user_meta( $user->ID, 'last_login', current_time( 'mysql' ) );
}, 10, 2 );

wp_logout

Fires after user logs out.

add_action( 'wp_logout', function( $user_id ) {
    // Cleanup user session data
    delete_user_meta( $user_id, 'my_session_data' );
} );

set_current_user

Fires after current user is set.

add_action( 'set_current_user', function() {
    $user = wp_get_current_user();
    // React to user change
} );

Cookie Hooks

auth_cookie_expiration

Filters cookie expiration time.

add_filter( 'auth_cookie_expiration', function( $length, $user_id, $remember ) {
    if ( $remember ) {
        return 30 * DAY_IN_SECONDS; // 30 days instead of 14
    }
    return $length;
}, 10, 3 );

set_auth_cookie

Fires before auth cookie is set.

add_action( 'set_auth_cookie', function( $auth_cookie, $expire, $expiration, $user_id, $scheme, $token ) {
    // Additional cookie logic
}, 10, 6 );

set_logged_in_cookie

Fires before logged-in cookie is set.


clear_auth_cookie

Fires before auth cookies are cleared.


send_auth_cookies

Filters whether to actually send auth cookies.

add_filter( 'send_auth_cookies', function( $send ) {
    // Prevent cookies in headless context
    if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
        return false;
    }
    return $send;
} );

Auth Cookie Validation Actions

// Cookie is malformed
add_action( 'auth_cookie_malformed', function( $cookie, $scheme ) {}, 10, 2 );

// Cookie has expired
add_action( 'auth_cookie_expired', function( $cookie_elements ) {} );

// Username in cookie doesn't exist
add_action( 'auth_cookie_bad_username', function( $cookie_elements ) {} );

// Hash doesn't match
add_action( 'auth_cookie_bad_hash', function( $cookie_elements ) {} );

// Session token invalid
add_action( 'auth_cookie_bad_session_token', function( $cookie_elements ) {} );

// Cookie validated successfully
add_action( 'auth_cookie_valid', function( $cookie_elements, $user ) {}, 10, 2 );

Nonce Hooks

nonce_life

Filters nonce lifespan.

add_filter( 'nonce_life', function( $lifespan, $action ) {
    // Shorter lifespan for sensitive actions
    if ( 'delete_post' === $action ) {
        return HOUR_IN_SECONDS;
    }
    return $lifespan;
}, 10, 2 );

nonce_user_logged_out

Filters user ID for logged-out nonce creation.

add_filter( 'nonce_user_logged_out', function( $uid, $action ) {
    return $uid; // 0 for logged out users
}, 10, 2 );

wp_verify_nonce_failed

Fires when nonce verification fails.

add_action( 'wp_verify_nonce_failed', function( $nonce, $action, $user, $token ) {
    error_log( "Nonce failed for action: $action" );
}, 10, 4 );

check_admin_referer

Fires after admin referer check.

add_action( 'check_admin_referer', function( $action, $result ) {
    // $result is false or 1/2
}, 10, 2 );

check_ajax_referer

Fires after ajax referer check.


Password Hooks

wp_hash_password_algorithm

Filters the password hashing algorithm.

add_filter( 'wp_hash_password_algorithm', function( $algorithm ) {
    return PASSWORD_ARGON2ID; // If available
} );

wp_hash_password_options

Filters password hashing options.

add_filter( 'wp_hash_password_options', function( $options, $algorithm ) {
    if ( PASSWORD_BCRYPT === $algorithm ) {
        $options['cost'] = 12;
    }
    return $options;
}, 10, 2 );

check_password

Filters password verification result.

add_filter( 'check_password', function( $check, $password, $hash, $user_id ) {
    return $check;
}, 10, 4 );

password_needs_rehash

Filters whether password needs rehashing.


random_password

Filters generated password.

add_filter( 'random_password', function( $password, $length, $special, $extra_special ) {
    return $password;
}, 10, 4 );

wp_set_password

Fires after password is set.

add_action( 'wp_set_password', function( $password, $user_id, $old_user_data ) {
    // Notify user of password change
}, 10, 3 );

Redirect Hooks

wp_redirect

Filters redirect location.

add_filter( 'wp_redirect', function( $location, $status ) {
    // Modify redirect URL
    return $location;
}, 10, 2 );

wp_redirect_status

Filters redirect HTTP status code.

add_filter( 'wp_redirect_status', function( $status, $location ) {
    return $status;
}, 10, 2 );

allowed_redirect_hosts

Filters allowed redirect hosts for safe redirects.

add_filter( 'allowed_redirect_hosts', function( $hosts, $host ) {
    $hosts[] = 'trusted-site.com';
    return $hosts;
}, 10, 2 );

wp_safe_redirect_fallback

Filters fallback URL when redirect is unsafe.

add_filter( 'wp_safe_redirect_fallback', function( $fallback, $status ) {
    return home_url();
}, 10, 2 );

Salt & Hash Hooks

salt

Filters the generated salt.

add_filter( 'salt', function( $salt, $scheme ) {
    // Add extra entropy
    return $salt . 'extra-secret';
}, 10, 2 );

Avatar Hooks

pre_get_avatar

Short-circuits get_avatar().

add_filter( 'pre_get_avatar', function( $avatar, $id_or_email, $args ) {
    // Return custom avatar HTML to skip Gravatar
    return '<img src="custom-avatar.png" />';
}, 10, 3 );

get_avatar

Filters final avatar HTML.

add_filter( 'get_avatar', function( $avatar, $id_or_email, $size, $default, $alt, $args ) {
    // Modify avatar HTML
    return $avatar;
}, 10, 6 );

Plugin File Hooks

plugin_files_exclusions

Filters directories/files excluded from plugin file scan.

add_filter( 'plugin_files_exclusions', function( $exclusions ) {
    $exclusions[] = 'tests';
    $exclusions[] = '.git';
    return $exclusions;
} );

Default exclusions: ‘CVS’, ‘node_modules’, ‘vendor’, ‘bower_components’


plugins_url

Filters plugins directory URL.

add_filter( 'plugins_url', function( $url, $path, $plugin ) {
    // Modify plugins URL (e.g., for CDN)
    return $url;
}, 10, 3 );