Redirecting After Plugin Activation

Occasionally when building a WordPress plugin, you may want to have the plugin immediately show its settings page after activation. I don’t typically like this practice because it’s an unexpected change to the standard WordPress user experience, but in certain circumstances it can make sense.

Criteria

I have a few rules that I believe developers should evaluate before adding an activation redirect:

  • The plugin does nothing without some initial configuration
  • The plugin settings screen is in a submenu that a user might not easily find
  • You feel confident that the user is activating the plugin with the intention to configure it immediately

If it doesn’t meet all three criteria, then I won’t add the redirect. The last one is subjective, and requires both a good understanding of your users and being honest about the importance of your plugin.

It’s also important to recognize how it will work when network activating in a multisite environment. It will only redirect for the network administrator who activated the plugin, and only for the primary site of the network (which contains the network admin). This isn’t necessarily a bad thing because you don’t want to redirect administrators of individual sites who did not know a plugin had been network activated, but it’s something to keep in mind.

Considerations

After you’ve decided that an activation redirect is the right choice, you’ll want to limit the scope to make it as smooth as possible.

There are some existing examples out there for how to handle a redirect like this, but most are fairly simple and don’t take into consideration some edge cases that might lead to redirects in situations where you wouldn’t want them to occur.

We should ensure:

1. Only redirect users once.

It’s pretty obvious you shouldn’t continue to redirect a user every time they visit the admin. It should only happen once and immediately after activation.

2. Only redirect the user who activated the plugin.

The odds are low because the timing has to be perfect, but if you have a highly active site with multiple authors who are working at the same time, you don’t want to accidentally redirect another user inside the WordPress admin. This is especially true if other users won’t have permission to view the settings page.

3. Do not redirect when bulk activating multiple plugins.

If your plugin was not the only plugin being activated, then you can’t assume that the user wants to view your settings page first.

How To Redirect

First you need to register an activation hook. In your primary plugin file, you can add this code:

register_activation_hook( __FILE__, 'jwe_activate' );

function jwe_activate() {}Code language: PHP (php)

This hook fires when the plugin is activated. It might seem logical to just put a redirect here, but that won’t work. In order to prevent accidental fatal errors in a plugin from making the admin inaccessible, plugins get activated inside an output buffer and ob_end_clean() is run before moving on. This prevents the Location header from getting returned if you were to run a wp_redirect() here.

To workaround this, WordPress redirects back to the plugins page after plugin activation. So what we can do instead is execute a redirect on the next admin page load.

We can store an option, and then check for that option via a hook on admin_init. If it exists, we delete it and execute the redirect. Something like this:

register_activation_hook( __FILE__, 'jwe_activate' );
add_action( 'admin_init', 'jwe_activation_redirect' );

/**
 * Plugin activation callback. Registers option to redirect on next admin load.
 */
function jwe_activate() {
	add_option( 'jwe_activation_redirect', true );
}

/**
 * Redirects the user after plugin activation
 */
function jwe_activation_redirect() {
	// Make sure it's the correct user
	if ( get_option( 'jwe_activation_redirect', false ) ) {
		// Make sure we don't redirect again after this one
		delete_option( 'jwe_activation_redirect' );
		wp_safe_redirect( admin_url( 'options-general.php?page=plugin-admin-page' ) );
		exit;
	}
}Code language: PHP (php)

This is what most of the suggestions call for if you were to Google for this problem. This is mostly fine, but it only accounts for #1 of the 3 considerations above. We can make it a little bit better.

First, we only want to execute the redirect for the user whom activated the plugin. To do that, we’ll store that user’s ID instead of a boolean in the option.

add_option( 'jwe_activation_redirect', wp_get_current_user()->ID );Code language: PHP (php)

Then we’ll check that value before doing the redirect.

if ( is_user_logged_in() && intval( get_option( 'jwe_activation_redirect', false ) ) === wp_get_current_user()->ID )Code language: PHP (php)

Make sure to note that the value from get_option() is returned as a string, so you’ll want to typecast it as an integer. We also need to verify the user is logged in first. The admin_init hook is triggered on all admin-ajax.php requests, so without that the redirect will occur for any unauthenticated Ajax requests.

Second, we want to verify that this isn’t a bulk activation of multiple plugins. To do that, we can check two things—an action request parameter and a checked value on the $_POST global.

if (
		( isset( $_REQUEST['action'] ) && 'activate-selected' === $_REQUEST['action'] ) &&
		( isset( $_POST['checked'] ) && count( $_POST['checked'] ) > 1 ) ) {
		return;
	}Code language: PHP (php)

That’s an ugly conditional, but it takes care of a few things:

  • It ensures that this activation occurred via the plugins page through an action parameter and not programmatically by something calling activate_plugin() directly.
  • It makes sure this is a bulk activation and not a single activation by looking for an action value of activate-selected.
  • And finally, it looks to see if more than one checkbox was actually checked for bulk activation.

Putting it all together

If we add up all of those parts, we have a nice redirect solution that limits unintended impacts.

// Set up the activation redirect
register_activation_hook( __FILE__, 'jwe_activate' );
add_action( 'admin_init', 'jwe_activation_redirect' );

/**
 * Plugin activation callback. Registers option to redirect on next admin load.
 *
 * Saves user ID to ensure it only redirects for the user who activated the plugin.
 */
function jwe_activate() {
	// Don't do redirects when multiple plugins are bulk activated
	if (
		( isset( $_REQUEST['action'] ) && 'activate-selected' === $_REQUEST['action'] ) &&
		( isset( $_POST['checked'] ) && count( $_POST['checked'] ) > 1 ) ) {
		return;
	}
	add_option( 'jwe_activation_redirect', wp_get_current_user()->ID );
}

/**
 * Redirects the user after plugin activation.
 */
function jwe_activation_redirect() {
	// Make sure it's the correct user
	if ( intval( get_option( 'jwe_activation_redirect', false ) ) === wp_get_current_user()->ID ) {
		// Make sure we don't redirect again after this one
		delete_option( 'jwe_activation_redirect' );
		wp_safe_redirect( admin_url( '/options-general.php?page=plugin-admin-page' ) );
		exit;
	}
}Code language: PHP (php)

3 Comments

  1. Thank you for the script William! I’ve just included it in a WP plugin I am working on and the redirect works splendidly. Thank you for sharing!

    • Hi William. After some tests I noticed that there is an error in the script. If an ajax call from front-end script is made to admin-ajax.php then somehow the test checking id (below) is passed (even if it shouldn’t, this might be a security threat).

      if ( intval( get_option( ‘fp_activation_redirect’ ) ) === wp_get_current_user()->ID )

      This modification helps solve the problem:

      if ( !wp_doing_ajax() && intval( get_option( ‘fp_activation_redirect’ ) ) === wp_get_current_user()->ID )

      You might want to update your script

Comments are closed.