@suaveplan/ab-testing - Enterprise A/B testing and experimentation: deterministic FNV-1a bucketing, targeting rules, variant assignment, conversion tracking, and OTel instrumentation
Summary
Enterprise A/B testing and experimentation engine with deterministic FNV-1a bucketing, targeting rules, variant assignment, conversion tracking, result aggregation, and OpenTelemetry instrumentation.
Documentation tree
- bucketing — (no submodules)
- bucketing — (no submodules)
- experiment-manager — (no submodules)
- experiment-manager — (no submodules)
- providers — (no submodules)
- provider — (no submodules)
- results — (no submodules)
- results — (no submodules)
- targeting — (no submodules)
- targeting — (no submodules)
- common — Defines the shared TypeScript interfaces and type aliases that form the public contract of
@suaveplan/ab-testing. Eve… - schemas — Provides Zod validation schemas for all public input types in
@suaveplan/ab-testing. These schemas serve as the singl…
- schemas — Provides Zod validation schemas for all public input types in
@suaveplan/ab-testing. These schemas serve as the singl… - bucketing — (no submodules)- experiment-manager — (no submodules)- experiment-manager — (no submodules)- providers — (no submodules)- provider — (no submodules)- results — (no submodules)- results — (no submodules)- targeting — (no submodules)- targeting — (no submodules)- common — Defines the shared TypeScript interfaces and type aliases that form the public contract of
@suaveplan/ab-testing. Eve… - schemas — Provides Zod validation schemas for all public input types in
@suaveplan/ab-testing. These schemas serve as the singl… - bucketing — (no submodules)- experiment-manager — (no submodules)- experiment-manager — (no submodules)- providers — (no submodules)- provider — (no submodules)- results — (no submodules)- results — (no submodules)- targeting — (no submodules)- targeting — (no submodules)- common — Defines the shared TypeScript interfaces and type aliases that form the public contract of
@suaveplan/ab-testing. Eve… - schemas — Provides Zod validation schemas for all public input types in
@suaveplan/ab-testing. These schemas serve as the singl… - bucketing — (no submodules)- experiment-manager — (no submodules) - experiment-manager — (no submodules)- providers — (no submodules) - provider — (no submodules)- results — (no submodules) - results — (no submodules)- targeting — (no submodules) - targeting — (no submodules)- common — Defines the shared TypeScript interfaces and type aliases that form the public contract of
@suaveplan/ab-testing. Eve… - schemas — Provides Zod validation schemas for all public input types in
@suaveplan/ab-testing. These schemas serve as the singl…
Features
- Deterministic bucketing — FNV-1a 32-bit hash maps
(userId, experimentId)to a stable variant with configurable seed - Targeting rules — eight operators (
eq,neq,in,notIn,gt,lt,gte,lte) evaluated with AND logic - Sample rate — fraction-based inclusion gate via injectable RNG for deterministic testing
- Assignment caching — repeat
assign()calls for the same user always return the same variant - Conversion tracking — named metric events with numeric values, aggregated per variant
- Provider API — plug in external platforms via
ExperimentProviderfor forced assignments and event forwarding - OTel instrumentation —
ab.assignspan,ab.assignments_totalcounter,ab.conversions_totalcounter - Event bus — emits
ab:assignedandab:conversionevents on an injectableEventBusLike - Zod validation — all experiment definitions and metric events are validated at the boundary
- Injectable dependencies —
clock,rng,logger,eventBus,hashSeedfor deterministic testing
Installation
bun add @suaveplan/ab-testing
Quick Start
import { createExperimentManager } from '@suaveplan/ab-testing';
const manager = createExperimentManager();
manager.defineExperiment({
id: 'checkout-cta',
name: 'Checkout CTA Colour',
status: 'running',
variants: [
{ id: 'ctrl', name: 'Blue', weight: 1, isControl: true },
{ id: 'treat', name: 'Green', weight: 1 },
],
primaryMetric: 'checkout_started',
});
const assignment = manager.assign('checkout-cta', 'user-123');
if (assignment.inExperiment) {
console.log(`Variant: ${assignment.variantId}`);
}
// Track a conversion
manager.track('checkout-cta', 'user-123', { name: 'checkout_started' });
// Read results
const results = manager.getResults('checkout-cta');
console.log(`Conversion rate: ${results.variants[0]?.conversionRate}`);
Module Documentation
| Module | Description |
|---|---|
src/types/common.md |
Core domain type interfaces |
src/types/schemas.md |
Zod validation schemas |
src/core/experiment-manager/experiment-manager.md |
Main manager implementation |
src/bucketing/bucketing.md |
FNV-1a bucketing primitives |
src/targeting/targeting.md |
Targeting rule evaluation |
src/results/results.md |
Results aggregation |
src/providers/provider.md |
Built-in provider implementations |
Subpath Exports
import { createExperimentManager } from '@suaveplan/ab-testing';
import { bucketUser } from '@suaveplan/ab-testing/bucketing';
import { evaluateTargeting } from '@suaveplan/ab-testing/targeting';
import { computeResults } from '@suaveplan/ab-testing/results';
import { ForceVariantProvider, LoggingProvider } from '@suaveplan/ab-testing/providers';
import { AbTestingError, AB_CODES } from '@suaveplan/ab-testing/errors';