JavaScript SDK
The Hyppot JavaScript SDK allows you to integrate A/B testing into your web applications. It works with any JavaScript framework or vanilla JavaScript and provides automatic impression tracking and easy conversion tracking.
Installation
Install the SDK using npm or yarn:
# Using npm
npm install hyppot
# Using yarn
yarn add hyppot
Or include it directly in your HTML:
<script src="https://unpkg.com/hyppot@latest/dist/index.umd.js"></script>
Basic Setup
Configure and initialize Hyppot in your application:
import { configureHyppot } from 'hyppot';
// Configure Hyppot
const { resolver, tracker } = configureHyppot((config) => {
config.prefix = '/hyppot'; // API endpoint prefix
});
// Initialize with user ID
const userId = 'user-123';
await resolver.initialize(userId);
Resolving Experiments
Once initialized, resolve experiments to get variant information:
// Resolve a specific experiment
const experiment = resolver.resolve('button-color-test');
if (experiment) {
// Get variable values
const buttonColor = experiment.getVariableValue('button-color');
const showFeature = experiment.getVariableValue('show-feature');
// Apply the variant
document.querySelector('.cta-button').style.backgroundColor = buttonColor;
if (showFeature) {
document.querySelector('.new-feature').style.display = 'block';
}
}
Tracking Conversions
Track user actions as conversions:
// Track a simple conversion
tracker.trackConversion({
conversionType: { type: 'button-click' },
user: userId,
eventDate: new Date()
});
// Track conversion with metrics
tracker.trackConversion({
conversionType: { type: 'purchase' },
user: userId,
eventDate: new Date(),
metrics: [
{ name: 'value', value: 99.99 },
{ name: 'product-id', value: 'product-123' },
{ name: 'category', value: 'electronics' }
]
});
Framework Integration
React
import { useEffect, useState } from 'react';
import { configureHyppot } from 'hyppot';
const { resolver, tracker } = configureHyppot((config) => {
config.prefix = '/hyppot';
});
function MyComponent({ userId }) {
const [experiment, setExperiment] = useState(null);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const initializeHyppot = async () => {
await resolver.initialize(userId);
setIsReady(true);
const exp = resolver.resolve('my-experiment');
setExperiment(exp);
};
initializeHyppot();
}, [userId]);
const handleClick = () => {
tracker.trackConversion({
conversionType: { type: 'button-click' },
user: userId,
eventDate: new Date()
});
};
if (!isReady) return <div>Loading...</div>;
const buttonColor = experiment?.getVariableValue('button-color') || 'blue';
return (
<button
style={{ backgroundColor: buttonColor }}
onClick={handleClick}
>
Click me!
</button>
);
}
Vue.js
<template>
<div>
<button
v-if="isReady"
:style="{ backgroundColor: buttonColor }"
@click="handleClick"
>
Click me!
</button>
<div v-else>Loading...</div>
</div>
</template>
<script>
import { configureHyppot } from 'hyppot';
const { resolver, tracker } = configureHyppot((config) => {
config.prefix = '/hyppot';
});
export default {
data() {
return {
isReady: false,
experiment: null
};
},
computed: {
buttonColor() {
return this.experiment?.getVariableValue('button-color') || 'blue';
}
},
async mounted() {
await resolver.initialize(this.userId);
this.isReady = true;
this.experiment = resolver.resolve('my-experiment');
},
methods: {
handleClick() {
tracker.trackConversion({
conversionType: { type: 'button-click' },
user: this.userId,
eventDate: new Date()
});
}
},
props: ['userId']
};
</script>
Angular
import { Component, OnInit } from '@angular/core';
import { configureHyppot } from 'hyppot';
const { resolver, tracker } = configureHyppot((config) => {
config.prefix = '/hyppot';
});
@Component({
selector: 'app-experiment',
template: `
<button
*ngIf="isReady"
[style.background-color]="buttonColor"
(click)="handleClick()"
>
Click me!
</button>
<div *ngIf="!isReady">Loading...</div>
`
})
export class ExperimentComponent implements OnInit {
isReady = false;
experiment: any = null;
userId = 'user-123';
async ngOnInit() {
await resolver.initialize(this.userId);
this.isReady = true;
this.experiment = resolver.resolve('my-experiment');
}
get buttonColor() {
return this.experiment?.getVariableValue('button-color') || 'blue';
}
handleClick() {
tracker.trackConversion({
conversionType: { type: 'button-click' },
user: this.userId,
eventDate: new Date()
});
}
}
Configuration Options
Basic Configuration
const { resolver, tracker } = configureHyppot((config) => {
// API endpoint prefix (default: '/hyppot')
config.prefix = '/hyppot';
// Session storage key (default: 'Hyppot_Ex')
config.experimentStatusKey = 'MyApp_Experiments';
// Automatic impression tracking (default: true)
config.autoTrackImpressions = true;
});
Advanced Configuration
const { resolver, tracker } = configureHyppot((config) => {
// Custom API endpoint
config.prefix = '/custom-experiments';
// Custom storage key to avoid conflicts
config.experimentStatusKey = 'MyApp_AB_Tests';
// Disable automatic impression tracking
config.autoTrackImpressions = false;
});
// Manual impression tracking when disabled
if (experiment) {
await tracker.trackImpression({
experimentId: 'my-experiment',
variantId: experiment.variantId,
user: userId,
eventDate: new Date()
});
}
Best Practices
1. Initialize Early
Initialize Hyppot as early as possible to avoid layout shifts:
// Initialize immediately when user is identified
const userId = await getCurrentUserId();
await resolver.initialize(userId);
2. Handle Loading States
Always handle the loading state while Hyppot initializes:
if (!resolver.isReady) {
// Show loading state or default variant
return <DefaultComponent />;
}
3. Graceful Degradation
Handle cases where experiments might not be available:
const experiment = resolver.resolve('my-experiment');
const featureEnabled = experiment?.getVariableValue('feature-enabled') ?? false;
// Always have a fallback
if (featureEnabled) {
showNewFeature();
} else {
showDefaultFeature();
}
4. Track Meaningful Conversions
Track conversions that matter to your business:
// Good: Track business-relevant actions
tracker.trackConversion({
conversionType: { type: 'purchase' },
user: userId,
eventDate: new Date(),
metrics: [
{ name: 'revenue', value: 29.99 },
{ name: 'items', value: 2 }
]
});
// Avoid: Tracking every minor interaction
Troubleshooting
Common Issues
Experiments not loading
- Check that the API endpoint is correct
- Verify CORS settings if serving from different domains
- Check browser console for network errors
Conversions not tracking
- Ensure conversion types are defined in the admin panel
- Check that the conversion type name matches exactly
- Verify the user ID is consistent between initialization and tracking
Session storage issues
- Check if the browser supports session storage
- Verify there are no storage quota issues
- Consider using a custom storage implementation
Debug Mode
Enable debug logging to troubleshoot issues:
const { resolver, tracker } = configureHyppot((config) => {
config.prefix = '/hyppot';
config.debug = true; // Enable debug logging
});
Performance Considerations
- Caching: Experiment data is cached in session storage
- Lazy Loading: Only load experiments when needed
- Minimal Bundle Size: The SDK is designed to be lightweight
- Async Operations: All network operations are asynchronous
Next Steps
- Create experiments - Learn how to set up A/B tests in the admin panel
- View results - Analyze your experiment performance
- Advanced configuration - Fine-tune your setup for production