Skip to content

Hooks and Filters

WP OTP exposes three filter hooks for customising the OTP email, and registers several WordPress hooks internally. This page documents both.


Outgoing filters (for plugin consumers)

These are filters the plugin applies via apply_filters(). Third-party code can hook into them to customise behaviour.


wp_otp_email_subject

Filters the email subject line.

Signature:

apply_filters( 'wp_otp_email_subject', string $subject, \WP_User $user ): string

Parameter Type Description
$subject string Default: "Your login code for {site name}"
$user \WP_User The user who requested the OTP

Example — append the site tagline:

add_filter( 'wp_otp_email_subject', function ( string $subject, \WP_User $user ): string {
    return $subject . ' — ' . get_bloginfo( 'description' );
}, 10, 2 );


wp_otp_email_message

Filters the full email body.

Signature:

apply_filters( 'wp_otp_email_message', string $message, string $code, \WP_User $user ): string

Parameter Type Description
$message string Default HTML message (see below)
$code string The raw OTP code (e.g. "483920")
$user \WP_User The user who requested the OTP

Default message:

Sent as HTML. The header renders as a logo image when Settings → WP OTP → Email logo URL is set; otherwise it falls back to the site name as bold text. The site name is always read from Settings → General → Site Title (get_bloginfo('name')).

With logo:

<p style="margin:0 0 16px;">
  <img src="{logo_url}" alt="{site name}" style="max-height:{logo_height}px;display:block;">
</p>
<p style="margin:0;">Your {site name} login code is: <b>{code}</b>. This code expires in {duration} minutes.</p>

Without logo:

<p style="font-size:24px;font-weight:bold;margin:0 0 16px;">{site name}</p>
<p style="margin:0;">Your {site name} login code is: <b>{code}</b>. This code expires in {duration} minutes.</p>

Example — custom message:

add_filter( 'wp_otp_email_message', function ( string $message, string $code, \WP_User $user ): string {
    return sprintf(
        '<p>Hi %s,</p><p>Your login code is: <strong>%s</strong></p>',
        esc_html( $user->display_name ),
        esc_html( $code )
    );
}, 10, 3 );


wp_otp_email_headers

Filters the array of additional email headers passed to wp_mail().

Signature:

apply_filters( 'wp_otp_email_headers', string[] $headers, \WP_User $user ): string[]

Parameter Type Description
$headers string[] Default: [ 'Content-Type: text/html; charset=UTF-8' ]
$user \WP_User The user who requested the OTP

Example — add a Reply-To header:

add_filter( 'wp_otp_email_headers', function ( array $headers, \WP_User $user ): array {
    $headers[] = 'Reply-To: noreply@example.com';
    return $headers;
}, 10, 2 );


Incoming hooks (registered by the plugin)

These are hooks the plugin registers internally via add_filter() / add_action(). They are listed here for completeness — third-party code should not need to remove or re-hook them.

WP Login flow (WpLoginProvider)

Hook Type Priority Handler
authenticate filter 15 handle_step_one() — phase 1: intercept, generate OTP, redirect
login_init action 10 process_otp_submission() — phase 2: validate, set auth cookie
login_form action 10 render_otp_field() — inject OTP code input
login_head action 10 output_login_styles() — CSS/JS to hide/show fields
login_errors filter 10 filter_login_errors() — generic error message

Admin settings page (Admin)

Hook Type Priority Handler
admin_menu action 10 Register Settings → WP OTP page
admin_init action 10 Register settings group + fields

GraphQL layer (GraphQlProvider) — optional

Hook Type Priority Handler
graphql_login_registered_provider_configs filter 10 Register OtpGraphQlProviderConfig with AxeWP
graphql_register_types action 10 Register requestOtp mutation

WordPress core hooks used (read-only)

The plugin calls the following WordPress functions but does not register hooks for them:

Function Used by Purpose
set_transient / get_transient / delete_transient OtpStore OTP storage
wp_mail OtpMailer Email delivery
wp_set_auth_cookie WpLoginProvider Set login session
do_action( 'wp_login' ) WpLoginProvider Fire standard login action
get_option / update_option OtpSettings, Admin Settings persistence
register_setting / add_settings_section / add_settings_field Admin Settings API