Welcome to Part five in my series on User Experience (UX) best practices in a product launch. In the previous article, I talked about the importance of including a welcome page in your plugin. Today I’ll explain how to build that welcome page with a GPL licensed boilerplate that can be used on any WordPress product.
Welcome Page Boilerplate For Your WordPress Product
I created a WP Welcome Page Boilerplate to simplify the process of adding a welcome page.
The boilerplate is currently available as a WordPress plugin. You can download the latest release version here and install it on your WordPress site to test it. Every step is documented in the code, so even a WordPress beginner can test it out.
WP Welcome Page Boilerplate
WP Welcome Page Boilerplate uses WordPress transients API to ensure the redirection when a WordPress plugin is activated. It has a built in welcome page that includes dummy content and takes care of adding and deleting the transients with safe redirects. It works like this:
- When the plugin is activated, a transient gets added.
- When the plugin is deactivated, the same transient gets deleted.
- Upon activation, the user receives a one-time safe redirect to the welcome page of inside our WP plugin.
Architecture
If you download the zipped plugin from GitHub and extract its content, you’ll find the root folder named WP-Welcome-Page-Boilerplate. It contains the standard plugin file wp-welcome-page-boilerplate.php, a folder named welcome. The architecture of this boilerplate looks like this:
- Root Folder: WP-Welcome-Page-Boilerplate
- File: WP-Welcome-Page-Boilerplate/wp-welcome-page-boilerplate.php is the file responsible for introducing the welcome page initializer as well as the definition of a few global constants. You should change these global constants to match your plugin’s package and path to the right folder.
- Folder: WP-Welcome-Page-Boilerplate/welcome is the folder that holds all the related files for our welcome page.
- File: WP-Welcome-Page-Boilerplate/welcome/welcome-init.php is the welcome page initializer. This takes care of adding and deleting transients on plugin activation and deactivation and includes the welcome-logic.php file.
- File: WP-Welcome-Page-Boilerplate/welcome/welcome-logic.php is the file responsible for adding all the logic related to our welcome page, which takes care of redirecting the user on first activation, adding a submenu and including the welcome page view file as well as enqueueing the style sheet.
- File: WP-Welcome-Page-Boilerplate/welcome/welcome-view.php is the file responsible for the view of our welcome page, 90% of this file is based on dummy HTML and CSS.
NOTE: Make sure you change the wpw_ prefix/sufix and WPW package name to the name of your plugin when you use this boilerplate in production.
Here is an image.
Let’s study the contents of the main plugin file in the root folder.
Base File Of The WP Welcome Page Boilerplate
The wp-welcome-page-boilerplate.php file is the standard base plugin file, containing the following code:
<?php /** * Plugin Name: WP Welcome Page Boilerplate * Plugin URI: http://AhmadAwais.com/ * Description: Welcome page boilerplate for WordPress plugins. * Author: mrahmadawais, WPTie * Author URI: http://AhmadAwais.com/ * Version: 1.0.1 * License: GPL2+ * License URI: http://www.gnu.org/licenses/gpl-2.0.txt * GitHub Plugin URI: https://github.com/WPTie/WP-Welcome-Page-Boilerplate * GitHub Branch: master * * @package WPW */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Define global constants. * * @since 1.0.0 */ // Plugin Version. if ( ! defined( 'WPW_VERSION' ) ) { define( 'WPW_VERSION', '1.0.1' ); } // Plugin Folder Name. if ( ! defined( 'WPW_NAME' ) ) { define( 'WPW_NAME', trim( dirname( plugin_basename( __FILE__ ) ), '/' ) ); } // Plugin Dir including the folder. if ( ! defined('WPW_DIR' ) ) { define( 'WPW_DIR', WP_PLUGIN_DIR . '/' . WPW_NAME ); } // Plugin URL including the folder. if ( ! defined('WPW_URL' ) ) { define( 'WPW_URL', WP_PLUGIN_URL . '/' . WPW_NAME ); } // Plugin Root File. if ( ! defined( 'WPW_PLUGIN_FILE' ) ) { define( 'WPW_PLUGIN_FILE', __FILE__ ); } /** * Welcome file. * * @since 1.0.0 */ if ( file_exists( WPW_DIR . '/welcome/welcome-init.php' ) ) { require_once( WPW_DIR . '/welcome/welcome-init.php' ); }
The Code
The first few lines (1-15) describe the standard meta information that establishes the presence of a WordPress plugin or plugin header. This will be familiar to anyone who has developed a plugin before.
Next, you’ll find an ABSPATH security check in lines 17-20. Its purpose is to abort the plugin process for any unauthorized access to the file.
From line 23-51, I’ve created a few global constants such as WPW_VERSION, WPW_NAME, WPW_URL, and so on. You can read more about these from the WordPress codex. You should change them to reflect that name of your plugin (which is WPW for this boilerplate). Make sure you keep the paths intact since these paths are being used inside the plugin to enqueue stylesheets and to implement the plugin activation and deactivation hooks (which need the path to plugin main file).
If you closely review this code the global constants have one thing common — an if ( ! defined )check is performed. By doing so, you’re saving yourself from a predefined global variable. The purpose of creating separate files is to keep the code clean. That’s why I required the welcome-init.php file in lines 54-61. If you are using the boilerplate, you will only need to include the welcome folder.
To play it safe, I recommend using the file_exists() function to check if the file you are including does in fact exist.
The Welcome Page Init File
I’ve created an initializer file (welcome-init.php) which initializes the welcome page. It adds and deletes a transient and requires the welcome-logic.php file. Let’s take a look at its code:
<?php /** * Welcome Page Init * * Welcome page initializer. * * @since 1.0.0 * @package WPW */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } // Add the transient on plugin activation. if ( ! function_exists( 'wpw_welcome_page' ) ) { // Hook that runs on plugin activation. register_activation_hook( WPW_PLUGIN_FILE, 'wpw_welcome_activate' ); /** * Add the transient. * * Add the welcome page transient. * * @since 1.0.0 */ function wpw_welcome_activate() { // Transient max age is 60 seconds. set_transient( '_welcome_redirect_wpw', true, 60 ); } } // Delete the Transient on plugin deactivation. if ( ! function_exists( 'wpw_welcome_page' ) ) { // Hook that runs on plugin deactivation. register_deactivation_hook( WPW_PLUGIN_FILE, 'wpw_welcome_deactivate' ); /** * Delete the Transient on plugin deactivation. * * Delete the welcome page transient. * * @since 2.0.0 */ function wpw_welcome_deactivate() { delete_transient( '_welcome_redirect_wpw' ); } } /** * Welcome Logic. * * @since 1.0.0 */ if ( file_exists( WPW_DIR . '/welcome/welcome-logic.php' ) ) { require_once( WPW_DIR . '/welcome/welcome-logic.php' ); }
After the doc block in the header, the code begins with an ABSPATH check (line 11-14). It performs the same function as it did in the base file. Next, write the code that adds a transient upon plugin activation and deletes it on deactivation. It can be down with two functions as follows:
Creating a Transient
The set_transient( $transient, $value, $expiration ) function creates or updates any transients. It takes three parameters of which the first two are compulsory and in the form of a key-value pair. The last parameter is optional and defines the time after which the transient expires. For the purpose of creating a welcome page redirect we need to have a particular transient stored in the database — the logic function that redirects a user to the welcome page will check if a certain transient _welcome_redirect_wpw exists and will redirect the user to the welcome page.
Deleting a Transient
The delete_transient( $transient ) function removes a transient. It takes a single parameter which is the key for the transient you want to delete. I will use this function to delete the transient we created.
Now that you are familiar with these functions, understanding the code will be much easier.
Code Explanation
At line 16-32, I created a transient for the welcome page via the set_transient() function. I called it inside the custom wpw_welcome_activate() function. In this case:
- The Key/Transient is: _welcome_redirect_wpw (You can define any custom key)
- The Value is set to: true
- The Expiration time is: 60 seconds
This means the value of _welcome_redirect_wpw is set to true for 60 seconds, after which the transient should expire.
I hooked this function to register_activation_hook() which is the hook that runs on plugin activation. So, now this function will run only on the plugin activation. Make sure the first parameter for this hook is the filename of your main plugin file. I defined it as a global constant.
Line 35-50 handles the plugin functionality upon its deactivation. Therefore, the delete_transient() function is defined which takes the same transient _welcome_redirect_wpw as its parameter and deletes it. It’s an optional step to ensure that when our plugin is deactivated, we don’t leave traces of any data in the database.
This is all done inside the wpw_welcome_deactivate() function which has been exclusively defined to handle plugin deactivation process.
The same function is also added to the plugin deactivation hook (i.e. register_deactivation_hook()) which deletes a transient when the plugin is deactivated and if for some reason the transient is still present.
Now we must redirect to the welcome page and the welcome page view. This will be done via a separate file. The same file is included at the end of this initializer.
Conclusion
In this article, we started to build our Welcome Page Boilerplate. In the next article, we will build a welcome page at the backend for better user-onboarding experience.
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