When you install our Yoast SEO plugin onto your WordPress site, there are some basic things that you have to set up for your site to rank. Normally you have to go to the settings of the plugin and set everything up yourself. There are a lot of settings in our plugin, and they're not all easy to understand. Sometimes it is hard to find out what they are for and how important it is for your site. To make it easier to get going, we have developed an onboarding wizard.
We try to develop our plugins in such a way that we set good defaults for every setting. But some settings are dependent on what you use the site for or on the preferences of the user. So to have the plugins configured well, we need input from our users. We want every user to have their plugin set up in the best possible way, even users who don’t know a lot about SEO.
Answer simple questions
The onboarding wizard makes it possible to set up the plugin by answering a few relatively simple questions. These are, for example, questions about whether your site is personal or professional, what the name of the end user is and on what kind of environment your site is running. By answering these questions, the plugin makes sure all settings are in line with the user’s preferences.
This way users do not need to know what every setting means in the Yoast SEO plugin configuration settings. Besides that, the user can now set up their site at once by just finishing the wizard.
How we put the wizard together
For the realization of our configuration wizard, we looked at several libraries for creating a wizard. There were a couple of libraries that could work well, but at Yoast, we think it is important that everyone can use our plugins, even visually impaired people. Accessibility was the part where the libraries did not meet our standards. We wanted our onboarding wizard to be at least keyboard accessible, so people who use screen readers can also use our wizard.
The only way we could meet our goal was to develop our own library. We wanted to use the wizard for our WordPress SEO plugin, but the onboarding wizard had to be generic and reusable for other software projects. This way we can use it to configure SEO plugins for other platforms as well.
Developing the wizard in React
Once we had made a choice for the techniques we were going to use, we began to think about how the wizard should behave and what we needed to build. We also thought about what components we should have, how we should build them and how we’d like them to behave. For this we came up with the following concepts:
- A Wizard can have one or more steps.
- A Wizard has a “previous” and “continue” button to allow users to traverse through the steps.
- A Step has the following attributes:
- id, string, identifier
- title, string, the title of the step.
- fields, array, list of strings referencing fields by key.
- A field has the following attributes:
- component, string, references the component that should be used to render the field in the component tree.
- properties, object, contains all the metadata needed to render the component and configure its behavior.
- data, mixed, the value of the field.
We began developing a Wizard component with a next and a previous button. When pressing one of the navigation buttons the content would display the title of the next step. With this, we got a bit familiar with React and how it works.
The funny thing is that, once you master the basic principles, React isn’t all that difficult. The difficulty at first is that you have to understand how the state of a React component works and how you can use properties for React components. Once you understand this, React is fairly easy to use and understand.
Basic React components work in the following way: every time the state updates, the component is re-rendered. You can trigger change the state for example based on onClick events. The properties in React components are used to set the initial state for the components.
At first, we’ve created a Step component which state gets updated to a next step. The step then renders the fields for the next step. Then we got to building the different components that we wanted to use for the wizard. We built the basic components like input fields, labels, and buttons first.
After that, we made composed components that use these basic level components. These are, for example, text input fields, which consist of a label and an input field. Another example is the Choice field, which is a group of radio buttons with a description.
We’ve also created conditional fields; these fields show in a step when another field has a certain value. We did this to provide extra information for the end user that is only relevant when a particular option is selected.
To make it possible to add new components to the wizard, we implemented custom components. These components can be added and injected when instantiating the Wizard. We developed this for times when normal form fields are not sufficient. The custom components make it possible to create a component with its own behavior, that the wizard can render in a step. This can be anything, as long as it’s an element that React can render. We have used this to add WordPress specific components.
Issues we had to solve
During the development, we came across some issues with React.
Jest was nice to use and provides a lot of useful tools. For example, classes and functions that are used by a class are automatically mocked. That way other components cannot influence the tests for that component.
We developed tests for our lower level components, but testing became harder with the higher level components. Those use a lot of different components and later on we also used some components from a React UI framework called Material-UI. Those components, for example, use onClick events for changing the state and have a lot of properties and different situations for how the component should behave.
We wanted a framework that could help us make the testing of those components quicker. By default, Jest mocks everything except the component you are testing, but sometimes a component depends on some other module to be available. We ran into some mocking problems with Material-UI components. A test would depend on some low-level Material-UI component, and we had to manually debug which component we had to unmock for our component to work in the tests.
For helping us testing the higher level components, we found a framework called Enzyme. This framework provides a more intuitive way to test those higher level components. With this framework, we could render components and for example find buttons and simulate onClick events on them by just calling a simulate function on the button. When we were just using Jest we had to do some more actions to simulate the onClick events.
A bug in React?!
While we were developing the input components for our onboarding wizard, we came across a weird bug. This bug was about remembering the values for radio button input fields between the steps. When you selected a radio button and switched to the next step and selected a radio button over there, the radio button for the first step was not correctly set anymore.
To solve this issue, we dove into the code and debugged the wizard with the built-in debugger from Google Chrome. After some fiddling around we came to the conclusion that React re-used DOM-elements. The input fields are not actually removed, but the values for the existing input fields updated.
The radios in React 15.3.1 are updated in the DOM by first updating the attributes (name, id, etc) and then updating whether they are checked or not. So when going from a list where the third radio is checked to a list where the second is one, the following happens:
- The first radio is updated, nothing of note happens.
- The second radio is updated, now the second and the third radio are both checked, but they have different names.
- The third radio updates, in updating the attributes the browser detects that there is already a radio with the same name and unchecks that one, the second radio button. Then the third radio is unchecked because the React state has the radio as unchecked. Now no radios are checked.
- The fourth radio is updated, nothing of note happens.
The bug only appeared in React version 15.3.1, and it was not present in React 15.3.0. You can read the full description here. We reported the issue and switched to React version 15.3.0 for the time being.
Designing the user experience
After we had learned React and Jest, we began thinking about what the components for the wizard should look like. We wanted to provide an easy-to-use interface to the end user, one that would be recognizable as a Yoast product.
For inspiration, we looked at some other installation wizards. Besides the components we already realized, we wanted to have a stepper component. A stepper shows the amount of steps that a user has to go through in the wizard to complete it. You can also track your current progress through these steps. The React framework Material-UI had a stepper built in. At first, we did not want to use this framework because of its poor accessibility support. But because we did not want to re-invent the wheel we used their horizontal async stepper component and modified it.
We added tooltips to the stepper buttons to provide information about the next step, without the need to always display the description for the step.
We also made the stepper responsive to make it work on smaller screens. For this, we removed the current step description in the stepper. We also chose to only display the first, last and current step in the process. This saved a lot of space, but the stepper still provides useful information about the progress for the user.
The buttons from Material-UI look a lot cooler than standard buttons, and they do not have a bad influence on the accessibility. After that, we gave everything a nice purple color to add the Yoast look and feel.
Yoast SEO wizard
The wizard ships with our new Yoast SEO 3.6 release for WordPress. So if you want to see how it looks and behaves, you can find it in the general tab, or if you’re a new user, you’ll receive a notification from us about the configuration wizard. In a follow-up tutorial, we’ll show you how to build your own onboarding wizard with our open source library.