Split test on two tectonic plates in Thingvellir, Iceland (winner still undefined)

A/B Testing with Redux

Pepijn Senders
HelloTech
3 min readJul 11, 2017

--

We think every developer has a ❤️/👿 relationship with A/B testing. It’s either about loading bulky scripts with jQuery written by marketing people, or it’s about having to hack something into your own code. It’s never really nice or cool, it’s always a drag.

We at HelloFresh wanted to make at least some part of it easier to handle, to keep the disruption from A/B tests to our shiny React / Redux apps to a minimum. This is when we came up with external alterations.

The idea basically sprung from changing the state of the store from a window function. But since we didn't want to add a reducer for everything and we also didn't want to expose every action in our application, we had to think of something special.

The kernel

First we have to add our actions to the window object in an elegant way. We came up with the fancy word ExternalActionKernel, which is basically a very simple React component.

import { Component } from 'react';
import { connect } from 'react-redux';
import { setAlteration } from '../../store/actions/externalAlterations';class ExternalActionKernel extends Component {
componentDidMount() {
window.triggerExternalAction = (action, payload) => {
return this.props[action](payload);
};
}
render() {
return null;
}
}
const mapDispatchToProps = { setAlteration };connect(null, mapDispatchToProps)(ExternalActionKernel);

And then to execute this action you would do something like:

window.triggerExternalAction('setAlteration', {
showTestModal: true
});

The alteration reducer basically holds all the alteration information. We’re not going to bore you with the code there, but it’s basically an object that gets updated through actions. The payload can be any kind of object.

Using the alterations

Now to use this alteration that we just set, we need to connect our component where we would show this: TestModal.


import React, { Component } from 'react';
import { connect } from 'react-redux';
class TestComponent extends Component {
render() {
if (this.props.showTestModal) {
return <div>AB Test</div>;
}
return <div>Normal</div>
}
}
connect(state => ({
showTestModal: state.alterations.showTestModal,
}))(TestComponent);

Look how elegant that is! No more:

$('.ab-test-modal').show()

The only thing the asynchronous scripts have to do now is call this window function with the right parameters and you have an A/B test!

Example

You can play around with our website a bit as well. For example, on our shop page you can change the highlighted product by using this technique.

You can even try yourself, in your browser! Simply go here, pop open your console, and execute the following:

window.triggerExternalAction('setCategoryPromotedProductFamily', {
category: 'kits',
productFamily: 'slice-n-dice-kit',
});
Or if you’re feeling too lazy, you can look at this GIF

🎉🎉🎉🎉🎉

Looking for a new job opportunity? Become a part of our team! We are constantly on the lookout for great talent. Help us in our mission of delivering fresh ingredients to your door and change the way people eat forever.

--

--