In the final part of my six-part series on improving User Experience (UX) in a WordPress product launch, we will finish building a GPL-licensed WP Welcome Page boilerplate. You’ll be able to use it for any of your WordPress products.
We have already built the base and the initializer files for our boilerplate. Now we will discuss the code for logic and look at the files that will safely redirect users to the welcome page at the backend and the welcome page itself respectively.
Defining The Plugin Logic
Having defined the set_transient() and delete_transient() functions in the initializer file, we can build the logic for the safe redirect as well as for the welcome page view. To manage the plugin logic, I created a separate file named welcome-logic.php which contains the following code:
<?php /** * Welcome Logic * * Welcome code related logic. * * @since 1.0.0 * @package WPW */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } // Safe Welcome Page Redirect. if ( ! function_exists( 'wpw_safe_welcome_redirect' ) ) { // Add to `admin_init`. add_action( 'admin_init', 'wpw_safe_welcome_redirect' ); /** * Safe Welcome Page Redirect. * * Safe welcome page redirect which happens only * once and if the site is not a network or MU. * * @since 1.0.0 */ function wpw_safe_welcome_redirect() { // Bail if no activation redirect transient is present. (if ! true). if ( ! get_transient( '_welcome_redirect_wpw' ) ) { return; } // Delete the redirect transient. delete_transient( '_welcome_redirect_wpw' ); // Bail if activating from network or bulk sites. if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) { return; } // Redirects to Welcome Page. // Redirects to `your-domain.com/wp-admin/plugin.php?page=wpw_welcome_page`. wp_safe_redirect( add_query_arg( array( 'page' => 'wpw_welcome_page' ), admin_url( 'plugins.php' ) ) ); } } // Welcome Page Sub menu. if ( ! function_exists( 'wpw_welcome_page' ) ) { // Add to `admin_menu`. add_action('admin_menu', 'wpw_welcome_page'); /** * Welcome Page Sub menu. * * Add the welcome page inside plugins menu. * * @since 1.0.0 */ function wpw_welcome_page() { // Add a global varaible to save the sub menu. global $wpw_sub_menu; // Sub menu itself. $wpw_sub_menu = add_submenu_page( 'plugins.php', // The slug name for the parent menu (or the file name of a standard WordPress admin page). __( 'Welcome Page', 'WPW' ), // The text to be displayed in the title tags of the page when the menu is selected. __( 'Welcome Page', 'WPW' ), // The text to be used for the menu. 'read', // The capability required for this menu to be displayed to the user. 'wpw_welcome_page', // The slug name to refer to this menu by (should be unique for this menu). 'wpw_welcome_page_content', // The function to be called to output the content for this page. ); } } // Welcome Page View. if ( ! function_exists( 'wpw_welcome_page_content' ) ) { /** * Welcome Page View. * * Welcome page content i.e. HTML/CSS/PHP. * * @since 1.0.0 */ function wpw_welcome_page_content() { // Welcome Page. if (file_exists( WPW_DIR . '/welcome/welcome-view.php') ) { require_once( WPW_DIR . '/welcome/welcome-view.php' ); } } } // CSS for Welcome Page. if ( ! function_exists( 'wpw_styles' ) ) { // Enqueue the styles. add_action( 'admin_enqueue_scripts', 'wpw_styles' ); /** * Enqueue Styles. * * @param int $hook Hook suffix for the current admin page. * @since 1.0.0 */ function wpw_styles( $hook ) { // Access the global varaible with saved sub menu. global $wpw_sub_menu; // Add style to the welcome page only. if ( $hook != $wpw_sub_menu ) { return; } // Welcome page styles. wp_enqueue_style( 'wpw_style', WPW_URL . '/welcome/css/style.css', array(), WPW_VERSION, 'all' ); } }
Code Explanation
Though the code is documented, we will also take a walk through it. The file starts with the docblock comment and is followed by the ABSPATH check to abort the plugin operation if this file is accessed outside the scope of WordPress.
To fulfill the requirements of a safe redirect of the welcome page, we need a custom function hooked at the admin_init action, which ensures that the function will run correctly when the admin area gets initialized. So, at line 16-52 I created a function called wpw_safe_welcome_redirect(). Since we need to create complex conditionals, it’s always better to create “guard clauses.” Guard clauses simply extract all conditionals that lead to calling an exception or immediate return of a value from the method and place it at the beginning of the method.
The first check tests the presence of our redirect transient. Here, you’ll find a function called get_transient(). It is yet another function which the Transients API in WordPress supports (the other two, set_transient() and delete_transient()), were discussed in the previous article. The purpose of get_transient() function is to retrieve a value stored against a particular transient, which takes up a single parameter which is the ‘key’ for transient.
Note: This is the same key which you used as a parameter inside set_transient() function in the previous article, i.e. I defined _welcome_redirect_wpw. Therefore, I’ve used the same to perform the check.
Now, if the value retrieved is not equal to true, we had set the value of our transient as true in the previous article, then a return which means that this function will stop its execution right here without return or doing anything.
If the transient has been deleted, the redirect function will not redirect the users to the welcome page.
However, if the retrieved value from the stored transient is true and the activation redirect transient is present then the function will execute further where it deletes the active transient so, that the redirect happens only once.
I also built another guard clause for this function to not redirect to the welcome page in case of the plugin being activated on a multisite WordPress network.
If the redirect transient was present and the plugin was not activated on a network, the function will execute forward and will perform a safe redirect where the user is redirected to the welcome page.
All these guard clauses help us redirect users to the welcome page once when they activate the plugin.
The wp_safe_redirect() function performs this task by telling the server about the exact $location of redirect. The add_query_arg() function helps to define the location. It comes in the form of a modified URL with query string. According to the codex, this is an associative array containing a key-value pair and the location URL.
The page slug in our case is wpw_welcome_page (will be defined later in this article). To define its location I used the admin_url() function. This function redirects users to your-domain.com/wp-admin/plugin.php?page=wpw_welcome_page.
So far, the process of a safe redirect is complete. But we need to have a WordPress admin page redirecting plugin users. To add a welcome page inside the Plugins Menu, I defined a custom function i.e. wpw_welcome_page() at line 54-79. It adds a submenu page with add_submenu_page() and we store the id of this page in a global variable to use for enqueueing the stylesheet (more on this later).
The add_submenu_page() Function
The add_submenu_page() is a built-in WordPress function which adds a page inside any menu like the ‘Plugins’. It takes a list of parameters i.e.
- $parent_slug
- $page_title
- $menu_title
- $capability
- $menu_slug
- $function
I’ve defined all the relevant parameters of this function at line 71-78. I also hooked the wpw_welcome_page() function to the admin_menu action in line 56-57.
So far, the basic structure of our welcome page is complete. When users activate the plugin, they will be redirected to an empty page. Now, we have to add the welcome page view.
As the last parameter of add_submenu_page function, I called back another function, which is going to be responsible for the view of our welcome page. This function is called wpw_welcome_page_content(), which includes the welcome page view file — i.e. welcome-view.php.
After that, from line 100-129, I have added a function which is responsible for enqueuing the stylesheet of our welcome page. Note: I wanted the stylesheet to be enqueued only on the welcome page that’s why I had created a global variable to store the ID of our submenu_page in the variable called $wpw_sub_menu. I am using a parameter $hook, which helps me compare the current admin page ID with the welcome page ID i.e. $wpw_sub_menu so that WP only enqueues the stylesheet at the welcome page with the help of a simple guard clause.
Welcome Page Contents
To handle the welcome page view, I created a file called welcome-view.php. This file is responsible for all the HTML/CSS code of the welcome page where we are redirecting our users. The code for this file looks like this:
<?php /** * Welcome Page View * * Welcome page content i.e. HTML/CSS/PHP. * * @since 1.0.0 * @package WPW */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } // Version. $the_version = WPW_VERSION; // Logo image. $logo_img = WPW_URL . '/welcome/img/logo.png'; ?> <!-- HTML Started! --> <div class="wrap about-wrap"> <h1><?php printf( __( 'WordPress Product %s' ), $the_version ); ?></h1> <div class="about-text"> <?php printf( __( "WordPress Product's welcome page boilerplate for WordPress plugins." ), $the_version ); ?> </div> <div class="wp-badge welcome__logo"></div> <div class="feature-section one-col"> <h2>Get Started</h2> <ul> <li><strong>Step #1:</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit.</li> <li><strong>Step #2:</strong> Cras sed sapien quam. Sed dapibus est id enim cilisis lig.</li> <li><strong>Step #3:</strong> tortor est congue ligula, eu adipiscing quam ligula ut purus.</li> </ul> </div> <div class="feature-section one-col"> <h2>What's Inside?</h2> <div class="headline-feature feature-video"> <div class='embed-container'> <iframe src='https://www.youtube.com/embed/3RLE_vWJ73c' frameborder='0' allowfullscreen></iframe> </div> </div> </div> <div class="feature-section two-col"> <div class="col"> <img src="http://placehold.it/600x180/0092F9/fff?text=WELCOME" /> <h3><?php _e( 'Some Feature' ); ?></h3> <p><?php _e( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed sapien quam. Sed dapibus est id enim facilisis, at posuere turpis adipiscing. Quisque sit amet dui dui.' ); ?></p> </div> <div class="col"> <img src="http://placehold.it/600x180/0092F9/fff?text=WELCOME" /> <h3><?php _e( 'Some Feature' ); ?></h3> <p><?php _e( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed sapien quam. Sed dapibus est id enim facilisis, at posuere turpis adipiscing. Quisque sit amet dui dui.' ); ?></p> </div> </div> <div class="feature-section two-col"> <div class="col"> <img src="http://placehold.it/600x180/0092F9/fff?text=WELCOME" /> <h3><?php _e( 'Some Feature' ); ?></h3> <p><?php _e( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed sapien quam. Sed dapibus est id enim facilisis, at posuere turpis adipiscing. Quisque sit amet dui dui.' ); ?></p> </div> <div class="col"> <img src="http://placehold.it/600x180/0092F9/fff?text=WELCOME" /> <h3><?php _e( 'Some Feature' ); ?></h3> <p><?php _e( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed sapien quam. Sed dapibus est id enim facilisis, at posuere turpis adipiscing. Quisque sit amet dui dui.' ); ?></p> </div> </div> </div> <!-- HTML Ended! -->
At line 1-20 you will find standard WP PHP docblock and an ABSPATH check, you can also define variables to be used inside the HTML.
Lines 22-78 contain all the contents, classes, assets, etc. I found a few classes that are being used by the WordPress core team to build a simple grid based column layout.
The layout of a welcome page which you can achieve with this code contains the following elements:
- The plugin name, its version, and logo
- A step-by-step getting started tutorial
- Video tutorial
- Plugin features in a two-columned layout
- Custom styles with the style.css file
WP Welcome Page Boilerplate – Testing
It is finally time to set up the page. To implement it, you will need to have the following setup:
- the WP-Welcome-Page-Boilerplate downloaded from GitHub
- a demo website with WordPress installed
- Welcome Page Boilerplate plugin installed and activated
Once you’ve activated the plugin, you’ll be redirected to the welcome page. From here you can view the complete layout of the welcome page in the screenshot below:
First of all, there is a brief introduction and logo of the plugin. Then you can find the getting started steps. Next is a video tutorial. It provides a more real-time view of how the plugin works. Finally, there is a section that lists the prominent features of the product. You can also add sections about contributors, new and upcoming features as well as the subscription form.
Let’s Conclude
This concludes the series on improving the user experience of your WordPress product. After implementing these steps myself, I had a larger number of users stick with my plugin. I hope it works for you as well.
Finally, you can catch all of my articles on my profile page, and you can follow me on my blog and/or reach out at Twitter @mrahmadawais; where I write about development workflows in the context of WordPress.
As usual, don’t hesitate to leave any questions or comments below, and I’ll aim to respond to each of them.
No Comments