-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
rawls238
committed
Aug 18, 2015
0 parents
commit 009b889
Showing
13 changed files
with
823 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
react-experiments | ||
==================== | ||
|
||
react-experiments is a Javascript library that assists in defining and managing UI experiments in React. | ||
|
||
# Installation | ||
|
||
npm install react-experiments | ||
|
||
# Usage | ||
|
||
react-experiments was built to work with [PlanOut.js](https://www.github.com/HubSpot/PlanOut.js) and most of the constructs in it are inspired by the structure of PlanOut.js. This library will work out of the box if you pass it a PlanOut Namespace or Experiment class, but if you want to use your own (potentially more lightweight) methods of assigning experiment parameters and logging exposure then you can extend the base [ExperimentClass](src/experimentClass.js) and pass that as the experimentClass prop to the Experiment class components. | ||
|
||
## Using the Experiment Component | ||
|
||
Here is a basic A/B test defined using react-experiments: | ||
|
||
```javascript | ||
import {TestNamespace} from [file where you define your namespace]; | ||
import {Experiment, Variation} from 'react-experiments'; | ||
|
||
... | ||
|
||
<Experiment experimentClass={TestNamespace} param='show_text'> | ||
<Variation name="experimental"> | ||
Example A | ||
</Variation> | ||
<Variation name='control'> | ||
Example B | ||
</Variation> | ||
</Experiment> | ||
``` | ||
|
||
The name passed into Variation as a prop should be the experimental value that the parameter will resolve to. For example, in this case Example A will be rendered if the 'show_text' param maps to the value "experimental" and Example B will be rendered if the 'show_text param maps to the value "control". | ||
|
||
There are two cases where an experiment component will render nothing: | ||
|
||
1) If, in the example above, the 'show_text' param mapped to the value 'foobar' then the Experiment component will render nothing. | ||
|
||
2) If you want to have conditional enrollment in an experiment then you can pass down an isEnrolled prop to the Experiment component. If the user is not enrolled in the experiment then nothing will render. | ||
|
||
## Namespace Usage | ||
|
||
In the case that you need define more than 1 experiment in the same component and want to ensure that any given user only views at most one experiment, then you can wrap your experiment components inside of a ```Namespace``` components as such: | ||
|
||
```javascript | ||
import {TestNamespace} from [file where you define your namespace]; | ||
import {Namespace, Experiment, Variation} from 'react-experiments'; | ||
|
||
... | ||
|
||
<Namespace experimentClass={TestNamespace}> | ||
<Experiment param='foo'> | ||
<Variation name="experimental"> | ||
[some html] | ||
</Variation> | ||
<Variation name='control'> | ||
[some html] | ||
</Variation> | ||
</Experiment> | ||
<Experiment param='bar'> | ||
<Variation name="experimental"> | ||
[some html] | ||
</Variation> | ||
<Variation name='control'> | ||
[some html] | ||
</Variation> | ||
</Experiment> | ||
</Namespace> | ||
``` | ||
|
||
## Default Component | ||
|
||
The Default component will render in the case that the experiment param does not map to any of the Variation components. The Default component can be used in both an Experiment component and a Namespace component. | ||
|
||
Here are two examples using the Experiment component. Suppose that for user X, the parameter foo maps to the value bar. | ||
|
||
Example A: | ||
```javascript | ||
<Experiment experimentClass={TestNamespace} param='foo'> | ||
<Variation name='foo'> | ||
foo | ||
</Variation> | ||
<Default> | ||
foobar | ||
</Default> | ||
</Experiment> | ||
``` | ||
Example B: | ||
```javascript | ||
<Experiment experimentClass={TestNamespace}> | ||
<Variation name='foo'> | ||
foo | ||
</Variation> | ||
<Variation name='bar'> | ||
bar | ||
</Variation> | ||
<Variation name='test'> | ||
test | ||
</Variation> | ||
<Default> | ||
foobar | ||
</Default> | ||
</Experiment> | ||
``` | ||
|
||
For user X in the example A, the Default component renders since for user X foo maps to bar and there is no variation component defined for bar and therefore foobar will render. | ||
In Example B, there is a variation component defined for bar and in this case bar will render. | ||
|
||
The same general pattern also holds for Namespace components, except Default components will only be respected when they are not in an Experiment component. | ||
|
||
For instance, in this example the Default component will not be rendered. | ||
```javascript | ||
<Namespace experimentClass={TestNamespace} param='foo'> | ||
<Experiment param='foo'> | ||
<Variation name='foo'> | ||
test | ||
</Variation> | ||
<Default> | ||
default | ||
</Default> | ||
</Experiment> | ||
</Namespace> | ||
``` | ||
|
||
However, in this example the Default component will be rendered. | ||
```javascript | ||
<Namespace experimentClass={TestNamespace} param='foo'> | ||
<Experiment param='foo'> | ||
<Variation name='foo'> | ||
test | ||
</Variation> | ||
</Experiment> | ||
<Default> | ||
default | ||
</Default> | ||
</Namespace> | ||
``` | ||
|
||
## Logging | ||
|
||
react-experiments logs an exposure event when it renders a Variation component. Since it only logs exposure when the component actually renders, not when the experiment value is assigned, you can implement the same Experiment component across multiple different React components and be certain that logExposure only gets invoked when the variation the user is enrolled in actually is shown to the user. | ||
|
||
Suppose you have two pages - /start and /welcome. If you have an experiment that is defined as follows: | ||
|
||
```javascript | ||
sampleParam = uniformChoice(choices=['a', 'b'], unit=userid) | ||
``` | ||
|
||
Suppose you define the following Experiment component on the /start page: | ||
```javascript | ||
<Experiment experimentClass={foo} param='sampleParam'> | ||
<Variation name='a'> | ||
test a | ||
</Variation> | ||
</Experiment> | ||
``` | ||
|
||
and the following Experiment component on the /welcome page: | ||
```javascript | ||
<Experiment experimentClass={foo} param='sampleParam'> | ||
<Variation name='b'> | ||
test b | ||
</Variation> | ||
</Experiment> | ||
``` | ||
|
||
then exposure will only be logged if the user is enrolled in the 'a' variation and is viewing the /start page or the user is enrolled in the 'b' variation and is viewing the /welcome page. | ||
|
||
It is important to note as well that if a user is binned into the Default component then exposure is NOT logged. | ||
|
||
|
Oops, something went wrong.