Guides · Integrations

A/B tests and flags

The built-in improve block puts different blocks per variant of an Obelism Improve A/B test or feature flag in any blocks field. How editors add one and how a site renders it.

2 min read

Sites built on Content can run their A/B tests and feature flags on Obelism Improve. Instead of hard-coding which content each variant shows, editors write each variant's content in Content, with the built-in improve block.

In the editor

Every blocks field takes it, whatever its allowed blocks, with no content type to create. Under Add block, choose A/B test or flag: it lists the tests and flags of the same environment in Improve. The block then has a tab per variant, each a list of blocks like the field it is in.

  • Each variant takes the blocks its list allows, so a test can only show what the page could show anyway. A variant can't hold another improve block.
  • It is offered while the organization has Improve enabled.
  • A draft may name a test that is still to come. Publishing checks the test or flag exists in that environment, by slug, and that every variant is one of its options. Promoting checks the same in the target, so sync the test there in Improve first.

In content

{
	"_uid": "b_…",
	"_type": "_improve",
	"kind": "test",
	"slug": "homepage-hero",
	"variants": {
		"control": [{ "_uid": "b_…", "_type": "hero", "heading": "Welcome" }],
		"variation": [{ "_uid": "b_…", "_type": "hero", "heading": "Hello there" }]
	}
}

kind is test or flag, slug the test's or flag's slug, and variants one list of blocks per option slug. A multi-variant test's options are its combinations (red-small). Agents list what a block can name, with each one's option slugs, with GET …/improve (listImproveSources).

On the site

The delivery API returns the block as stored, with each variant projected like any other blocks. Ask Improve's SDK for the visitor's option and render that variant:

import { isImproveBlock, pickImproveVariant } from '@obelism/content'

// `improve` is Improve's SDK (@obelism/improve-sdk), set up for the visitor.
const blocks = fields.body.flatMap((block) => {
	if (!isImproveBlock(block)) return [block]
	const option =
		block.kind === 'flag'
			? improve.getFlagValue(block.slug)
			: improve.getTestValue(block.slug)
	return pickImproveVariant(block, option)
})

Improve returns null when the test or flag isn't active or the visitor isn't in it. pickImproveVariant(block, option, fallback?) then takes the fallback option's variant, else the first one.

npx @obelism/content init writes an example of the block to content/examples/ while the organization has Improve on.

On this page

Marks in the margin

  • Note
  • Watch out
  • Updated

Scribes marked doubtful lines in the margin. That practice is called obelism.

Stuck on a step?