Webhooks

Webhooks are one way to keep cached experiment configuration up-to-date on your servers.

With the API, your servers pull experiment overrides from GrowthBook in a cronjob (or similar).

With Webhooks, GrowthBook pushes experiment overrides to your servers as soon as they change.

Adding a Webhook Endpoint

When logged into GrowthBook as an admin, navigate to Settings -> Webhooks.

There you can add a webhook endpoint.

This page is also where you can view the shared secret used to verify requests (see below) and see the status of your webhook and any errors.

Payload

Webhooks will do a POST to the endpoint you provide. The body is a JSON object containing experiment overrides in the same format as the API returns.

Here's an example payload:

{
  "timestamp": 1625098156,
  "overrides": {
    "experiment-key": {
      "status": "running",
      "weights": [0.5, 0.5],
      "coverage": 1,
      "groups": ["beta"],
      "url": "^/post/[0-9]+$"
    },
    "another-experiment": {
      "status": "stopped",
      "force": 2
    }
  }
}

The overrides field has one entry per experiment with overrides that should take precedence over hard-coded values in your code.

  • status - Either "draft", "running", or "stopped". Stopped experiments are only included in the response if a non-control variation won.
  • weights - How traffic should be weighted between variations. Will add up to 1.
  • coverage - A float from 0 to 1 (inclusive) which specifies what percent of users to include in the experiment.
  • groups - An array of user groups who are eligible for the experiment
  • url - A regex for which URLs the experiment should run on
  • force - Force all users to see the specified variation index (0 = control, 1 = first variation, etc.).

VPCs and Firewalls

If your webhook endpoint is behind a firewall and you are using GrowthBook Cloud, make sure to whitelist the ip address 52.70.79.40.

Verify Signatures

Webhook payloads are signed with a shared secret so you can verify they actually came from GrowthBook. The signature is passed in a X-GrowthBook-Signature header.

Here is example code in NodeJS for verifying the signature. Other languages should be similar:

const crypto = require("crypto");
const express = require("express");
const bodyParser = require("body-parser");

// Retrieve from GrowthBook settings
const GROWTHBOOK_WEBHOOK_SECRET = "abc123";

const app = express();

app.post("/webhook", bodyParser.raw(), (req, res) => {
  const payload = req.body;
  const sig = req.get("X-GrowthBook-Signature");

  const computed = crypto
    .createHmac("sha256", GROWTHBOOK_WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(sig))) {
    throw new Error("Signatures do not match!");
  }

  const { overrides } = JSON.parse(payload);
  // TODO: Store in a cache or database

  // Make sure to respond with a 200 status code
  res.status(200).send("");
});

Errors and Retries

If your endpoint returns any HTTP status besides 200, the webhook will be considered failed.

Failed webhooks are tried a total of 3 times using an exponential back-off between attempts.

You can view the status of your webhooks in the GrowthBook app under Settings -> Webhooks.