Giter VIP home page Giter VIP logo

firely's Introduction

firely

Firely is an A/B Testing overlay based on Firebase Remote Config. It's a work in progress to simplify the integration and make the management of A/B testing XPs safer.

Download

compile 'com.firely:core:1.0.0'

You need to apply the plugin (TODO integrate in maven repo):

buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }

    dependencies {
        classpath group: 'com.busbud.android', name: 'firely-plugin', version: '0.1.0'
    }
}

apply plugin: 'com.busbud.android.firely'

You also need to import the aar (TODO integrate in maven repo):

compile project(':firely-0.1.0')

How does it work

This library, integrated in your gradle project, only requires:

  • A firely-config.json file that will contains the type of items, the keys, and the default value
  • A call to Firely.setup(Context context) from the Application.onCreate() method
  • One proguard rule

firely-config.json file is organized in 3 main sections (for us, but it can have the "names" you want):

  • Feature Flags
  • Config
  • Experiments (or A/B Tests)

Here is an example of firely-config.json:

{
  "config": [
    {
      "key": "android_version_code_min",
      "default": 0
    }
  ],
  "feature_flag": [
    {
      "key": "refer_a_friend",
      "default": true
    },
    {
      "key": "promotion_url",
      "default": ""
    }
  ],
  "experiment": [
    {
      "key": "xp_button_pay",
      "default": "control"
    }
  ]
}

Firely is an Android library that come with a gradle plugin, firely-plugin. It will generate a FirelyConfig.java file based on the firely-config.json, like the R.java android creates. The FirelyConfig.java will contain Enums that match the configuration. You can then use these enums on Firely to get LiveVariable, CodeBlock, OrderedArrayBlock.

LiveVariable

Let's imagine I am using Remote Config to restrict my user to a minimum Android version on which they can run (otherwise they have to update the app). With Firely, I can instantiate a LiveVariable that will use this setting:

LiveVariable<Integer> minAndroidRemoteVersion = Firely.integerVariable(FirelyConfig.Config.ANDROID_VERSION_CODE_MIN);

FirelyConfig.Config.ANDROID_VERSION_CODE_MIN is generated by the plugin and the default value is 0.

Now, anytime I need to get the last version that has been fetched, I just call:

Integer lastVersion = minAndroidRemoteVersion.get();

Here is another example with a feature flag:

if (Firely.booleanVariable(FirelyConfig.FeatureFlag.REFER_A_FRIEND).get()) {
	// Add the view
}

CodeBlock

Now I need to build out an XP that will change the text of a button.

Firely.codeBlock(Remote.Experiment.XP_BUTTON)
	.withVariant("billed_currency", "no_price")
	.execute(
	() -> advance.setText(getString(R.string.bb_payment_cta)), // control
	() -> advance.setText(.getString(R.string.bb_payment_cta_2)), // billed_currency
	() -> advance.setText(getString(R.string.bb_payment_cta_3))); // no_price

NOTE: we are always using "control" as the default value and as the control group for A/B Tests.

OrderedArrayBlock

In the Busbud Android App, we use a lot of blocks and lists. Let's imagine you have N blocks of data in a page. You want to A/B test which one should go first and the order for all the others. A basic approach could be to have N! variants.

If we have three items: 1-2-3, 2-1-3, 2-3-1, 1-3-2, 3-2-1, 3-1-2

And while using CodeBlocks:

Firely.codeBlock(Remote.Experiment.XP_BUTTON)
	.withVariant("2-1-3", "2-3-1", "1-3-2", "3-2-1", "3-1-2")
	.execute(
	() -> {
		addOne();
		addTwo();
		addThree();
	}, // control
	() -> {
		addTwo();
		addOne();
		addThree();
	},
	... etc

Really inefficient.

Another approach is to use OrderedArrayBlock. You will use one Firebase entry:

{
  ...
  "experiment": [
    {
      "key": "xp_mypage_order",
      "default": "one,two,three"
    }
  ]
}
OrderedArrayBlock mCheckoutXp = 
		Firely.orderedArrayBlock(FirelyConfig.Experiment.XP_CHECKOUT_ORDER)
			.addStep("one", () -> addOne())
			.addStep("two", () -> addTwo())
			.addStep("three", () -> addThree());

And you can control your A/B Tests from the Firebase Remote Config dashboard by changing the xp_mypage_order key.

three,one,two will then call addThree(), addOne(), addTwo(). You can use this to remotely control the order of lists.

Analytics

One of the highlights of Firebase is that everything is working together. In the documentation, Firebase proposes putting the values, manually, as a User Property:

String experiment1_variant = FirebaseRemoteConfig.getInstance().getString("experiment1");
   AppMeasurement.getInstance(context).setUserProperty("MyExperiment",experiment1_variant);

That's nice, but it does not fit our needs. Putting the property at the user level means it will be erased over time and we will lose the information. Instead, we prefer to tag all the events with all the experiments that have been applied at the time the event is triggered.

We added a method on Firely to help with this:

Firely.getAllPropsWithCurrentValue()

And this method is called each time we send an event and merged into the property list. Therefore we can track the configuration changes over time.

Build locally

You can build locally the project by:

  1. Building the plugin:

./gradlew :firely-plugin:publishToMaven -c plugin.gradle

  1. Create a firebase project for com.busbud.android.firely.sample and copy the google-service.json in the /firely-sample repository

  2. Build the project: ./gradlew assembleDebug

firely's People

Contributors

jeanbaptistemorin avatar cdnbacon avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.