Skip to main content

JavaScript Client SDK

Шаг 1 - установка SDK

<script src="https://api.expf.ru/sigma.min.js"></script>

Шаг 2 - инициализация SDK

После установки вам нужно будет инициализировать SDK с помощью токена.

Токены предназначены для встраивания SDK в приложения. При необходимости вы можете отменить или создать новые проекты для SDK.

import Sigma from expf-sigma.js;

const token = <TOKEN>;
const sigma = new Sigma();

Шаг 3 - создание экземпляра класса Sigma

Создайте экземпляра класса Sigma, используйте метод init для инициализации sigma и передайте токен.

import Sigma from expf-sigma.js;

const token = <TOKEN>;
const sigma = new Sigma();

sigma.init({ token });

userData

userData – объект с пользовательскими данными. SDK целиком и полностью полагаются на предоставленные данные (методы по раздаче эксперимента, фича флагов и т.п.). Подробнее...

При инициализации SDK следует предоставлять объект userData и передавать как можно больше данных, чтобы воспользоваться преимуществами расширенных условий и конфигурации (например, проверки на уровне страны или ОС/браузера).

info

С версии 3.0.0 и выше, добавлена обработка поля split_by. В UserData можно передать поля userId, deviceId, profileId.

userData = {
userId: 'userId', // например, clientId из счетчика google analytics
profileId: 'profileId' // например, ID пользователя при регистрации
deviceId: 'deviceId' // например, ID устройства с которого зашел пользователь
}

Расчет соли и прочего происходит не по userId, а по полю, указанному в split_by.

Пример userData с подключением в sdk при инициализации

const userData = {
userId: 'userId',
email: 'example@mail.ru',
deviceCategory: 'mobile',
custom: {
new_user: true,
level: 2
}
}

sigma.init({ token, userData })

cacheTTL

cacheTTL - третий необязательный параметр. Number.

Метка времени (по умолчанию 10 секунд), указывает через какой промежуток времени обновить данные. Измеряется в секундах. Меньше 10 поставить нельзя, если указать число меньше 10, значение будет взято по умолчанию.

Пример подключения cacheTTL в sdk при инициализации

const cacheTTL: number = 60;
sigma.init({ token, userData, cacheTTL })

Шаг 4 - Работа с фича флагами

Метод checkFlag(...) принимает обязательный, строковый параметр - название 'фича-флага'. Он используется для проверки наличия определенной фичи в конфигурации экспериментов.

Если в конфигурации существует эксперимент с таким же названием 'фича-флага', метод назначает группу, проверяет условия этой группы и возвращает значение условия (или значение группы по умолчанию).

Если эксперимент с таким названием не найден в конфигурации, но переданное название 'фича-флага' существует, метод возвращает значение условия 'фича-флага' (или значение 'фича-флага' по умолчанию).

Если в конфигурации не найдено название 'фича-флага', метод вернет null.

Тип возвращаемого значения метода может быть string, bool, json или number.

Пример использования:

/** 
* @param {string} flagName
*/
const feature?: string | bool | number = await sigma.checkFlag('flagName');

Пример с типом данных при работе с документом

example type string

const titleFlag?: string = await sigma.checkFlag('titleFlag'); //'Привет'
document.querySelector('.h1').textContent = titleFlag || 'Hello'; // <h1>Привет</h1>

example type number

const priceFlag?: number = await sigma.checkFlag('priceFlag'); // 100
document.querySelector('.priceItem').textContent = 100 + priceFlag; <p>200</p>

example type bool

const isHidden?: bool = await sigma.checkFlag('isHiddenFlag'); // true
document.querySelector('.btn').dataset.hidden = isHidden; // <button data-hidden="true"></button>

Шаг 5 - Работа с экспериментами

Метод getExperiment(...) принимает обязательный, строковый параметр - идентификатор эксперимента.

Он проверяет наличие эксперимента и условия вхождения пользователя в эксперимент. Если эксперимент существует, но пользователь не попал в него вернет null. При выполнении условий пользователь будет назначен в группу эксперимента.

/**
* @param {string} exp_id
*/
await sigma.getExperiment('exp_id') // interface || null

При успешном определении группы эксперимента, методу getExperiment(...) будет доступен объект интерфейса для работы с параметрами и фича флагами.

Эксперименты с параметрами

Метод getParamValue(...) принимает обязательный, строковый параметр - название параметра эксперимента.

Возвращаемое значение string | number | boolean | json зависит от настройки эксперимента.

/**
* @param {string} exp_id
* @param {string} apple_pay
*/
const applePay?: string | number | boolean = await sigma.getExperiment('exp_id').then(res => res.getParamValue('apple_pay'));

Эксперименты с фича флагами

Метод getFeatureValue(...) принимает обязательный, строковый параметр - название фича-флага эксперимента.

Возвращаемое значение string | number | boolean | json зависит от настройки эксперимента.

/**
* @param {string} exp_id
* @param {string} apple_pay
*/
const applePay?: string | number | boolean = await sigma.getExperiment('exp_id').then(res => res.getFeatureValue('apple_pay'));

Эксперимент с переадресацией

info

JavaScript sdk v.1.2.0 и выше.

Проекты, в которых есть эксперименты с переадресацией.

Метод useSplitUrl() вызывается без аргументов:

  • проверяет условия попадания в эксперимент
  • назначает группу
  • получает адрес страницы пользователя(адрес, домен, путь, query-параметры)
  • проверяет условия правил в админ-панели
  • выполнит редирект или завершит работу

Параметры: url, pathname, query, domain - определяются в sdk автоматически. Можно переназначить любой из перечисленных параметров, передав в userData ключ с названием параметра и строковым значением

Пример:

const sigma = new Sigma();
const token = <TOKEN>;
const userData = {
userId: 'id',
url: 'url',
pathname: 'pathname',
query: 'query',
domain: 'domain'
}

sigma.init({ token, userData });
await sigma.useSplitUrl(); // redirect || null

Свойство эксперимента groupIndex

info

sdk v.3.1.0 и выше

groupIndex - свойство метода getExperiment(...), возвращает индекс группы в которую попал пользователь, если группа не назначена вернет null

Возвращаемое значение number | null

Пример:

const sigma = new Sigma();
const token = <TOKEN>;
const userData = {
userId: 'id'
}

sigma.init({ token, userData });

const experiment: Promise<void> = await sigma.getExperiment(...);
const groupIndex: number = experiment.groupIndex; // 0 (первая группа) || null

Шаг 6 - Получение списка экспериментов

Для оценки эффективности АБ теста, необходимо передавать в системы аналитики наименование эксперимента и вариант, который вернулся пользователю. Т.к. экспериментов много, то необходимо возвращать их все. Дальше разработчик может передавать полученную строку из кэша в системы аналитики как захочет. Метод getAllUserExperiments() вызывается без аргументов.

Возвращает строку(название и индекс), и запишет в кэш все эксперименты в которые попал пользователь. Если пользователь не попал ни в один эксперимент, вернет null

const allExperiments?: string = await sigma.getAllUserExperiments(); // param.0|exp_name_pay.1|has_layer.2|bg_link.3

Экземпляры класса sigma

В случае, когда нужно провести эксперименты с разными userId или подключить несколько проектов (токенов), можно создать новый экземпляр класса Sigma, и передать в метод init этого класса еще один userId или токен. Количество экземпляров класса Sigma не ограничено, важное условие при создании второго и последующих классов - в метод init добавить свойство с ключом postfix и любым строковым значением.

const sigma2 = new Sigma();
const token2 = 'token2';

sigma2.init({
token: token2,
userData: { userId: '123' },
postfix: 'test'
});

const allExperiments = await sigma2.getAllUserExperiments()

Полный пример кода

import Sigma from expf-sigma.js;

const sigma = new Sigma();
const token = 'token';
const userData = {
userId: 'userId',
email: 'example@mail.ru',
appVersion: '1.2.3',
ip: '70.123.12.84',
custom: {
cookieKey: "1",
example: false
},
}

sigma.init({
token,
userData,
}),

const applePay = await sigma.getExperiment('exp_name').then(res => res.getParamValue('apple_pay'));

if (applePay && applePay === true) {
applePay.textContent = `applePayVariant 1`;
} else if (applePay && applePay === false) {
applePay.textContent = `applePayVariant 2`;
}

const pay = await sigma.checkFlag('pay'));

if (pay && pay === 'masterCard') {
button.textContent = `masterCard`;
} else if (pay && pay === 'visa`) {
button.textContent = `visa`;
} else {
button.textContent = `cash`;
}

Целевая аудитория

info

Версия 2.0.1 и выше

Целевая аудитория – это глобальные условия эксперимента (общий фильтр), от которого дальше происходит деление пользователей на группы и проверка правила в них внутри (если они есть).
Порядок обработки эксперимента: Принудительный список -> Целевая аудитория -> Группа.

  • Целевая аудитория в лестнице приоритетов находится после проверки слоя.
    Если слой есть, то проверяется бакет, а затем Целевая аудитория.
  • Принудительные список пользователей игнорирует Целевую аудиторию и остается в первом приоритете.
  • Условия из ФФ эксперимента проверяются после глобальных условий.

Анти фликер

Для решения проблемы рендеринга, которое может быть связано с тем, что пользователь сначала видит контент до применения сплитов, а потом может увидеть другой после их расчетов. Можно применить механизм, который скрывает элемент пока модуль работает с данными. Этот механизм также решит проблему, если модуль по какой то причине не загрузился.

  • в <head> добавить скрипт, который навешивает класс скрывающий элемент (в примере sigma-preloader), и назначить время(мс) по истечению которого класс будет удален(в примере 5000)

    Пример:

    <style>
    .sigma-preloader {
    opacity: 0;
    }
    </style>

    <script>
    window.SIGMA_ERROR_TIMEOUT = 5000

    ((element, className, delay) => {
    element.className += ' ' + className;
    const removeClassName = () => {
    element.className = element.className.replace(RegExp(' ?' + className), '')
    };
    setTimeout(function () {
    removeClassName();
    }, delay);

    })(document.documentElement, 'sigma-preloader', SIGMA_ERROR_TIMEOUT);
    </script>
  • Следующий скрипт удалит класс скрывающий элемент('sigma-preloader') сразу по завершению работы sdk.
    В ином случае, будет ждать 5000мс после этого удалит класс 'sigma-preloader' и добавит ключ в sessionStorage который отключит конкретный эксперимент.

    const rootElement = document.documentElement;
    const removeClassName = () => {
    if (rootElement.classList.contains('sigma-preloader')) {
    rootElement.classList.remove('sigma-preloader');
    }
    };

    const sigmaToken = <TOKEN>;
    const sigmaUserData = { userId: <USER_ID> }

    async function sigmaPayload(sigmaToken, sigmaUserData) {
    if (sessionStorage.getItem('sigmaDisabledSplitUrl')) {
    removeClassName();
    return null;
    }

    const sigmaTimeStart = performance.now();
    const sigma = new Sigma();

    sigma.init({
    token: sigmaToken,
    userData: sigmaUserData,
    });

    await sigma.useSplitUrl();

    const sigmaTimePassed = performance.now() - sigmaTimeStart;

    if (sigmaTimePassed > SIGMA_ERROR_TIMEOUT) {
    sessionStorage.setItem('sigmaDisabledSplitUrl', 1);
    }

    removeClassName();
    }

    sigmaPayload(sigmaToken, sigmaUserData);

Пример подключения sdk для ECMAScript 2017(es5)

  var token = <TOKEN>;
var clientId = '1';

var start = new Promise(
function (resolve, reject) {
if (window.Sigma) {
var sigma = new Sigma();
var userData = {
userId: clientId
};
sigma.init({ token: token, userData: userData });
var exp = sigma.getExperiment('exp');
resolve(exp);
}else {
var reason = new Error("s haven't initialized");
reject(reason);
}

}
);

var abStart = function () {
start
.then(function (res) {
var resultExp = res.getFeatureValue('test');
console.log(resultExp);
})
.catch(function (error) {
console.log(error.message);
});
};

abStart();