Advertisement
  1. Code
  2. WordPress
Code

Build a Custom WordPress User Flow — Part 2: New User Registration

by
Difficulty:IntermediateLength:MediumLanguages:
This post is part of a series called Build a Custom WordPress User Flow.
Build a Custom WordPress User Flow — Part 1: Replace the Login Page
Build a Custom WordPress User Flow — Part 3: Password Reset

In the first tutorial in this series on customizing the WordPress login experience, we created a plugin that lets you replace your WordPress login screen with a custom page. Today, we will go a step further and replace the new user registration flow in the same way.

The reasons for customizing the login page we outlined in Part 1 (matching the registration page with your site's theme to hide WordPress and make the user experience seamless) apply also to new user registration, but there are also some more specific reasons for why you might want to create your own registration page:

  • First, at registration, you might want to change the fields you ask from your new members, adding extra fields or maybe dropping some. As an example, in this tutorial, we will remove the user name field and instead use the new user's email address as login.
  • Second, there is registration spam. When I first opened registrations to everyone on my site, it didn't take more than a few hours for the first spam registration to appear, the next one following right after it. Adding a reCAPTCHA field on a custom registration page is a good way to handle this while keeping the user experience consistent.
  • Finally, you might want to do some custom actions at registration, for example adding the new user to your mailing list. After having built your own registration flow, this will be easier than ever.

So, equipped with this set of reasons, let's get started. 

In this tutorial, you will learn how to replace the WordPress registration screen with a custom page and to implement the registration with your own code, without violating WordPress's design principles. 

The functionality will be built on top of the plugin we built in Part 1 of the tutorial series, so if you haven't read it yet, it's a good idea to start by checking out that tutorial. You can write the code yourself while following the tutorial, or download the example code from the tutorial's Github project.

Add a Custom New User Registration Page

The default WordPress new user registration page at wp-login.php?action=register looks like this:

WordPress new user registration screen

Not bad, but unless you're running WordPress.org, it's most likely not consistent with your blog or web site design. 

Note: If you can't access the registration page on your WordPress site, it's because by default WordPress doesn't allow new users to register themselves. To change this, go to the General Settings page in your admin Dashboard and check the checkbox before "Anyone can register". Then save the settings and return to the registration page.

Check this checkbox to enable new user registration in WordPress

In the first part in the series, we created a custom page for displaying the login form and a shortcode that was used to place the login form on that page. Now, we'll do the same for registration: first, we'll create a shortcode for displaying the registration form, and then a page on which this shortcode will be placed.

It's also possible to place the shortcode on a different page or have the login and registration forms on a single page.

Step 1: Create the Shortcode

Building on top of the plugin created in Part 1 of the series, let's start by adding a shortcode for the registration page.

At the end of the plugin class's (Personalize_Login_Plugin) constructor, add the following shortcode definition:

Then, create the function responsible for rendering the new user registration form:

If you have already read Part 1 in the series, you'll notice a lot of similarities between this function and the login form rendering function from that tutorial. 

First, on lines 10-12, you'll notice that the shortcode takes an attribute show_title, used for defining whether a title should be rendered by the shortcode or not.

Second, the registration form is not shown to users who are already logged in (lines 14-15). The message returned instead of the form is quite simple, so depending on your needs, you may want to replace this piece of code with something more elaborate — for example a link back to the dashboard. 

A new element is the check for the WordPress option users_can_register on line 16. This option is controlled by the WordPress General Settings field Anyone can register mentioned above. To make sure we respect the settings the user defines in WordPress, we should not display the registration form if the setting is set to false. Instead, as you see on line 17, the function will return a notification about registration being closed.

The actual rendering of the registration form is done on line 19 using a PHP template, register_form.php, located in the templates directory we created in the previous tutorial. See Part 1 for a longer explanation on how this works as well as the code for the function used, get_template_html.

Now, let's add the registration form template.

Step 2: Create the Registration Form

In the templates directory, add a new PHP file and name it register_form.php. Then, continue by adding a registration form with the fields you want your new user to fill.

Here's the version I created for this tutorial; a rather standard registration form with fields for the user's email, first name, and last name. The form doesn't contain a separate field for a user name as the email address will double as one.

Just like the default WordPress new user registration, our version will generate the password and email it to the new user. This serves as a simple email check (the user won't be able to log in without entering a valid email address) and enforces some level of password security. 

Of course, this approach has its own security risk in the form of emailing passwords, so it's a good idea to ask (or even require) the user to change the password once logged in.

On lines 2-4, the template renders a title for the form if the show_title attribute is set.

Then, on line 6, take a look at the action parameter: The form is submitted to the default WordPress registration URL which we can retrieve using the function wp_registration_url. We'll talk more about to this soon, but I'll mention already now that this doesn't mean that we'll let WordPress handle the registration...

The rest of the template is a rather standard HTML form with fields for email, first name, and last name.

Before we get to see the shortcode in action, we still need to create the registration page and place the shortcode on it.

Step 3: Create the New User Registration Page

To show the registration form, you'll need to add the following code on a WordPress page:

This could be any page, but for now, let's create a new page for the registration form.

In the previous part, we created a function, plugin_activated, for creating the plugin's pages at plugin activation. Inside the function, we added an array for storing all the pages the plugin should create. 

Now, let's add the information about the new page to the array. After the addition, the array definition should look like this, with the new page (with the slug member-register) defined last:

The activation hook is only run when a plugin is activated, so go ahead and deactivate and then activate the plugin on the Plugins page. Now, when you navigate to the URL http://<YOUR SITE>/member-register, you should see something like this (using the current WordPress default theme, Twenty Fifteen):

Custom new user registration form

Step 4: Redirect the User to Our New Registration Page

Before we move to executing the registration action, let's make sure the user always gets redirected to this new registration page instead of the default new user page at wp-login.php?action=register.

To do this, we'll use the action hook login_form_{action} which, as you might remember from Part 1, is fired before every action in wp-login.php. As you see from the link above, the action in this case is register, and so, we'll hook our function to login_form_register.

In the plugin's constructor, add the following line:

Then, create the callback function:

As we hooked the function to the login_form_register action, we know that the user is either trying to access the new user registration form or to post it.

That's why the first thing we do in this function (on line 6) is to check the request method that was used to access the page: the redirect is only done on GET requests as the POST request will be reserved for executing the registration action. More about this soon.

Then, the function continues by checking if the user is already logged in (line 7). 

Logged in users are redirected to the account page (or the admin dashboard if they are admins) using the function redirect_logged_in_user which we created in Part 1. Visitors are redirected to our new page, member-register.

Now, with the page and the form in place, let's move into what happens when the user submits the form.

Register a New User

When the user submits the new user registration form, its contents are posted to wp-login.php?action=register, the same URL we used when redirecting the user to the registration page above. 

To do the customizations we mentioned earlier (most importantly, using the email address as the user name) we will need to replace this functionality with our own code. To do this, we will first create a function for registering a new user programmatically and then  call this function in an action handler.

Step 1: Create the User

Let's start by creating a function that can be used to register a new user using the data collected from the form above: email address, first name, and last name. The email address will be the only unique identifier, and the rest is just something nice to have.

In the plugin class, add the following private function:

As I mentioned above, the email address is the only unique identifier, and also the only required parameter. That's why we begin the function by validating its value. First on line 15, we validate the email address and then, on line 20 we verify the email address isn't already in use. If either of the validations fail, a Wp_Error object is returned. We'll return to displaying these errors soon.

If all goes well and no errors are found, the function continues by generating a password on line 26.

On lines 28-37, you'll find the core of this function, the creation of the new user. The user is added using the WordPress function wp_insert_user. (line 37). As its only parameter, the function takes an associative array with information about the user being created. As you'll see on lines 28-35, we use $email for both the user name (user_login) and email (email) fields. For a full list of the fields that can be included in the attribute array, take a look at the WordPress codex.

After creating the user, on line 38, the function calls wp_new_user_notification to send the  generated password to the new user and to notify the site admin of the new user. 

Step 2: Call the Registration Code When a User Submits the Form

Now that we have written the code for registering the user, we can call it when the registration form is submitted.

Earlier, when we added the redirect to our custom registration page using the action login_form_register, I mentioned we'd use the same action also for handling the POST requests.

As is often the case in programming, this isn't the only way we could handle the new user registration, but it does have a rather important benefit: this way, we'll make sure no one can accidentally access the default registration code in WordPress.

For clarity, let's add a separate function and tie it to the same action (technically, there is no reason why you couldn't just as well add this code to the redirect function we created above). 

In the plugin class's constructor, add a new action definition:

Then, create the function:

The function begins with a request method check on line 8: the function is linked to the WordPress action login_form_register, the same that we used for redirecting the user, and the request method is what differentiates the two uses from each other.

On line 11, we verify that registering new users is allowed. If not, the user is redirected back to the registration page with an error code (closed) as query parameter (register-errors).

On the other hand, if registration is open, the function collects the required parameters (lines 15-17) from the request data and uses them to call the function we created above (line 19) to create the new user.

After the register_user call, the function redirects the user to the correct place depending on whether the new user registration was successful or not: 

  • After a successful redirect, the user is redirected to the login page, with the parameter $registered indicating that a new user was just created. 
  • In case of an error, the redirect points back to the registration form with the error codes from the new user registration function are combined into a comma separated list and included in the request (lines 23-24).

Step 3: Display Error and Success Messages

As we saw above, the registration function redirects the user to the login page if registration was successful and back to the registration page if there were errors, with the status passed as request parameter.

Now, let's add some code to display those messages to the user, starting with the error messages on the new user registration page.

In render_register_form, add the following piece of code right before rendering the template:

This snippet first checks if errors were passed in the request parameter register-errors (line 2). If yes, it goes through all of them, looking up corresponding error messages using the get_error_message function we created in Part 1 of the tutorial series. 

The error messages are collected into an array in the $attributes array for printing in the template.

To be able to show the correct error messages, we'll also need to add the new error messages to the function get_error_message. In the switch structure, add these (or your own) error messages:

To display the errors on the registration page, add the following code in the register_form.php template in between the title and the form:

Next, let's add the success message.

When a new user has been successfully registered, the user is redirected to the Sign In page, with a parameter, registered={email address} appended to the URL. 

In the function render_login_form, add the following two lines to check if the parameter is present:

Then, in the template login_form.php, add a message that will be shown if the registered flag is set:

That's it. You have now built a complete new user registration flow with parameter validation and error reporting. 

Go ahead an create a new user account to test the flow.

Sign In page shows a success message

If you are testing the plugin on a local server, unless you have configured the emailer settings, you might not receive the email containing the password — that's normal.

Fight Registration Spam with Google's ReCaptcha

While the registration form is now complete, we'll keep customizing it a bit more by adding a reCAPTCHA check (it's the "I'm not a robot" checkbox you'll find on many of the bigger sites online) to prevent registration spammers from creating accounts on your web site.

Step 1: Get Your Captcha Key

First, visit the reCAPTCHA site. Click on the "Get reCAPTCHA" button on the top right corner to access the reCAPTCHA admin page.

Google reCAPTCHA web site

If you are not signed in to your Google Account, you'll be asked to sign in. If you don't have one yet, you'll need to create one to use this tool. 

On the reCAPTCHA account page, you'll find the following form. Use it to insert information about your web site. 

Registering a new site for reCAPTCHA

Once you have submitted the form by clicking on Register, you will see a page with instructions on enabling reCAPTCHA on your site, as well as two keys used for using the API: Site Key and Secret Key.

To store the keys in our WordPress plugin, we'll need to create two settings fields. To keep things simple, we'll add them to the General Settings and not create a custom settings page yet.

To add the settings fields, first hook a new action. In the plugin's constructor, add the following new line:

Then create the function for defining the settings fields and the two callback functions for rendering the settings fields:

As this tutorial is not about WordPress Settings API, we won't go through the settings field declaration. If you are not familiar with how adding settings in WordPress works, check out this complete tutorial series by Tom McFarlin.

Now, go to the General Settings page and copy the reCAPTCHA keys to the two fields you just created and save the settings.

Settings for reCAPTCHA

Step 2: Display the CAPTCHA

With the preparations done, we can now add the reCAPTCHA field and use it to verify that our users are human.

In render_registration_form, first retrieve the reCAPTCHA site key from WordPress settings and store it in the $attributes array to make it available in the template:

Then, using the parameter, add a placeholder for the  reCAPTCHA field in the registration form, right above the submit button:

The actual reCAPTCHA field will be placed inside the div above using JavaScript. So, in order to show the field, we'll still need to include the JavaScript in the page footer.

WordPress has a specific action just for this use. Add the following line in the plugin's constructor: 

Then, create the function, add_captcha_js_to_footer that prints out the JavaScript include tag that loads the reCAPTCHA API from Google:

Now, when you go to the registration page, you should see the reCAPTCHA field in place:

The reCAPTCHA field in action

Step 3: Check the CAPTCHA

If the JavaScript based "not a robot" check is successful, the reCAPTCHA widget adds a new parameter to the form, g-recaptcha-response. Then, in the server side validations in the do_register_user function, we can use the parameter to check that the user has passed the test.

First, let's create a function for checking the reCAPTCHA parameter:

On lines 9-13, the function retrieves the reCAPTCHA response. If it isn't found, the user hasn't even tried to complete the test before submitting the form.

Then, on lines 16-24, the function uses wp_remote_post to send a POST request to the reCAPTCHA server to verify the received response. The request takes two parameters, embedded in an array with the id body: the reCAPTCHA secret key and the response we are validating, read from the request parameter g-recaptcha-response.

The server returns its response as a JSON encoded object. Once the response is decoded, it can be used to check the response as we do on line 29.

Next, let's use the function in handle_register_request to make the reCAPTCHA check a part of the parameter validation. For clarity, here's the entire if...else construct with the new code appended in the middle (lines 4-6):

If the reCAPTCHA check fails, the user is sent back to the registration page with the error code captcha included in the URL. 

To display the error to the user, add a matching error message in the get_error_message function. Something like this, maybe:

And that's it. You have added a reCAPTCHA check to your new user registration flow.

What's Next?

You have now successfully customized your WordPress based site's new user registration flow. If you have more ideas on things you'd like to differently at this step, this is a good time to extend the changes we did in this tutorial. Add new fields, do more validation, add the user to a mailing list. You name it.

In the next, and final, tutorial in this series, we will complete the customization by replacing the "Forgot your password" functionality with our own custom pages.

Until then, happy coding.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.