@gemx-dev/experiment
v3.5.17
Published
AB Testing Section Block Components for multiple frameworks with tracking
Maintainers
Readme
@gemx-dev/experiment (develop)
The most developer-friendly A/B testing library for modern web applications
A powerful, framework-agnostic A/B testing library that works seamlessly with React, Vue, Angular, and vanilla JavaScript. Built with TypeScript for type safety and designed for optimal developer experience.
✨ Features
- 🚀 Zero Configuration - Start testing in minutes with our intuitive API
- 🛡️ Type-Safe - Full TypeScript support with intelligent autocompletion
- 🌐 Framework Agnostic - Works with React, Vue, Angular, or vanilla JavaScript
- 📊 Built-in Analytics - Seamless integration with Google Analytics, Mixpanel, and more
- 🎯 Smart Targeting - Device, location, and custom targeting rules
- 🔧 Developer Experience - Built-in debugging, error handling, and clean APIs
- 📦 Lightweight - Minimal bundle size with tree-shaking support
- 🔄 Persistent - User assignments persist across sessions
- 🎨 Flexible - Support for weighted variants and custom metadata
📦 Installation
# npm
npm install @gemx-dev/experiment
# yarn
yarn add @gemx-dev/experiment
# pnpm
pnpm add @gemx-dev/experiment🚀 Quick Start
React
import { GxExperimentWrapper, getVariant } from '@gemx-dev/experiment/react';
const variant = getVariant({
experimentId: 'hero-test',
variants: [
{ name: 'A', weight: 0.5 },
{ name: 'B', weight: 0.5 },
],
});
function HeroSection() {
return (
<GxExperimentWrapper variant={variant} experimentId="hero-test" onTrack={(event, data) => console.log(event, data)}>
<div data-variant="A">
<h1>Welcome to our amazing product!</h1>
<button>Get Started</button>
</div>
<div data-variant="B">
<h1>Discover something incredible!</h1>
<button>Try Now</button>
</div>
</GxExperimentWrapper>
);
}Vue
<template>
<GxExperimentWrapper :variant="variant" experiment-id="hero-test" @track="handleTrack">
<div data-variant="A">
<h1>Welcome to our amazing product!</h1>
<button>Get Started</button>
</div>
<div data-variant="B">
<h1>Discover something incredible!</h1>
<button>Try Now</button>
</div>
</GxExperimentWrapper>
</template>
<script setup lang="ts">
import { getVariant } from '@gemx-dev/experiment';
import { GxExperimentWrapper } from '@gemx-dev/experiment/vue';
import { ref } from 'vue';
const variant = ref(
getVariant({
experimentId: 'hero-test',
variants: [
{ name: 'A', weight: 0.5 },
{ name: 'B', weight: 0.5 },
],
}),
);
const handleTrack = (event: string, data: any) => {
console.log(`Event: ${event}`, data);
};
</script>Vanilla JavaScript / HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@gemx-dev/experiment/dist/index.js"></script>
</head>
<body>
<gx-experiment-wrapper variant="A" experiment-id="hero-test">
<div data-variant="A">
<h1>Welcome to our amazing product!</h1>
<button>Get Started</button>
</div>
<div data-variant="B">
<h1>Discover something incredible!</h1>
<button>Try Now</button>
</div>
</gx-experiment-wrapper>
</body>
</html>📚 API Reference
Core Functions
getVariant(config: ExperimentConfig): string
Determines which variant a user should see based on the experiment configuration.
const variant = getVariant({
experimentId: 'my-experiment',
variants: [
{ name: 'control', weight: 0.5 },
{ name: 'treatment', weight: 0.5 },
],
weights: [0.5, 0.5], // Optional: override individual variant weights
description: 'Testing new button color',
targeting: {
trafficPercentage: 0.1, // 10% of traffic
deviceType: 'mobile',
country: 'US',
},
});React Components
GxExperimentWrapper
A React wrapper component that handles variant assignment and tracking.
interface ExperimentWrapperProps {
config: ExperimentConfig;
trackingEndpoint?: string;
gaTracking?: boolean;
autoTrack?: boolean;
fallbackVariant?: string;
debug?: boolean;
loading?: boolean;
onTrack?: (event: string, data: TrackingEvent) => void;
onVariantAssigned?: (variant: string, experimentId: string) => void;
onError?: (error: string, experimentId?: string) => void;
children: React.ReactNode;
}Vue Components
GxExperimentWrapper
A Vue wrapper component with similar functionality to the React version.
<GxExperimentWrapper :variant="variant" experiment-id="my-experiment" :ga-tracking="true" :debug="true" @track="handleTrack" @variant-assigned="handleVariantAssigned" @error="handleError">
<!-- Your variants here -->
</GxExperimentWrapper>Web Components
<gx-experiment-wrapper>
A custom HTML element that works in any framework or vanilla JavaScript.
<gx-experiment-wrapper variant="A" experiment-id="my-experiment" ga-tracking="true" debug="true">
<div data-variant="A">Variant A</div>
<div data-variant="B">Variant B</div>
</gx-experiment-wrapper>TypeScript Interfaces
ExperimentConfig
interface ExperimentConfig {
experimentId: string;
variants: Variant[];
weights?: number[];
description?: string;
targeting?: TargetingConfig;
metadata?: Record<string, any>;
}
interface Variant {
name: string;
weight?: number;
component?: any;
metadata?: Record<string, any>;
}
interface TargetingConfig {
trafficPercentage?: number;
deviceType?: 'mobile' | 'desktop' | 'tablet';
country?: string;
userSegment?: string;
customRules?: Record<string, any>;
}TrackingEvent
interface TrackingEvent {
event: string;
experimentId: string;
variant: string;
timestamp: number;
sessionId?: string;
userId?: string;
customData?: Record<string, any>;
}🎯 Advanced Usage
Custom Targeting
const variant = getVariant({
experimentId: 'premium-feature-test',
variants: [{ name: 'control' }, { name: 'premium' }],
targeting: {
trafficPercentage: 0.2, // 20% of users
deviceType: 'desktop',
country: 'US',
userSegment: 'premium',
customRules: {
userAge: { min: 25, max: 65 },
subscriptionTier: ['pro', 'enterprise'],
},
},
});Analytics Integration
<GxExperimentWrapper
config={experimentConfig}
gaTracking={true}
trackingEndpoint="https://api.yourapp.com/analytics"
onTrack={(event, data) => {
// Custom analytics
analytics.track(event, data);
// Google Analytics
gtag('event', event, {
experiment_id: data.experimentId,
variant: data.variant,
custom_parameter: data.customData,
});
}}
>
{/* Your variants */}
</GxExperimentWrapper>Debug Mode
<GxExperimentWrapper
config={experimentConfig}
debug={true}
onVariantAssigned={(variant, experimentId) => {
console.log(`User assigned to variant ${variant} in experiment ${experimentId}`);
}}
onError={(error, experimentId) => {
console.error(`Experiment error: ${error}`, experimentId);
}}
>
{/* Your variants */}
</GxExperimentWrapper>Programmatic Control
// Check if user is in a specific variant
const isVariant = (targetVariant: string) => {
return getVariant(experimentConfig) === targetVariant;
};
// Reassign variant (useful for testing)
const reassignVariant = () => {
localStorage.removeItem(`gx_experiment_${experimentId}`);
// Next page load will reassign
};
// Get experiment status
const getExperimentStatus = () => {
return {
experimentId,
variant: getVariant(experimentConfig),
isInitialized: true,
sessionId: getSessionId(),
userId: getUserId(),
};
};🧪 Testing
Unit Tests
npm testIntegration Tests
npm run test:integrationDemo Applications
# Start all demos
npm run demo
# React demo only
npm run demo:react
# Vue demo only
npm run demo:vue
# HTML demo
npm run demo:html📊 Analytics & Tracking
Built-in Events
experiment_viewed- When a user sees an experimentvariant_assigned- When a variant is assigned to a userexperiment_error- When an error occurs
Custom Events
<GxExperimentWrapper
config={experimentConfig}
onTrack={(event, data) => {
// Track custom events
if (event === 'button_clicked') {
analytics.track('Button Clicked', {
experiment: data.experimentId,
variant: data.variant,
button_text: data.customData?.buttonText,
});
}
}}
>
<div data-variant="A">
<button onClick={() => track('button_clicked', { buttonText: 'Get Started' })}>Get Started</button>
</div>
</GxExperimentWrapper>🔧 Configuration
Environment Variables
# Optional: Custom tracking endpoint
GX_TRACKING_ENDPOINT=https://api.yourapp.com/analytics
# Optional: Enable debug mode
GX_DEBUG=true
# Optional: Default experiment configuration
GX_DEFAULT_CONFIG=./experiments.jsonBuild Configuration
The library supports multiple build targets:
- ES Modules (
dist/index.mjs) - For modern bundlers - CommonJS (
dist/index.js) - For Node.js and older bundlers - TypeScript (
dist/index.d.ts) - For type definitions
Development Setup
# Clone the repository
git clone https://github.com/ducky0209/gemx-package.git
cd gemx-package
# Install dependencies
npm install
# Build the library
npm run build
# Run tests
npm test
# Start development server
npm run demo:reactProject Structure
src/
├── adapters/ # Framework-specific adapters
│ ├── react/ # React components
│ └── vue/ # Vue components
├── components/ # Web components
├── core/ # Core A/B testing logic
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
└── tracking/ # Analytics and tracking🆘 Support
Made with ❤️ by the GemX team
