c9-core/plugins/c9.ide.abtesting/abtesting.js

106 wiersze
4.0 KiB
JavaScript

/**
* Client-side support for A/B testing experiments.
*/
define(function(require, exports, module) {
"use strict";
main.consumes = ["Plugin", "info", "c9.analytics"];
main.provides = ["abtesting"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var plugin = new Plugin("Ajax.org", main.consumes);
var info = imports.info;
var analytics = imports["c9.analytics"];
var outplan = require("outplan");
var MS_PER_DAY = 1000 * 60 * 60 * 24;
var userId;
plugin.on("load", function() {
userId = info.getUser().id;
outplan.configure({
logFunction: function(e) {
var label = e.name + " - " + e.event;
analytics.track(label, { variation: e.params.name });
}
});
});
plugin.on("unload", function() {
userId = undefined;
});
function create(name, choices, options) {
var experiment = outplan.create(name, choices, options);
experiment.expose = expose.bind(null, name);
return experiment;
}
function expose(experimentName, overrideUserId, options) {
if (overrideUserId && typeof overrideUserId === "object")
return expose(experimentName, null, options);
return outplan.expose(experimentName, overrideUserId == null ? userId : overrideUserId, options);
}
function isUserCreatedAfter(experimentDate) {
var diffDays = (experimentDate - Date.now()) / MS_PER_DAY;
if (diffDays > 20) {
// Sanity check: new Date() takes zero-based month argument, one-based day argument
throw new Error("Passed a date far in the future to isUserCreatedAfter()");
}
return info.getUser().date_add > experimentDate;
}
/**
* Support for A/B testing experiments.
*/
plugin.freezePublicAPI({
/**
* Create a new experiment. Alias for require("outplan").create()
*
* @param {String} name
* The name of the experiment.
* @param {String[]|Object[]} choices
* A list of variations, e.g. ["A", "B"],
* or variation objects, e.g. [{ name: "A", color: "#AAA" }, { name: "B", color: "#BBB" }]
* @param {Object} [option]
* Options for the experiment. This may also include
* arguments for the distribution operator, e.g. weight.
* @param {Function} [options.operator]
* The distribution operator, e.g. outplan.WeightedChoice.
*/
create: create,
/**
* Get the selected variation of an experiment, and call the log function with
* an "expose" event to track its exposure.
*
* @param {String} name The experiment name.
* @param {Number} [userId] A unique identifier for the current user.
* @param {Object} [options] Options
* @param {Boolean} [options.log=true] Whether to log an "exposure event"
*/
expose: expose,
/**
* Helper to determine if the current user was created after the start of an experiment.
*
* @throws {Error} when a date in the future (~20 days from now) is passed.
* This error is thrown as a sanity check to make sure `new Date()`
* is called with a zero-based month argument (and a one-based day).
*
* @param {Date} experimentDate
*/
isUserCreatedAfter: isUserCreatedAfter,
});
register(null, {
"abtesting": plugin
});
}
});