Python
View the full documentation on GitHub.
Installation
pip install growthbook (recommended) or copy growthbook.py into your project
Quick Usage
import requests
from growthbook import GrowthBook
# We recommend using a db or cache layer in production
apiResp = requests.get("https://cdn.growthbook.io/api/features/MY_API_KEY")
features = apiResp.json()["features"]
# User attributes for targeting and experimentation
attributes = {
  "id": "123",
  "customUserAttribute": "foo"
}
def on_experiment_viewed(experiment, result):
  # Use whatever event tracking system you want
  analytics.track(attributes["id"], "Experiment Viewed", {
    'experimentId': experiment.key,
    'variationId': result.variationId
  })
# Create a GrowthBook instance
gb = GrowthBook(
  attributes = attributes,
  features = features,
  trackingCallback = on_experiment_viewed
)
# Simple on/off feature gating
if gb.isOn("my-feature"):
  print("My feature is on!")
# Get the value of a feature with a fallback
color = gb.getFeatureValue("button-color-feature", "blue")
GrowthBook class
The GrowthBook constructor has the following parameters:
- enabled (
bool) - Flag to globally disable all experiments. Default true. - attributes (
dict) - Dictionary of user attributes that are used for targeting and to assign variations - url (
str) - The URL of the current request (if applicable) - features (
dict) - Feature definitions from the GrowthBook API - forcedVariations (
dict) - Dictionary of forced experiment variations (used for QA) - qaMode (
boolean) - If true, random assignment is disabled and only explicitly forced variations are used. - trackingCallback (
callable) - A function that takesexperimentandresultas arguments. 
There are also getter and setter methods for features and attributes if you need to update them later in the request:
gb.setFeatures(gb.getFeatures())
gb.setAttributes(gb.getAttributes())
Features
Defines all of the available features plus rules for how to assign values to users. Features are usually fetched from the GrowthBook API and persisted in cache or a database in production.
Feature definitions are defined in a JSON format. You can fetch them directly from the GrowthBook API:
import requests
apiResp = requests.get("https://cdn.growthbook.io/api/features/MY_API_KEY")
features = apiResp.json()["features"]
Or, you can use a copy stored in your database or cache server instead:
import json
json_string = '{"feature-1":{...},"feature-2":{...},...}'
features = json.loads(json_string)
We recommend using the db/cache approach for production.
Attributes
You can specify attributes about the current user and request. These are used for two things:
- Feature targeting (e.g. paid users get one value, free users get another)
 - Assigning persistent variations in A/B tests (e.g. user id "123" always gets variation B)
 
Attributes can be any JSON data type - boolean, integer, float, string, list, or dict.
attributes = {
  'id': "123",
  'loggedIn': True,
  'age': 21.5,
  'tags': ["tag1", "tag2"],
  'account': {
    'age': 90
  ]
}
Tracking Experiments
Any time an experiment is run to determine the value of a feature, you want to track that event in your analytics system.
You can use the trackingCallback option to do this:
from growthbook import GrowthBook, Experiment, Result
def on_experiment_viewed(experiment: Experiment, result: Result):
  # Use whatever event tracking system you want
  analytics.track(attributes["id"], "Experiment Viewed", {
    'experimentId': experiment.key,
    'variationId': result.variationId
  })
gb = GrowthBook(
  trackingCallback = on_experiment_viewed
)
Using Features
There are 3 main methods for interacting with features.
gb.isOn("feature-key")returns true if the feature is ongb.isOff("feature-key")returns false if the feature is ongb.getFeatureValue("feature-key", "default")returns the value of the feature with a fallback
In addition, you can use gb.evalFeature("feature-key") to get back a FeatureResult object with the following properties:
- value - The JSON-decoded value of the feature (or 
nullif not defined) - on and off - The JSON-decoded value cast to booleans
 - source - Why the value was assigned to the user. One of 
unknownFeature,defaultValue,force, orexperiment - experiment - Information about the experiment (if any) which was used to assign the value to the user
 - experimentResult - The result of the experiment (if any) which was used to assign the value to the user
 
Inline Experiments
Instead of declaring all features up-front and referencing them by ids in your code, you can also just run an experiment directly. This is done with the gb->run method:
from growthbook import Experiment
exp = Experiment(
  key = "my-experiment",
  variations = ["red", "blue", "green"]
)
# Either "red", "blue", or "green"
print(gb.run(exp).value)
As you can see, there are 2 required parameters for experiments, a string key, and an array of variations. Variations can be any data type, not just strings.
There are a number of additional settings to control the experiment behavior:
- key (
str) - The globally unique tracking key for the experiment - variations (
any[]) - The different variations to choose between - weights (
float[]) - How to weight traffic between variations. Must add to 1. - coverage (
float) - What percent of users should be included in the experiment (between 0 and 1, inclusive) - condition (
dict) - Targeting conditions - force (
int) - All users included in the experiment will be forced into the specified variation index - hashAttribute (
string) - What user attribute should be used to assign variations (defaults to "id") - namespace (
tuple[str,float,float]) - Used to run mutually exclusive experiments. 
Here's an example that uses all of them:
exp = Experiment(
  key="my-test",
  # Variations can be a list of any data type
  variations=[0, 1],
  # Run a 40/60 experiment instead of the default even split (50/50)
  weights=[0.4, 0.6],
  # Only include 20% of users in the experiment
  coverage=0.2,
  # Targeting condition using a MongoDB-like syntax
  condition={
    'country': 'US',
    'browser': {
      '$in': ['chrome', 'firefox']
    }
  },
  # Use an alternate attribute for assigning variations (default is 'id')
  hashAttribute="sessionId",
  # Includes the first 50% of users in the "pricing" namespace
  # Another experiment with a non-overlapping range will be mutually exclusive (e.g. [0.5, 1])
  namespace=("pricing", 0, 0.5),
)
Inline Experiment Return Value
A call to run returns a Result object with a few useful properties:
result = gb.run(exp)
# If user is part of the experiment
print(result.inExperiment) # True or False
# The index of the assigned variation
print(result.variationId) # e.g. 0 or 1
# The value of the assigned variation
print(result.value) # e.g. "A" or "B"
# The user attribute used to assign a variation
print(result.hashAttribute) # "id"
# The value of that attribute
print(result.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:
gb.run(Experiment(
  key = "3-way-uneven",
  variations = ["A","B","C"],
  weights = [0.5, 0.25, 0.25]
))
Slow rollout (10% of users who match the targeting condition):
# User is marked as being in "qa" and "beta"
gb = GrowthBook(
  attributes = {
    "id": "123",
    "beta": True,
    "qa": True,
  },
)
gb.run(Experiment(
  key = "slow-rollout",
  variations = ["A", "B"],
  coverage = 0.1,
  condition = {
    'beta': True
  }
))
Complex variations
result = gb.run(Experiment(
  key = "complex-variations",
  variations = [
    ("blue", "large"),
    ("green", "small")
  ],
))
# Either "blue,large" OR "green,small"
print(result.value[0] + "," + result.value[1])
Assign variations based on something other than user id
gb = GrowthBook(
  attributes = {
    "id": "123",
    "company": "growthbook"
  }
)
# Users in the same company will always get the same variation
gb.run(Experiment(
  key = "by-company-id",
  variations = ["A", "B"],
  hashAttribute = "company"
))
Django
For Django (and other web frameworks), we recommend adding a simple middleware where you instantiate the GrowthBook object
from growthbook import GrowthBook
def growthbook_middleware(get_response):
    def middleware(request):
        request.gb = GrowthBook(
          # ...
        )
        response = get_response(request)
        request.gb.destroy() # Cleanup
        return response
    return middleware
Then, you can easily evaluate a feature (or run an inline experiment) in any of your views:
def index(request):
    featureEnabled = request.gb.isOn("my-feature")
    # ...
