Making prototyping easier

Making user journeys configurable in the GOV prototype kit

I’m a massive advocate of prototyping ideas and putting them in front of users. This helps us to learn how a service may be used and solving problems or identifying challenges early on.

Journey flow Photo by Alvaro Reyes on Unsplash

I’m a designer within a government organisation and I use a customised version of the GOV Prototype Kit (part of the GOV Design System) to design services for our organisation. If you’re familiar with the kit, you’ll know how easy it is to use and how good it is for prototyping services quickly and easily.

However, when you’re working with a prototype that might be large or have a few different routes within it, making changes when iterating can get complicated. For example, changing bank links next pages in the journey and routes depending on question responses. It can all get time consuming to start changing stuff repeatedly.

I faced this problem this week.

I have a prototype for a service which has about 50 pages and the journey has changed a few times based on user feedback, research and business needs.

User journey map

The latest iteration aimed to simplify the journey as the previous journey had a check your answers page and a task list and just confused users. It felt like 2 disjointed services rather than one coherent journey.

I decided to take a step back and rather than change each pages back link and routing, I wanted to see if I could be a bit cleverer and make it more configurable.

I wanted a way for others in the team, unfamiliar with writing code or where just a part of a journey needs to change, to be able to change just a config file.

This has benefits for also being able to create and test different user journeys and easily supports A/B testing of different versions of pages too if needed. Just create a different version of the config file and you’re away.


You can get the code for this, including a working demo from my repo:
https://github.com/awjdigital/Prototype-kit-config

The solution I have implemented, which has room for improvement and extending, is as follows:

The config file

{
"pages":
[{
"page": "keep",
"back": "maintenance/start",
"submit": "maintenance/assessment/keep",
"next": "",
"check": "",
"conditions":[{
"yes": "/maintenance/assessment/financial",
"no": "/maintenance/assessment/outcome/surrender"
}]
}]
}

This is a straightforward json file which allows for an array of pages.

page: the name of the file or view
back: the url for the back link
submit: the url for the form action
next: this is populated when there are no conditional routes
check: this is the url for the check your answers page if used
conditions: an array of options based on the form, in this example, there is a conditional route based on how a yes/no radio is answered.

The route file

Get request

router.get('/maintenance/assessment/keep', (req, res) => {
var appJourneyData = require('./data/app-journey-config.json')
var appJourney = appJourneyData.pages.filter(function (value) {
return value.page === "keep";
})[0];
res.render('/maintenance/assessment/keep', {
appJourney
});
})

This route for the get action, retrieves the config file and gets the config vales for the page “keep”, and the array object passed to the view data.

There is scope for improvement here, some validation is the object doesn’t exist and even some auto-generated routes based on the config.

Post request

router.post('/maintenance/assessment/keep', (req, res) => {
var appJourneyData = require('./data/app-journey-config.json')
var appJourney = appJourneyData.pages.filter(function (value) {
return value.page === "keep";
})[0];
if (req.session.data['keep-licence'] === 'no') {
res.redirect('appJourney.conditions[0].no);
} else {
res.redirect('appJourney.conditions[0].yes);
}
})

With the post request, the values in the page object are used to determine where to go next. As the ‘keep’ page has conditions, these are used to set the redirect in an if statement.

This could be significantly improved by setting the form input name in the config, which is used in the conditions.

For now though, this works fine for what we need.

View

Using the page config in the view

<a href="/{{appJourney.back}}" class="govuk-back-link">Back</a>
<form method="POST" action="/{{appJourney.submit}}">
...
</form>

As you’ll see the back link and submit links are set based on the config.

In summary

While there are lots of improvements that can be made, this fairly simple solution doesn't require much effort to implement. It enables you to make changes to your service journey quite easily, quickly and even on the fly if doing user research and the journey needs changing.

Let me know if you use this technique, or you have your own way of doing it.