Make WordPress Core

Opened 2 weeks ago

Last modified 25 hours ago

#61040 new enhancement

Provide a framework for plugin onboarding experiences

Reported by: jorbin's profile jorbin Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Plugins Keywords:
Focuses: administration Cc:

Description

Building off conversations happening in #60992, there is an opportunity for core to provide a framework that is more advanced that the existing register_activation_hook

By framework, I mean a set of hook and potentially broader functionality for plugins to use. I think plugins will still need to figure out what this means for that, but providing a consistent route to enter this will benefit the users of Core.

Change History (23)

#1 follow-up: @kevinwhoffman
2 weeks ago

Can I suggest that we frame this problem as "plugin configuration" rather than "plugin onboarding"? Not every plugin that allows for configuration has a distinct onboarding experience, and the need to discover where configuration takes place is not limited to right after activation.

If we can establish a framework for plugins to communicate where configuration takes place, then core can use that value in ways that improve not just onboarding, but the more general problem of discoverability when it comes to understanding all of the possible places where plugins can be configured.

#2 in reply to: โ†‘ย description @jeherve
2 weeks ago

Replying to kevinwhoffman:

Can I suggest that we frame this problem as "plugin configuration" rather than "plugin onboarding"? Not every plugin that allows for configuration has a distinct onboarding experience, and the need to discover where configuration takes place is not limited to right after activation.

I think that's a good point. Many plugins "only" register a Custom Post Type for example, and linking to the CPT menu after installation would make sense in my opinion, it's the logical next step for the site owner, even if no "onboarding" needs to happen.

#3 @poena
2 weeks ago

Adding that the need for onboarding is not limited to plugins, there is a high need for better onboarding for themes.

#4 in reply to: โ†‘ย 1 @jason_the_adams
2 weeks ago

Replying to kevinwhoffman:

Can I suggest that we frame this problem as "plugin configuration" rather than "plugin onboarding"? Not every plugin that allows for configuration has a distinct onboarding experience, and the need to discover where configuration takes place is not limited to right after activation.

I want to be careful not to generalize this too much. For many plugins the onboarding is a rather critical step in the process. For me "configuration" implies adjustment, while onboarding is more like installation.

Right now a plugin is simply activated in WordPress. You click "activate" and now it's running. But think about software, where installation is not simply whether it exists on your machine or not, but setting up the initial configuration necessary for it to function properly.

Some examples of this:

  • Setting up a payment gateway for a donation plugin
  • Providing SSH/FTP credentials for a backup plugin
  • Selecting security preferences for a security plugin (to prevent problematic defaults)

I like the idea of having a way for folks to know how to go configure a plugin further after installation (e.g. changing the "Activate" button to "Configure"), but want to make it clear that many plugins move users on redirect to onboard not just because it's useful.

#5 @kevinwhoffman
7 days ago

In Post Status, @afragen asked for more details about my "Configure" link proposal originally posted in ticket:60992#comment:53, so I'll copy my response here for transparency:

Given that different plugins can live in different areas of WP Admin, I donโ€™t think core can possibly apply a standard โ€œConfigureโ€ link to all plugins, so each plugin would define its own โ€œConfigureโ€ link. Possible methods of definition include a Configuration field in the plugin header or a hook provided by core. I imagine the value would be a path relative to /wp-admin such as /admin.php?page=wpseo_dashboard#top#first-time-configuration for Yoast SEO. This allows the configuration page to work on sites where WP Admin is in a non-standard location.

Examples:

  • For plugins like WooCommerce, Yoast SEO, and GiveWP which have first-time onboarding experiences, the โ€œConfigureโ€ link could be set to the onboarding wizard.
  • For plugins like ACF that do not have a first-time onboarding experience, the โ€œConfigureโ€ link could be set to the Fields Groups page which provides some guidance through an empty state panel.
  • For plugins like Hello Dolly with no standalone plugin pages, the โ€œConfigureโ€ link can be left undefined and the existing disabled โ€œActiveโ€ button can be displayed.

Itโ€™s important to emphasize that the โ€œConfigureโ€ link should be timeless; it should always allow you to configure the plugin, whether it is immediately after activation or 30 days later. If a user clicks โ€œConfigureโ€ some time after completing the onboarding experience, then the plugin should recognize this and redirect them to an appropriate settings page (similar to what happens when you skip an onboarding wizard). Yes, plugins with onboarding experiences would still use a redirect, but the difference is that the plugin determines where itโ€™s best to send the user after the user has signaled an intent to configure the plugin. The user makes the choice, and the plugin responds.

Historically plugins have felt the need to redirect based on an activation hook because there was no other reliable convention in place to direct a user to whatโ€™s next after plugin activation . With a prominent โ€œConfigureโ€ link in key areas of WP Admin, plugin developers can rely on it as the funnel into plugin configuration and move away from relying on post-activation redirects.

#6 follow-up: @costdev
7 days ago

For me "configuration" implies adjustment, while onboarding is more like installation.

But think about software, where installation is not simply whether it exists on your machine or not, but setting up the initial configuration necessary for it to function properly.

I think that's where "configuration" and "initial configuration" don't need to be differentiated by a Core feature, but rather by a plugin detecting whether the user has done an initial configuration yet. I see onboarding as what you see at the "first launch", and the detection/content there is typically done by the application (read: plugin), not the OS (read: WordPress). Thinking along the lines of mobile apps in that regard, rather than desktop installers.

Given that onboarding/initial configuration should have multiple entry points (since plugins can be installed and activated several ways), it seems reasonable to expect that feature-complete onboarding would include state management via an option or transient (like WooCommerce does with _wc_activation_redirect).


I'd like to determine the extent to which such a framework might go. For example, do we want to do more than something like this? If so, what are your ideas?

  1. Add a '{$plugin}_configuration_url' filter hook.
    1. Plugins can decide whether this goes to an onboarding/initial configuration URL, or a settings page. Or even go to the same URL and perform state checks before/after the page loads.
  2. If filtered:
    1. Plugins > Add New: Replace the Active button with a Configure button in the plugin's card.
    2. Modals: Replace the Active button with a Configure button in the modal's footer.
    3. Plugins > Installed plugins: Add a Configure action link in the plugin's row.

Though we're discussing plugins at the moment, if we were to extend this to themes now or in future: {$theme}_configuration_url and either a button, or an extra link in the "New theme activated. <a>Visit site</a>" admin notice post-activation.

And now that I've typed this, Kevin just posted, so I'm going to post this and now scroll up to read what Kevin wrote. ๐Ÿ˜†

#7 follow-up: @costdev
7 days ago

@kevinwhoffman I agree with everything you said - On hook vs plugin header, I'd lean towards a filter hook because the plugin author should be able to decide whether to point it to a URL which determines whether to show onboarding vs settings, or to have separate URLs and conditionally return one of them in the filter's callback.

#8 in reply to: โ†‘ย 6 @kevinwhoffman
7 days ago

Replying to costdev:

I think that's where "configuration" and "initial configuration" don't need to be differentiated by a Core feature, but rather by a plugin detecting whether the user has done an initial configuration yet.

Well said, we're on the same page here. Configuration is always possible, but the nature of the configuration depends on what has already been done (or not).

On hook vs plugin header, I'd lean towards a filter hook because the plugin author should be able to decide whether to point it to a URL which determines whether to show onboarding vs settings, or to have separate URLs and conditionally return one of them in the filter's callback

Agreed, a filter would be more powerful. I initially liked the simplicity of a plugin header field, but conditional scenarios could be handled much better through a filter. It's also worth noting some of these onboarding URLs can look pretty funky, so including a partial path in the plugin header would likely confuse new developers who don't know exactly what it's for.

#9 @alanfuller
7 days ago

In terms of user expectation on activate, @kevinwhoffman expressed an opinion that user don't expect activate to actually activate an onboarding or redirect to settings.

I argue that in fact they do.

Most users now are used to apps on phones, in fact many users refer to plugins as apps. With an app from an app store there is a two stage process, install and open. The open activates the intial onboarding like create an account and set up wizard.

I feel this is something that needs to be examined in detail with some real user feedback, rather than the opinions of a couple of people for and against.

I apologize if extensive research has already been done, and if so can we have a link to it?

My opinion is just my opinion, but having used 6.5 heavily I have formed a personal opinion about the lack of auto refresh, regardless of onboarding or not, feels horrendous, I am a plugin developer and know fully about this issue yet every time I add a plugin, which is multiple times a day my gut 'expects' to find the items on the dashboard and my 'gut' panics and thinks something is broken.

I appreciate the efforts looking into this.

Last edited 7 days ago by alanfuller (previous) (diff)

#10 in reply to: โ†‘ย 7 @jeherve
7 days ago

Replying to costdev:

@kevinwhoffman I agree with everything you said - On hook vs plugin header, I'd lean towards a filter hook because the plugin author should be able to decide whether to point it to a URL which determines whether to show onboarding vs settings, or to have separate URLs and conditionally return one of them in the filter's callback.

Would a hook be a viable option here? As long as there hasn't been a page refresh the plugin's code hasn't run, so any functions defining an onboarding/configuration URL would not be available yet, at least from what I can tell.

The plugin header option would allow us to work around that limitation.

#11 @alanfuller
7 days ago

I was just about to say Plugin Header might be a way to go, but also need to think about localization. I guess the 'polygots' scan could be modified to add a plugin header string by meta - not sure how complex.

#12 @alanfuller
7 days ago

We also could get really funky and have a plugins.json in the root that is rather like blueprint.json with steps - just a random thought.

#13 follow-ups: @costdev
7 days ago

Would a hook be a viable option here? As long as there hasn't been a page refresh the plugin's code hasn't run, so any functions defining an onboarding/configuration URL would not be available yet, at least from what I can tell.

Yeah it works because activate_plugin() calls plugin_sandbox_scrape() which loads the main plugin file, which is where I would imagine we'd advise plugin authors to put it. It's a configuration thing, so I wouldn't recommend someone puts it behind an init hook. Options/Transients should already be available if they want to base their URL on the value of one.


For fellow "lemme try" people:

  1. Enable WP_DEBUG and WP_DEBUG_LOG.
  2. Go to Plugins > Add New and install WooCommerce. Do not activate it yet
  3. Modify woocommerce/woocommerce.php to add this after the ABSPATH bail:
    add_filter(
            plugin_basename( __FILE__ ) . '_configuration_url',
            function () {
                    return admin_url( 'admin.php?page=wc-admin' );
            }
    );
    
  4. Modify wp_ajax_activate_plugin() (in src/wp-admin/includes/ajax-actions.php) so it ends with the following:
    // Add these two lines above the call to wp_send_json_success().
    $configuration_url = apply_filters( $status['plugin'] . '_configuration_url', '' );
    error_log( $configuration_url );
    
    wp_send_json_success( $status );
    
  5. Activate WooCommerce and check wp-content/debug.log.
Last edited 7 days ago by afragen (previous) (diff)

#14 @kevinwhoffman
7 days ago

Refreshing vs. Redirecting

As soon as a plugin is activated, any presence that it has in the WP Admin UI should instantly be reflected without further action required by the user. This primarily includes items appearing in the admin menu and admin bar, since those elements are likely visible in the viewport when activation occurs. A user who has already clicked "Activate" should not have to take yet another action to see the results of said activation.

Ideally updating the UI would happen without a page refresh, but if a refresh is necessary, I think it's acceptable to reload the current page in order to update the UI. The risk with refreshing the page in order to update the UI is that plugins using the activation hook for onboarding redirects will then take over. I believe this is one of the primary reasons why the auto-refresh was removed in the first place. Perhaps this is a challenge better left to the wider effort of updating WP Admin as I imagine the admin menu and admin bar will change significantly.

WordPress should avoid redirecting to a completely separate plugin onboarding experience as a result of pressing "Activate." Onboarding is configuration, not activation. An "active" plugin has an established meaning in WordPress that we should honor. Active does not mean that the plugin is fully configured and ready to do its job; it simply means that the plugin code is active on the site. WooCommerce, Yoast SEO, and GiveWP can all be "active" without having to open or complete any of their onboarding wizards.

The iPhone App Store as an analog

If we're using the iPhone App store as an analog, then pressing "Get" in the app store is the equivalent of pressing both "Install" and "Activate" on the WordPress Plugins screen. At the end of that process, you've got an app/plugin on your phone/site that is now active and available to use. It is not necessarily configured and ready to do its job.

In order to actually experience the phone app, you tap the "Open" button which appears in place of the "Get" button. In WordPress, this would be the equivalent of pressing the proposed "Configure" button that takes the place of the "Activate" button in the plugin card.

So while it's valuable to consider popular conventions like the App Store when deciding how similar experiences should work within WordPress, we need to be aware that there is not an apples-to-apples comparison. WordPress considers "Install" and "Activate" to be two separate steps whereas the App Store uses a singular "Get" action to accomplish both steps.

#15 in reply to: โ†‘ย 13 @afragen
7 days ago

Replying to costdev:

  1. Modify wp_ajax_activate_plugin() (in src/wp-admin/includes/admin-ajax.php) so it ends with the following:

This is actually in src/wp-admin/includes/ajax-actions.php ๐Ÿ˜‰

#16 in reply to: โ†‘ย 13 @afragen
7 days ago

Replying to costdev:

Would a hook be a viable option here? As long as there hasn't been a page refresh the plugin's code hasn't run, so any functions defining an onboarding/configuration URL would not be available yet, at least from what I can tell.

Yeah it works because activate_plugin() calls plugin_sandbox_scrape() which loads the main plugin file, which is where I would imagine we'd advise plugin authors to put it. It's a configuration thing, so I wouldn't recommend someone puts it behind an init hook. Options/Transients should already be available if they want to base their URL on the value of one.


For fellow "lemme try" people:

  1. Enable WP_DEBUG and WP_DEBUG_LOG.
  2. Go to Plugins > Add New and install WooCommerce. Do not activate it yet
  3. Modify woocommerce/woocommerce.php to add this after the ABSPATH bail:
    add_filter(
            plugin_basename( __FILE__ ) . '_configuration_url',
            function () {
                    return admin_url( 'admin.php?page=wc-admin' );
            }
    );
    
  4. Modify wp_ajax_activate_plugin() (in src/wp-admin/includes/admin-ajax.php) so it ends with the following:
    // Add these two lines above the call to wp_send_json_success().
    $configuration_url = apply_filters( $status['plugin'] . '_configuration_url', '' );
    error_log( $configuration_url );
    
    wp_send_json_success( $status );
    
  5. Activate WooCommerce and check wp-content/debug.log.

debug.log output from above

[26-Apr-2024 17:45:35 UTC] http://xxxx.test/wp-admin/admin.php?page=wc-admin

#17 follow-up: @annezazu
40 hours ago

I can't speak to the technical aspects of this work but, thinking ahead to phase 3 and the admin redesign, I'm curious what can be done to build this/present this in a future proof way with the new efforts in mind. It could offer a great stress test with what's being thought of currently. Here's the broader overview issue on the admin redesign for context: โ€‹https://github.com/WordPress/gutenberg/issues/53322

#18 follow-up: @jason_the_adams
38 hours ago

It seems like the question as to whether pressing "Activate" should load an onboarding experience keeps coming up. I feel like we're trying to find a one-size-fits-all solution as our answer to this question โ€” as we consider things like WP-CLI, remote installation, bulk activation, and so forth. I think that's a mistake.

Consider this one scenario:

  1. I download GiveWP
  2. I install GiveWP
  3. I click "Activate" for GiveWP
  4. I'm redirected to onboard GiveWP

That's how it's worked for years (and for many other plugins), and I've never heard of a user describe this as confusing behavior. I think it's a mistake to mess up this UX in the name of it having technical difficulties (e.g. it's done by hijacking the redirect).

That's why I'm a fan of this form registration flow. Depending on the scenario, WP can provide the best UX for the user. Something like:

  • Activated one plugin: Redirect them
  • Activated many plugins: Display an admin notice
  • Activated via WP-CLI: Nothing? Perhaps show the URL to finish configuration at
  • Activated remotely: Return the URL

One other scenario we may want to consider here is perhaps giving the plugin the ability to prompt whether onboarding is necessary. If a user activates, completes the onboarding, deactivates, and then activates again, it's not necessary for them to onboard. Perhaps this is implicitly accomplished by not providing an onboarding URL unless it's necessary?

#19 in reply to: โ†‘ย 17 @jason_the_adams
38 hours ago

Replying to annezazu:

I can't speak to the technical aspects of this work but, thinking ahead to phase 3 and the admin redesign, I'm curious what can be done to build this/present this in a future proof way with the new efforts in mind. It could offer a great stress test with what's being thought of currently. Here's the broader overview issue on the admin redesign for context: โ€‹https://github.com/WordPress/gutenberg/issues/53322

If we get this configuration right, I'm hopeful it will better set plugins up for Phase 3, as we'll at least have a formal way for the new design to identify whether a plugin has an onboarding UI and where the user ultimately needs to go to complete it.

#20 @costdev
33 hours ago

Activated one plugin: Redirect them
Activated many plugins: Display an admin notice
Activated via WP-CLI: Nothing? Perhaps show the URL to finish configuration at
Activated remotely: Return the URL

One issue is that on Plugins > Add New, there was no way to allow a user to activate multiple plugins if a redirect occurred. Differentiating "one plugin" from "many plugins" on Plugins > Add New requires preventing the redirect takeover.

Note that by "multiple plugins", I refer to the following two scenarios:

  1. Clicking the Activate button in multiple plugin cards.
  2. Clicking Activate within the modals for each of a plugin's dependencies, then the Activate button in the dependent plugin's card.

I've seen in some places that there's a belief that users don't install multiple plugins from this screen (I'm not attributing this to you though), which is not quite correct. It's common for a user to have installed an addon for say, WooCommerce, then activate it, only to receive a notice to go back to Plugins > Add New to install and activate WooCommerce. This is one of the scenarios that the Plugin Dependencies feature targeted, and so the concept of installing/activating multiple plugins from this screen, while not new, is more apparent now.

The previous flow as detailed above was both frustrating and confusing to users (I've witnessed this a lot with clients and received emails asking for clarification). Even though things are different now without the redirect, I'm confident that we're all going to produce a more balanced result that will cover more use cases in a way that's straightforward for users.

Regarding WP-CLI based installation/activation: This may be done as part of a one-click setup where the user can select a list of plugins. These can also often be installed and activated on existing site, depending on the tool used, and can use WP-CLI. I think if a configuration URL is provided, we should consider how we might serve this information to users who haven't yet loaded the WordPress admin since activation. This may be a single admin notice on Plugins > Installed plugins, or something else. This would likely need to some further thought and discussion, but should be kept in mind as we look at the various activation methods.

#21 @costdev
33 hours ago

@annezazu I think that at the moment, the technical details amount to a filter for plugin authors (and either at the same time or later, theme authors) to provide a configuration URL. In the current UI, replacing the Active button in plugin cards and adding a Configure link in plugin rows is consistent with existing patterns in these areas of the WordPress admin.

From what I've seen of the admin redesign project so far, I would imagine a configure button would be provided for plugins and themes in the new UI, which would use the same configuration URL provided by such a filter. So from a "build this in a futureproof way" perspective, I think we've got that same mindset.

From a "display this in a futureproof way" perspective, I think we're going to inevitably have some big differences in how things are displayed between the current UI and the redesign. I haven't seen any early mockups of how the plugin and theme screens would display in the new admin. I think I'd need to see a general layout for these screens to theorise further on this, but my intention with this work would be to follow existing patterns so that when the redesign transitions existing patterns to new ones, the work done here would be transitioned in the same way.

#22 in reply to: โ†‘ย 18 ; follow-up: @kevinwhoffman
28 hours ago

Replying to jason_the_adams:

It seems like the question as to whether pressing "Activate" should load an onboarding experience keeps coming up. I feel like we're trying to find a one-size-fits-all solution as our answer to this question โ€” as we consider things like WP-CLI, remote installation, bulk activation, and so forth. I think that's a mistake.

Consider this one scenario:

  1. I download GiveWP
  2. I install GiveWP
  3. I click "Activate" for GiveWP
  4. I'm redirected to onboard GiveWP

That's how it's worked for years (and for many other plugins), and I've never heard of a user describe this as confusing behavior. I think it's a mistake to mess up this UX in the name of it having technical difficulties (e.g. it's done by hijacking the redirect).

Yes, the redirect method has been used for years, but it doesn't mean it's right. Having prototyped the original GiveWP onboarding wizard, I think the redirect method was a mistake. At the time, we were following the lead of large plugins like WooCommerce and Yoast. In doing so, we perpetuated the unpredictability of the "Activate" button.

Now when a new user installs a plugin, they have no idea whether the "Activate" button will simply activate the plugin or redirect them to an entirely different page.

Consider this scenario, which is the default behavior for a WordPress plugin:

  1. I download ACF
  2. I install ACF
  3. I click "Activate" for ACF
  4. ACF is simply activated like the button suggests, and nothing more

That's different behavior compared to GiveWP, but how would you know what to expect?

Imagine if clicking "Get" in the App Store caused some apps to open immediately, but there's no way of telling which apps will do that until you try them. That's what the redirect experience is like for new users of each WordPress plugin.

With the changes to AJAX plugin activations, the redirect method creates even more unpredictability. Now if I click "Activate" and then try to go anywhere else in WP Admin, I'm going to be redirected to that plugin's onboarding experience regardless of whether I'm trying to view my Posts, Pages, Tools, Settings, etc.

The proposed filter and "Configure" link would restore some consistency to the plugin activation experience while still giving plugins with first-time onboarding experiences a clear method of directing users to their preferred next step. We could even consider making the "Configure" text filterable by plugin developers so the button can say "Start Onboarding," "Continue Onboarding", etc. based on the configuration that's been done so far. That's the type of clarity and control that I hope this framework can offer to developers and users alike.

#23 in reply to: โ†‘ย 22 @alanfuller
25 hours ago

Replying to kevinwhoffman:

Imagine if clicking "Get" in the App Store caused some apps to open immediately, but there's no way of telling which apps will do that until you try them. That's what the redirect experience is like for new users of each WordPress plugin.

The App Store analogy is a relevant one, as the vast number of users are accustomed to it. However, App Stores only have two steps: Install and Open. Opening the app includes onboarding in most cases.

Additionally, App stores don't support multi-dependency installs.

So, if the objective is to redesign for the most user-friendly experience (ignoring technical limitations at this stage), in my opinion, for a plugin with no dependencies, on the ADD page, there should be a two-step process: Install and Open. Opening technically activates and runs the plugin, including any onboarding. For plugins with dependencies, the flow should be Install, notify users of dependencies, and give them an opportunity to install. When all dependencies are met, the plugin should Open, running a plugin configured within the dependency setup to be the master, with whatever onboarding is defined in the master plugin.

Now, my second point: This is just my opinion on what users want. In a commercial world, we would gather user requirements through various methods beyond those that participate in trac discussions. (But I do assume App Stores have rather worked out the simple use case.)

Last edited 25 hours ago by alanfuller (previous) (diff)
Note: See TracTickets for help on using tickets.