Web adapters
Pluggable exposure adapters for Snowplow, GA4, GTM dataLayer, and Mojito migrations.
@fabricorg/experiments-web-adapters is a small add-on protected by a bundle-size
gate that provides ready-made onExposure handlers for common tracking systems. Use
when you want exposures to land in your existing analytics pipeline without
writing boilerplate.
Install
pnpm add @fabricorg/experiments-web @fabricorg/experiments-web-adaptersAdapters
snowplowAdapter(options?)
Sends self-describing exposure events to a Snowplow tracker.
import { createClient } from '@fabricorg/experiments-web';
import { snowplowAdapter } from '@fabricorg/experiments-web-adapters';
const client = createClient(manifest, {
manifestUrl,
subjectId,
onExposure: snowplowAdapter({
schema: 'iglu:io.fabric.experiments/exposure/jsonschema/1-0-0',
}),
});By default looks up globalThis.snowplow. Pass tracker to inject a
specific tracker function.
gaAdapter(options?)
Sends a GA4 event via gtag.
import { gaAdapter } from '@fabricorg/experiments-web-adapters';
const client = createClient(manifest, {
...,
onExposure: gaAdapter({ eventName: 'experiment_exposure' }),
});dataLayerAdapter(options?)
Pushes a fx_exposure event to window.dataLayer for GTM tags.
This is the default adapter wired up by the tag-loader bootstrap, so you only need to import this directly if you're using the programmatic SDK.
import { dataLayerAdapter } from '@fabricorg/experiments-web-adapters';
const onExposure = dataLayerAdapter();compose(...adapters)
Fan out a single exposure to multiple adapters with per-adapter try/catch isolation — one tracker error never breaks the chain:
import { compose, snowplowAdapter, gaAdapter } from '@fabricorg/experiments-web-adapters';
const onExposure = compose(snowplowAdapter(), gaAdapter());DataLayer event shape
| Field | Value |
|---|---|
event | fx_exposure |
fx_experiment_id | experiment id |
fx_variant_key | assigned variant key |
fx_subject_id | subject id used for assignment |
fx_manifest_version | manifest version that produced the assignment |
Mojito compatibility bridge
mojitoCompatibilityAdapter(existingAdapter, options?) lets an existing
Mojito storage adapter continue receiving its familiar callbacks while Fabric
serves and assigns experiments:
import { init } from '@fabricorg/experiments-web'
import { mojitoCompatibilityAdapter } from '@fabricorg/experiments-web-adapters'
const hooks = mojitoCompatibilityAdapter(Mojito.options.storageAdapter, {
experimentNames: { w12: 'Checkout hero' },
variantNames: { w12: { '0': 'Control', '1': 'Treatment' } },
})
await init({ manifestUrl, subjectId, ...hooks })Mappings:
| Fabric hook | Mojito callback |
|---|---|
| successful exposure | onExposure(test) |
| variant/shared-code failure | onRecipeFailure(test, message) |
| trigger rejection, exception, or selector timeout | onVeilTimeout(test, variantKey) |
The compatibility object contains options.id/name,
chosenRecipe.id/name, subjectId, and manifestVersion. Its fabric field
retains the complete typed Fabric record. This is an incremental migration
bridge, not an unsafe evaluator for arbitrary Mojito plugin code.