LogSure

A/B tests and feature flags

The Lab runs A/B experiments and feature flags without cookies: your page asks for a variant or a flag's value, works it out itself, and LogSure counts who saw which and who reached the goal.

Make an experiment

Admins make experiments in the console's Lab, for one app:

An experiment starts as a draft. Start it to begin counting, and stop it when you are done. The key and the variants are fixed once it has started.

Ask for the variant

logsure.variant('checkout-button', { id: user.id }).then((v) => {
  if (v === 'green') showGreenButton();
  // null while the experiment is not running: show your default
});

From a back-end

Send the same with the app's server key: $exposure with props: { exp, variant, unit }, and your goal events with the same unit, an opaque id of your own. To assign like the tracker does, take FNV-1a 32 of key + ":" + id as a share of 232 and walk the cumulative weights.

curl -sS -X POST 'https://logsure.example.com/_care/event' \
  -H "authorization: Bearer $LOGSURE_KEY" -H 'content-type: application/json' \
  --data '{"app":"example-shop","name":"$exposure",
           "props":{"exp":"checkout-button","variant":"green","unit":"u_1042"}}'

Read the results

An experiment's results: each variant's visitors, conversions and rate, the uplift with its 95% interval, the p-value and the chance to beat control, with a guardrail below.

The same is in the API (lab), the iPhone and Mac apps, the terminal (:lab) and over MCP (list_experiments, get_experiment_results, and with settings access create_experiment, update_experiment, start_experiment, stop_experiment).

Feature flags

A boolean flag: how it decides in order, a test box where a score of 30 gets On, and the tracker snippet.

Admins make flags under Lab › Flags. A new flag is off until you switch it on.

How a flag decides

  1. Off: the default.
  2. Rules, in order: the first whose conditions match (all or any) serves its value. Conditions test the attributes you pass, and id: equals, not equals, in a list, not in a list, contains, starts with, ends with, greater or less than, semver comparisons, and exists. An attribute you didn't pass matches no condition, negated ones included.
  3. Without the score (the default for a new flag): the fallthrough value. A score you pass is ignored.
  4. With "use score" on: the first range holding the score serves its value. Ranges include both ends: on for scores 10 to 50 means 9 → off, 10 → on, 50 → on, 51 → off. No score, or a score in no range, serves the default.

The score is a number from 0 to 100 that your app chooses, with whatever meaning you like: engagement, a plan tier, a device class, or a random bucket of your own. LogSure never computes or interprets one. Values outside 0 to 100 are clamped, and anything but a number counts as no score.

In the page

<script defer data-app="example-shop" data-flags="true" src="/_care/script.js"></script>

await logsure.flagsReady();
if (logsure.flag('new-checkout', { id: user.id, attrs: { plan: user.plan, version: '2.4.1' }, fallback: false })) {
  showNewCheckout();
}
const headline = logsure.flag('pricing-copy', { score: user.engagement, fallback: 'Start now' }); // a text flag

On a server

Fetch /_care/flags with the server key and evaluate it the same way, or ask LogSure to:

curl -sS -X POST 'https://logsure.example.com/_care/flags/evaluate' \
  -H "authorization: Bearer $LOGSURE_KEY" -H 'content-type: application/json' \
  --data '{"id":"u_1042","score":30,"attrs":{"plan":"pro"}}'

Nothing sent there is stored.

Measuring a flag

An experiment can measure a flag: pick it under Measure a flag in the experiment editor, and the experiment takes the flag's values as its variants and counts its $flag events as exposures. The flag stays fixed while the experiment runs.

Flags are in the API (lab) and over MCP: list_flags and get_flag (with its history), and with settings access create_flag, update_flag, toggle_flag and set_flag_rollout.