Simplifying experiments with React.
Bucket testing (sometimes referred to as A/B testing or split testing) is a term used to describe the method testing two versions of a website against one another to see which one performs better on specified key metrics (such as clicks, downloads or purchases).
npm install react-bucket-test
yarn add react-bucket-test
import Hypothesis, { Variation } from 'react-bucket-test';
import GoogleTagManager from 'react-bucket-test/lib/drivers/GoogleTagManager';
const driver = GoogleTagManager({
prefix: 'my_cool_prefix_'
});
const Header = () => (
<header>
<Hypothesis name="CTA Button" driver={driver}>
<Variation
name="Control"
traffic={80}
render={({ registerEvent }) => (
<div>
<button onClick={() => registerEvent({ action: 'click' })}>
Get started for free
</button>
</div>
)}
/>
<Variation
name="Variation"
traffic={20}
render={({ registerEvent }) => (
<div>
<button onClick={() => registerEvent({ action: 'click' })}>
Create your account
</button>
</div>
)}
/>
</Hypothesis>
</header>
);
That's it!
const driver = myCustomDriver();
const HeroBanner = () => (
<Hypothesis name="Homepage Hero Banner with Video" driver={driver}>
...
</Hypothesis>
);
This is the container for your tests, that's the component that will read and set your variations, dispatch the events to the driver, all logic is here. It accepts only <Variation>
as children.
It passes this value to the driver. It is an id like for your tests. It's better to have unique names for each hypothesis.
This library provides some drivers, such as Google Tag Manager (more are coming). Drivers must follow an interface, you can check the section to create your own drivers.
<Variation
name="Video with cats"
traffic={50}
render={({ registerEvent }) => (
<HeroWithVideo
video="cats.mp4"
onPlay={() => registerEvent({ action: 'play', category: 'cats' })}
/>
)}
/>
You can specify how to split the traffic of your tests. It must be a number. If you don't specify a traffic, it will split the traffic automatically through your variations equally. If you have 4 variations and the traffic is not specified, the traffic will be split into 25% for each variation.
If you specify a traffic for one variation, you must specify for all of your variations.
It uses weights, not percentage. This means you can use for example, 2, 1, 1 instead of 50, 25, 25.
render
: ({ registerEvent: func, category: string, name: string, traffic: number | null }) => Component
To render your component. It passes down the following parameters:
registerEvent
: function - it accepts an object of any property as parameter, the driver will receive this object.category
: string - the hypothesis name.name
: string - the variation name.traffic
: number - the variation traffic.
Drivers are used to register the events to a tracking tool, such as Google Tag Manager. You can pass any driver to the <Hypothesis>
component. This library provides drivers for the following tracking tools:
- Google Tag Manager
To create your own driver, you just need to create an object with the following properties:
Default: react_bucket_test_
It's useful to create a namespace for your application.
Default: localStorage.getItem
Used by <Hypothesis>
to render the correct variation.
Default: localStorage.setItem
Used by <Hypothesis>
to set a variation in case if none exists.
onMount
is called by <Hypothesis>
when componentDidMount
.
onUnmount
is called by <Hypothesis>
when componentWillUnmount
.
category
: string - the hypothesis name.name
: string - the variation name.traffic
: number - the variation traffic.
That's the method that your <Variation>
receives when rendered.
props
receives at least:
category
: string - the hypothesis name.name
: string - the variation name.traffic
: number - the variation traffic.
You will override these properties if you pass properties with those names.
It uses dataLayer
variable to publish events to GTM.
Default:
prefix
: 'reactbucket_test_gtm'onMount
:{ action: 'load', ...props }
onUnmount
:{ action: 'unmount', ...props }
registerEvent
:{ action: 'registerEvent', ...props }
You can override any property:
// drivers are not included to the final bundle size
import GoogleTagManager from 'react-bucket-test/lib/drivers/GoogleTagManager';
const driver = GoogleTagManager({
prefix: 'experiment_'
});
Made with ❤️