npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@banditjs/bandit-core

v1.0.4-beta

Published

Core library for the Bandit.js

Downloads

3

Readme

Bandit-core

Core library for the Banditjs

Bandit.js is a simple, lightweight A/B testing library. Bandit's goal is to make A/B testing more accessible for application developers.

There are currently 3 different kinds of testing types Bandit supports, normal, multivariant & dependent A/B tests.

Bandit is primarily configuaration driven, A/B tests are all derived from a JSON/Javascript configuration you provide when instanciating Bandit.

Installation

npm i @banditjs/bandit-core

Coin types & Demos

Normal coins

Normal coins represent your standard A/B tests. They involve a control and a single experiment and are the most straightforward to configure in a Bandit configuration.

Your coin needs a unique name, probability (a natural number from 0-100) & the normal type.

Example

import { Chest } from '@banditjs/bandit-core';

const definitions = [
  {
    name: 'redText',
    probability: 50,
    type: 'normal'
  }
];

const sample = Chest(definitions).mixCoins();
const textColor = sample.redText.active ? 'red' : 'blue';

In this example above we have a normal coin named redText that would be active 50% of the time. When it is active our textColor would be set to red otherwise it would be set to blue.

Multivariant coins

A Multivariant coin represents a multi-experiment A/B test, which is an A/B test where you have multiple related experiments running against one another and potentially a control. Another name we like to use for these tests are A-to-Z tests.

Example

import { Chest } from '@banditjs/bandit-core';

const defintiions = [
  {
    name: 'textColor',
    type: 'multivariant',
    variants: [
      { name: 'red', probability: 10 },
      { name: 'blue', probability: 10 },
      { name: 'purple', probability: 10 },
      { name: 'green', probability: 10 }
    ]
  }
];

const sample = Chest(defintiions).mixCoins();

// If any of the variants end up active take the name which is the text color to use otherwise default to white
let activeVariant = sample.textColor.variants.filter(variant => variant.active);
let textColor = activeVariant.length > 0 ? activeVariant[0].name : 'white';

In this example we have a multivariant coin named textColor, it has 4 different variants, red, blue, purple & green, and all of them have a 25% chance of being active.

Bandit currently does the probability for multivariant tests out of 100. If your probabilities add up to more than 100 you will not see expected behaviors in your tests. If your probabilities add up to less than 100 the remaining difference represents the probability none of your tests are active.

Dependent coin

A dependent coin represents an A/B test that can be active or not depending on the behavior of another test. This coin is meant to give the ability to test behavior similar to this:

- You have three tests, A, B & C
- A should never be active if B is active
- B should always be active when C is not active

Example

import { Chest } from '@banditjs/bandit-core';

const defintiions = [
	{
		name: 'whiteBackground',
		probability: 50
		type: 'normal'
	},
	{
		dependsOn: [
      {
        active: true,
        behavior: false,
        name: 'whiteBackground'
      }
    ],
		name: 'yellowText',
		probability: 100,
		type: 'dependent',

	}
]

const sample = Chest(definitions).mixCoins();
const background = sample.whiteBackground.active ? 'white' : 'black';
const textColor = sample.yellowText.active ? 'yellow' : 'red'

In this example we have two coins, whiteBackground which is a normal coin active 50% of the time & yellowText which is a dependent coin which is active 100% of the time(sort of) and is dependent on the whiteBackground coin

Now everyone knows yellow text on a white background is unreadable so the yellowText dependent coin is configured to have inactive(false) behavior when the whiteBackground coin is active (true)

When the whiteBackground coin is active the background color is white and the yellowText coin is inactive so the textColor is it's default color red. Otherwise when the whiteBackground coin is inactive the yellowText coin is guarnteed to be active so the background is it's default color black and the text color is yellow.

Math

With that said to know the true probability of the yellowText coin we need to take that constraint into account:

The whiteBackground coin would be 50/100 or .5 and yellowText would be 100/100 or 1

Now to find the true probability of yellowText we need to multiply it's value by the value of whiteBackground

So 1 * .5 or .5 is the true probability of yellowText

Keep this fact in mind when building your dependent tests out as you need to do a little math to ensure your samplingf is being done correctly.

Circular Dependencies

Bandit does not handle circular dependencies in dependent coins, upon initalizing a chest Bandit will check the definition provided and throw an error if any circular dependencies are found.

Currency converters

A currency converter is a function that is applied to every coin in a chest after it has been mixed and sampled from. They allow you to apply last minute logic to a sample before it is returned back to you

These converters are applied via a call to Chest.mixCoins(...currencyConverters) where currencyConverters is an array of functions to apply in order from last to first applied. These functions must take in a

Demo

You want to tag some extra metadata on your tests in order to run some analytics on the distribution of what tests were active across browsers.

import { Chest } from '@banditjs/bandit-core';

const browserName = // Some calculation of what browser currently in use
const browserTrackingConverter = coin => coin.metadata.browser = browserName

const defintiions = [
   {
    name: 'lucky',
    probability: 50,
    type: 'normal'
  },
  {
    name: 'textColor',
    type: 'multivariant',
    variants: [
      { name: 'red', probability: 25 },
      { name: 'blue', probability: 25 }
    ]
  }
];

const sample = Chest(defintiions, [browserTrackingConverter]).mixCoins();

// Sample could look similar to
[
  {
    active: false,
     metadata: {
      browser: 'Microsoft Edge'
    },
    name: 'lucky',
    probablility: 50,
    type: 'NORMAL'
  },
  {
    metadata: {
      browser: 'Microsoft Edge'
    },
    name: 'textColor',
    type: 'MULTIVARIANT',
    variants: [
      {
    active: false,
    name: 'red',
    probability: 25,
    type: 'VARIANT'
  },
  {
    active: true,
    name: 'blue',
    probability: 25,
    type: 'VARIANT'
  }
    ]

  }
]

isActive converter

By default the first converted always applied is the isActive converter, it applies a boolean active property to all coins & variants in the sample depending on whether or not they were flipped active when mixing the coins in the chest. This includes flipping dependent coins active and inactive depending on the results of the coins they are dependent on.