Skip to content

A/B testing React components and debug tools. Simple, universal interface. Well documented and tested in popular browsers.

License

Notifications You must be signed in to change notification settings

eisisig/react-ab-test

 
 

Repository files navigation

A/B Testing React Components

NPM Version Circle CI Coverage Status Dependency Status

Wrap components in <Variant /> and nest in <Experiment />. A variant is chosen randomly and saved to local storage.

<Experiment name="My Example">
  <Variant name="A">
    <div>Version A</div>
  </Variant>
  <Variant name="B">
    <div>Version B</div>
  </Variant>
</Experiment>

Report to your analytics provider using the emitter.

emitter.addPlayListener(function(experimentName, variantName){
  mixpanel.track("Start Experiment", {name: experimentName, variant: variantName});
});

Table of Contents

Installation

npm install react-ab-test

Usage

Standalone Component

Try it on JSFiddle

var Experiment = require("react-ab-test").Experiment;
var Variant = require("react-ab-test").Variant;
var emitter = require("react-ab-test").emitter;

var App = React.createClass({
  onButtonClick: function(e){
    this.refs.experiment.win();
  },
  render: function(){
    return <div>
      <Experiment ref="experiment" name="My Example">
        <Variant name="A">
          <div>Section A</div>
        </Variant>
        <Variant name="B">
          <div>Section B</div>
        </Variant>
      </Experiment>
      <button onClick={this.onButtonClick}>Emit a win</button>
    </div>;
  }
});

// Called when the experiment is displayed to the user.
emitter.addPlayListener(function(experimentName, variantName){
  console.log("Displaying experiment ‘" + experimentName + "’ variant ‘" + variantName + "’");
});

// Called when a 'win' is emitted, in this case by this.refs.experiment.win()
emitter.addWinListener(function(experimentName, variantName){
  console.log("Variant ‘" + variantName + "’ of experiment ‘" + experimentName + "’  was clicked");
});

Coordinate Multiple Components

Try it on JSFiddle

var Experiment = require("react-ab-test").Experiment;
var Variant = require("react-ab-test").Variant;
var emitter = require("react-ab-test").emitter;

// Define variants in advance.
emitter.addExperimentVariants("My Example", ["A", "B", "C"]);

var Component1 = React.createClass({
  render: function(){
    return <Experiment name="My Example">
      <Variant name="A">
        <div>Section A</div>
      </Variant>
      <Variant name="B">
        <div>Section B</div>
      </Variant>
    </Experiment>;
  }
});

var Component2 = React.createClass({
  render: function(){
    return <Experiment name="My Example">
      <Variant name="A">
        <div>Subsection A</div>
      </Variant>
      <Variant name="B">
        <div>Subsection B</div>
      </Variant>
      <Variant name="C">
        <div>Subsection C</div>
      </Variant>
    </Experiment>;
  }
});

var Component3 = React.createClass({
  onButtonClick: function(e){
    emitter.emitWin("My Example");
  },
  render: function(){
    return <button onClick={this.onButtonClick}>Emit a win</button>;
  }
});

var App = React.createClass({
  render: function(){
    return <div>
      <Component1 />
      <Component2 />
      <Component3 />
    </div>;
  }
});

// Called when the experiment is displayed to the user.
emitter.addPlayListener(function(experimentName, variantName){
  console.log("Displaying experiment ‘" + experimentName + "’ variant ‘" + variantName + "’");
});

// Called when a 'win' is emitted, in this case by emitter.emitWin()
emitter.addWinListener(function(experimentName, variantName){
  console.log("Variant ‘" + variantName + "’ of experiment ‘" + experimentName + "’ was clicked");
});

Debugging

Try it on JSFiddle

var Experiment = require("react-ab-test").Experiment;
var Variant = require("react-ab-test").Variant;
var experimentDebugger = require("react-ab-test").experimentDebugger;

experimentDebugger.enable();

var App = React.createClass({
  render: function(){
    return <div>
      <Experiment ref="experiment" name="My Example">
        <Variant name="A">
          <div>Section A</div>
        </Variant>
        <Variant name="B">
          <div>Section B</div>
        </Variant>
      </Experiment>
    </div>;
  }
});

Alternative Libraries

Please let us know about alternate libraries not included here.

Resources for A/B Testing with React

Please let us know about React A/B testing resources not included here.

API Reference

<Experiment />

Experiment container component. Children must be of type Variant.

  • Properties:
    • name - Name of the experiment.
      • Required
      • Type: string
      • Example: "My Example"
    • defaultValue - Name of the default variant. This property is useful for server side rendering but otherwise not recommended.
      • Optional
      • Type: string
      • Example: "A"

<Variant />

Variant component.

  • Properties:
    • name - Name of the variant.
      • Required
      • Type: string
      • Example: "A"

emitter

Event emitter responsible for coordinating and reporting usage. Extended from facebook/emitter.

emitter.emitWin(experimentName)

Emit a win event.

  • Return Type: No return value
  • Parameters:
    • experimentName - Name of an experiment.
      • Required
      • Type: string
      • Example: "My Example"

emitter.addVariantListener([experimentName, ] callback)

Listen for variants being added to an experiment.

  • Return Type: Subscription
  • Parameters:
    • experimentName - Name of an experiment. If provided, the callback will only be called for the specified experiment.
      • Optional
      • Type: string
      • Example: "My Example"
    • callback - Function to be called when a variant is added to an experiment.
      • Required
      • Type: function
      • Callback Arguments:
        • experimentName - Name of the experiment.
          • Type: string
        • variantName - Name of the variant.
          • Type: string

emitter.addValueListener([experimentName, ] callback)

Listen for the chosen value of an experiment.

  • Return Type: Subscription
  • Parameters:
    • experimentName - Name of an experiment. If provided, the callback will only be called for the specified experiment.
      • Optional
      • Type: string
      • Example: "My Example"
    • callback - Function to be called when a variant is chosen.
      • Required
      • Type: function
      • Callback Arguments:
        • experimentName - Name of the experiment.
          • Type: string
        • variantName - Name of the variant.
          • Type: string

emitter.addPlayListener([experimentName, ] callback)

Listen for an experiment being displayed to the user. Trigged by the React componentWillMount lifecycle method.

  • Return Type: Subscription
  • Parameters:
    • experimentName - Name of an experiment. If provided, the callback will only be called for the specified experiment.
      • Optional
      • Type: string
      • Example: "My Example"
    • callback - Function to be called when an experiment is displayed to the user.
      • Required
      • Type: function
      • Callback Arguments:
        • experimentName - Name of the experiment.
          • Type: string
        • variantName - Name of the variant.
          • Type: string

emitter.addWinListener([experimentName, ] callback)

Listen for a successful outcome from the experiment. Trigged by the emitter.emitWin(experimentName) method.

  • Return Type: Subscription
  • Parameters:
    • experimentName - Name of an experiment. If provided, the callback will only be called for the specified experiment.
      • Optional
      • Type: string
      • Example: "My Example"
    • callback - Function to be called when a win is emitted.
      • Required
      • Type: function
      • Callback Arguments:
        • experimentName - Name of the experiment.
          • Type: string
        • variantName - Name of the variant.
          • Type: string

emitter.addExperimentVariants(experimentName, variantNames)

Define experiment variant names. Required when an experiment spans multiple components.

  • Return Type: No return value
  • Parameters:
    • experimentName - Name of the experiment.
      • Required
      • Type: string
      • Example: "My Example"
    • variantNames - Array of variant names.
      • Required
      • Type: Array.<string>
      • Example: ["A", "B", "C"]

emitter.setExperimentValue(experimentName, variantName)

Set the active variant of an experiment.

  • Return Type: No return value
  • Parameters:
    • experimentName - Name of the experiment.
      • Required
      • Type: string
      • Example: "My Example"
    • variantName - Name of the variant.
      • Required
      • Type: string
      • Example: "A"

emitter.getExperimentValue(experimentName)

Returns the variant name currently displayed by the experiment.

  • Return Type: string
  • Parameters:
    • experimentName - Name of the experiment.
      • Required
      • Type: string
      • Example: "My Example"

experimentDebugger

Debugging tool. Attaches a fixed-position panel to the bottom of the <body> element that displays active experiments and enables the user to change active variants in real-time.

The debugger is wrapped in a conditional if(process.env.NODE_ENV === "production") {...} and will not display on production builds using envify.

experimentDebugger.enable()

Attaches the debugging panel to the <body> element.

  • Return Type: No return value

experimentDebugger.disable()

Removes the debugging panel from the <body> element.

  • Return Type: No return value

Subscription

Returned by the emitter's add listener methods. More information available in the facebook/emitter documentation.

subscription.remove()

Removes the listener subscription and prevents future callbacks.

  • Parameters: No parameters

About

A/B testing React components and debug tools. Simple, universal interface. Well documented and tested in popular browsers.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 99.1%
  • HTML 0.9%