GrowthBook Javascript Client Library

Supports both browser and NodeJS environments.

Installation

yarn add @growthbook/growthbook

or

npm install --save @growthbook/growthbook

or use directly in your HTML without installing first:

<script type="module">
  import { GrowthBook } from "https://unpkg.com/@growthbook/growthbook/dist/bundles/esm.min.js";
  //...
</script>

Quick Usage

import { GrowthBook } from "@growthbook/growthbook";

// Define the experimental context
const growthbook = new GrowthBook({
  // The attributes used to assign variations
  user: { id: "123" },
  // Called when a user is put into an experiment
  trackingCallback: (experiment, result) => {
    analytics.track("Experiment Viewed", {
      experimentId: experiment.key,
      variationId: result.variationId,
    });
  },
});

// Run an experiment
const { value } = growthbook.run({
  key: "my-experiment",
  variations: ["A", "B"],
});

console.log(value); // "A" or "B"

GrowthBook class

The GrowthBook constructor takes a Context object. Below are all of the possible Context properties:

  • enabled (boolean) - Switch to globally disable all experiments. Default true.
  • user ({}) - Map of user attributes that are used to assign variations
  • groups ({}) - A map of which groups the user belongs to (key is the group name, value is boolean)
  • url (string) - The URL of the current page (defaults to window.location.href when in a browser environment)
  • overrides ({}) - Override properties of specific experiments (used for Remote Config)
  • forcedVariations ({}) - Force specific experiments to always assign a specific variation (used for QA)
  • qaMode (boolean) - If true, random assignment is disabled and only explicitly forced variations are used.
  • trackingCallback (function) - A function that takes experiment and result as arguments.

Experiments

Below are all of the possible properties you can set for an Experiment:

  • key (string) - The globally unique tracking key for the experiment
  • variations (any[]) - The different variations to choose between
  • weights (number[]) - How to weight traffic between variations. Must add to 1.
  • status (string) - "running" is the default and always active. "draft" is only active during QA and development. "stopped" is only active when forcing a winning variation to 100% of users.
  • coverage (number) - What percent of users should be included in the experiment (between 0 and 1, inclusive)
  • url (RegExp) - Users can only be included in this experiment if the current URL matches this regex
  • include (() => boolean) - A callback that returns true if the user should be part of the experiment and false if they should not be
  • groups (string[]) - Limits the experiment to specific user groups
  • force (number) - All users included in the experiment will be forced into the specific variation index
  • hashAttribute (string) - What user attribute should be used to assign variations (defaults to "id")

Running Experiments

Run experiments by calling growthbook.run(experiment) which returns an object with a few useful properties:

const {
  inExperiment,
  variationId,
  value,
  hashAttribute,
  hashValue,
} = growthbook.run({
  key: "my-experiment",
  variations: ["A", "B"],
});

// If user is part of the experiment
console.log(inExperiment); // true or false

// The index of the assigned variation
console.log(variationId); // 0 or 1

// The value of the assigned variation
console.log(value); // "A" or "B"

// The user attribute used to assign a variation
console.log(hashAttribute); // "id"

// The value of that attribute
console.log(hashValue); // e.g. "123"

The inExperiment flag is only set to true if the user was randomly assigned a variation. If the user failed any targeting rules or was forced into a specific variation, this flag will be false.

Example Experiments

3-way experiment with uneven variation weights:

growthbook.run({
  key: "3-way-uneven",
  variations: ["A", "B", "C"],
  weights: [0.5, 0.25, 0.25],
});

Slow rollout (10% of users who opted into "beta" features):

// User is in the "qa" and "beta" groups
const growthbook = new GrowthBook({
  user: { id: "123" },
  groups: {
    qa: isQATester(),
    beta: betaFeaturesEnabled(),
  },
});

growthbook.run({
  key: "slow-rollout",
  variations: ["A", "B"],
  coverage: 0.1,
  groups: ["beta"],
});

Complex variations and custom targeting

const {value} = growthbook.run({
  key: "complex-variations",
  variations: [
    {color: "blue", size: "large"},
    {color: "green", size: "small"}
  ],
  url: /^\/post\/[0-9]+$/i
  include: () => isPremium || creditsRemaining > 50
});

console.log(value.color, value.size); // blue,large OR green,small

Assign variations based on something other than user id

const growthbook = new GrowthBook({
  user: {
    id: "123",
    company: "growthbook",
  },
});

growthbook.run({
  key: "by-company-id",
  variations: ["A", "B"],
  hashAttribute: "company",
});

// Users in the same company will always get the same variation

Overriding Experiment Configuration

It's common practice to adjust experiment settings after a test is live. For example, slowly ramping up traffic, stopping a test automatically if guardrail metrics go down, or rolling out a winning variation to 100% of users.

For example, to roll out a winning variation to 100% of users:

const growthbook = new GrowthBook({
  user: { id: "123" },
  overrides: {
    "experiment-key": {
      status: "stopped",
      force: 1,
    },
  },
});

const { value } = growthbook.run({
  key: "experiment-key",
  variations: ["A", "B"],
});

console.log(value); // Always "B"

The full list of experiment properties you can override is:

  • status
  • force
  • weights
  • coverage
  • groups
  • url (can use string instead of regex if serializing in a database)

If you use the GrowthBook App (https://github.com/growthbook/growthbook) to manage experiments, there's a built-in API endpoint you can hit that returns overrides in this exact format. It's a great way to make sure your experiments are always up-to-date.

Typescript

This module exposes Typescript types if needed.

This is especially useful if experiments are defined as a variable before being passed into growthbook.run. Unions and tuples are used heavily and Typescript has trouble inferring those properly.

import type {
  Context,
  Experiment,
  Result,
  ExperimentOverride,
} from "@growthbook/growthbook";

// The "number" part refers to the variation type
const exp: Experiment<number> = {
  key: "my-test",
  variations: [0, 1],
  status: "stoped", // Type error! (should be "stopped")
};

Event Tracking and Analyzing Results

This library only handles assigning variations to users. The 2 other parts required for an A/B testing platform are Tracking and Analysis.

Tracking

It's likely you already have some event tracking on your site with the metrics you want to optimize (Google Analytics, Segment, Mixpanel, etc.).

For A/B tests, you just need to track one additional event - when someone views a variation.

// Specify a tracking callback when instantiating the client
const growthbook = new GrowthBook({
  user: { id: "123" },
  trackingCallback: (experiment, result) => {
    // ...
  },
});

Below are examples for a few popular event tracking tools:

Google Analytics

ga("send", "event", "experiment", experiment.key, result.variationId, {
  // Custom dimension for easier analysis
  dimension1: `${experiment.key}::${result.variationId}`,
});

Segment

analytics.track("Experiment Viewed", {
  experimentId: experiment.key,
  variationId: result.variationId,
});

Mixpanel

mixpanel.track("$experiment_started", {
  "Experiment name": experiment.key,
  "Variant name": result.variationId,
});

Analysis

Now just connect GrowthBook to the data source where your tracked events end up (Mixpanel, GA, or a data warehouse like Snowflake) and you can pull the data, run it through the built-in stats engine, and analyze results.

Dev Mode

If you are using this library to run experiments client-side in a browser, you can use the GrowthBook Dev Mode widget to make development and testing easier.

Simply add the following script tag to your development or staging site:

<script
  async
  src="https://unpkg.com/@growthbook/dev/dist/bundles/index.min.js"
></script>

and you should see the Dev Mode widget on the bottom-left of your screen

Dev Mode Variation Switcher