Overview
This guide walks you through installing and configuring the Stringboot Web SDK in your web application with complete A/B testing support , including required analytics integration and device ID configuration.
What You’ll Set Up
Install Package
Add the SDK to your project via npm, yarn, or pnpm
Configure Analytics
REQUIRED : Set up experiment tracking with your analytics provider
Configure Device ID
REQUIRED : Set up device identification for A/B testing
Initialize SDK
Complete initialization with all required parameters
Verify Setup
Test that strings, translations, and experiments work correctly
SDK Version: 1.0.5 • Size: 6.6 kB gzipped • Dependencies: Zero
Step 1: Install the SDK
NPM
npm install @stringboot/web-sdk
Yarn
yarn add @stringboot/web-sdk
PNPM
pnpm add @stringboot/web-sdk
Verify Installation
npm list @stringboot/web-sdk
You should see:
Analytics integration is REQUIRED for A/B testing and experiment tracking. The SDK needs to send experiment assignments to your analytics platform for proper tracking and analysis.
Why Analytics Integration is Required
When a user is assigned to an experiment variant, the SDK must:
Track which variant they received
Send this data to your analytics platform
Allow you to correlate experiment variants with user behavior
Enable proper A/B test analysis and decision-making
Choose Your Analytics Provider
Google Analytics 4
Mixpanel
Amplitude
Custom Analytics
Install Google Analytics 4 npm install @google-analytics/gtag
Create Analytics Handler src/analytics/googleAnalytics.ts
import type { ExperimentAssignment } from '@stringboot/web-sdk' ;
// Initialize Google Analytics
export function initializeGA4 ( measurementId : string ) {
// Load gtag.js
const script = document . createElement ( 'script' );
script . async = true ;
script . src = `https://www.googletagmanager.com/gtag/js?id= ${ measurementId } ` ;
document . head . appendChild ( script );
// Configure gtag
window . dataLayer = window . dataLayer || [];
function gtag ( ... args : any []) {
window . dataLayer . push ( args );
}
gtag ( 'js' , new Date ());
gtag ( 'config' , measurementId );
}
// Analytics handler for Stringboot
export const googleAnalyticsHandler = (
experiments : Record < string , ExperimentAssignment >
) => {
Object . entries ( experiments ). forEach (([ key , assignment ]) => {
// Track experiment assignment as custom dimension
if ( window . gtag ) {
window . gtag ( 'event' , 'stringboot_experiment_assigned' , {
experiment_key: key ,
variant_id: assignment . variantId ,
variant_name: assignment . variantName ,
experiment_name: assignment . experimentName ,
});
// Set user property for segmentation
window . gtag ( 'set' , 'user_properties' , {
[ `stringboot_exp_ ${ key } ` ]: assignment . variantName ,
});
}
});
};
TypeScript Global Types Add to src/types/global.d.ts: interface Window {
dataLayer : any [];
gtag : ( ... args : any []) => void ;
}
Usage in Initialization import StringBoot from '@stringboot/web-sdk' ;
import { initializeGA4 , googleAnalyticsHandler } from './analytics/googleAnalytics' ;
// Initialize GA4 first
initializeGA4 ( 'G-XXXXXXXXXX' );
// Initialize Stringboot with analytics
await StringBoot . initialize ({
apiToken: 'YOUR_API_TOKEN' ,
baseUrl: 'https://api.stringboot.com' ,
defaultLanguage: 'en' ,
analyticsHandler: googleAnalyticsHandler ,
});
View Data in GA4
Go to Admin → Custom definitions
Create custom event parameters:
experiment_key
variant_id
variant_name
experiment_name
View events in Reports → Events → stringboot_experiment_assigned
Pro Tip : Initialize your analytics platform BEFORE initializing Stringboot to ensure experiment assignments are tracked immediately.
Device ID is REQUIRED for A/B testing. The SDK uses the device ID to consistently assign users to experiment variants. Without it, users may see different variants on each session.
Why Device ID is Required
The device ID ensures:
Consistent variant assignment : Same user always sees the same variant
Accurate experiment results : Prevents users from seeing multiple variants
Cross-session tracking : User gets same experience across sessions
Proper analytics correlation : Links experiment data with user behavior
Choose Your Device ID Strategy
Automatic Device ID (Default) The SDK automatically generates and persists a UUID in localStorage: import StringBoot from '@stringboot/web-sdk' ;
await StringBoot . initialize ({
apiToken: 'YOUR_API_TOKEN' ,
baseUrl: 'https://api.stringboot.com' ,
defaultLanguage: 'en' ,
analyticsHandler: yourAnalyticsHandler ,
// providedDeviceId: undefined // Auto-generate (default)
});
// Retrieve the generated device ID
const deviceId = await StringBoot . getDeviceId ();
console . log ( 'Device ID:' , deviceId );
// Output: "550e8400-e29b-41d4-a716-446655440000"
How It Works
First initialization: SDK generates a UUID v4
UUID is saved to localStorage with key stringboot_device_id
Subsequent initializations: SDK reads the same UUID from storage
Persists across sessions, page reloads, and browser restarts
Best For
Simple applications without existing user authentication
MVP or prototyping
When you don’t need cross-device consistency
Auto-generated device IDs are browser-specific . The same user on different browsers/devices will have different IDs.
Recommendation : Use auto-generated UUID for simple apps, GA Client ID if using Google Analytics, or custom user ID for authenticated apps with cross-device needs.
Step 4: Complete Initialization
Now that you have analytics and device ID configured, let’s do the complete initialization.
Vanilla JavaScript/TypeScript
import StringBoot from '@stringboot/web-sdk' ;
import type { StringBootConfig } from '@stringboot/web-sdk' ;
import { initializeGA4 , googleAnalyticsHandler } from './analytics/googleAnalytics' ;
async function initializeApp () {
try {
// 1. Initialize analytics first
initializeGA4 ( 'G-XXXXXXXXXX' );
// 2. Configure Stringboot
const config : StringBootConfig = {
apiToken: import . meta . env . VITE_STRINGBOOT_API_TOKEN ,
baseUrl: 'https://api.stringboot.com' ,
defaultLanguage: 'en' ,
cacheSize: 1000 ,
debug: import . meta . env . DEV ,
// REQUIRED for A/B testing
analyticsHandler: googleAnalyticsHandler ,
// Optional: Use custom device ID
// providedDeviceId: await getCustomDeviceId(),
};
// 3. Initialize Stringboot
await StringBoot . initialize ( config );
console . log ( '✅ Stringboot initialized successfully' );
console . log ( 'Device ID:' , await StringBoot . getDeviceId ());
console . log ( 'Current language:' , StringBoot . getCurrentLanguage ());
} catch ( error ) {
console . error ( '❌ Stringboot initialization failed:' , error );
throw error ;
}
}
// Initialize on app load
initializeApp ();
React
React + TypeScript
React + JavaScript
import { useEffect } from 'react' ;
import { useStringBoot } from '@stringboot/web-sdk/react' ;
import { initializeGA4 , googleAnalyticsHandler } from './analytics/googleAnalytics' ;
function App () {
// Initialize GA4 before Stringboot
useEffect (() => {
initializeGA4 ( 'G-XXXXXXXXXX' );
}, []);
// Initialize Stringboot with analytics
const { initialized , error } = useStringBoot ({
apiToken: import . meta . env . VITE_STRINGBOOT_API_TOKEN ,
baseUrl: 'https://api.stringboot.com' ,
defaultLanguage: 'en' ,
cacheSize: 1000 ,
debug: import . meta . env . DEV ,
// REQUIRED for A/B testing
analyticsHandler: googleAnalyticsHandler ,
});
if ( error ) {
return (
< div className = "error" >
< h1 > Initialization Error </ h1 >
< p > { error } </ p >
</ div >
);
}
if ( ! initialized ) {
return (
< div className = "loading" >
< p > Loading Stringboot... </ p >
</ div >
);
}
return < YourApp /> ;
}
export default App ;
Next.js
'use client' ;
import { useEffect } from 'react' ;
import { useStringBoot } from '@stringboot/web-sdk/react' ;
import { initializeGA4 , googleAnalyticsHandler } from '@/lib/analytics/googleAnalytics' ;
export default function RootLayout ({
children ,
} : {
children : React . ReactNode ;
}) {
// Initialize GA4
useEffect (() => {
initializeGA4 ( process . env . NEXT_PUBLIC_GA_MEASUREMENT_ID ! );
}, []);
// Initialize Stringboot
const { initialized , error } = useStringBoot ({
apiToken: process . env . NEXT_PUBLIC_STRINGBOOT_API_TOKEN ! ,
baseUrl: 'https://api.stringboot.com' ,
defaultLanguage: 'en' ,
analyticsHandler: googleAnalyticsHandler ,
});
if ( error ) {
return < html >< body > Error: { error } </ body ></ html > ;
}
if ( ! initialized ) {
return < html >< body > Loading... </ body ></ html > ;
}
return (
< html lang = "en" >
< body > { children } </ body >
</ html >
);
}
Environment Variables : Never commit API tokens to version control. Use .env.local for Next.js or .env for Vite/Create React App, and add them to .gitignore.
Environment Variables Setup
Vite
Next.js
Create React App
Create .env.local: VITE_STRINGBOOT_API_TOKEN = your_token_here
VITE_GA_MEASUREMENT_ID = G-XXXXXXXXXX
VITE_STRINGBOOT_BASE_URL = https://api.stringboot.com
Access in code: import . meta . env . VITE_STRINGBOOT_API_TOKEN
import . meta . env . VITE_GA_MEASUREMENT_ID
Step 5: Verify Installation
Test Basic String Retrieval
import StringBoot from '@stringboot/web-sdk' ;
async function testStringboot () {
try {
// Get a string
const welcome = await StringBoot . get ( 'welcome_message' );
console . log ( '✅ String retrieved:' , welcome );
// Get device ID
const deviceId = await StringBoot . getDeviceId ();
console . log ( '✅ Device ID:' , deviceId );
// Get current language
const lang = StringBoot . getCurrentLanguage ();
console . log ( '✅ Current language:' , lang );
// Get available languages
const languages = await StringBoot . getActiveLanguages ();
console . log ( '✅ Available languages:' , languages );
} catch ( error ) {
console . error ( '❌ Test failed:' , error );
}
}
testStringboot ();
Test Analytics Integration
Create a test experiment in the Stringboot Dashboard :
Go to Experiments → Create New Experiment
Select a string key
Create 2 variants (Control and Variant A)
Set to RUNNING status
Save the experiment
Then verify analytics tracking:
import StringBoot from '@stringboot/web-sdk' ;
async function testExperimentTracking () {
// Force sync to get latest experiments
await StringBoot . sync ();
// Get a string that's part of an experiment
const text = await StringBoot . get ( 'experiment_string_key' );
console . log ( '✅ Got string:' , text );
// Check your analytics platform (GA4, Mixpanel, Amplitude)
// You should see event: "stringboot_experiment_assigned"
// With properties: experiment_key, variant_id, variant_name
}
testExperimentTracking ();
Open browser DevTools (F12) and verify:
Console : No errors, initialization success messages
Application → Local Storage : stringboot_device_id exists
Network : Successful API calls to https://api.stringboot.com
Console : Analytics events logged (if debug mode enabled)
Google Analytics 4
Mixpanel
Amplitude
Go to Reports → Realtime
Look for event: stringboot_experiment_assigned
Check event parameters include:
experiment_key
variant_id
variant_name
experiment_name
Troubleshooting
Initialization fails with 'Analytics handler required'
Cause: The analyticsHandler parameter is missing or undefined.Solution: // ❌ Wrong
await StringBoot . initialize ({
apiToken: 'token' ,
baseUrl: 'https://api.stringboot.com' ,
// Missing analyticsHandler
});
// ✅ Correct
await StringBoot . initialize ({
apiToken: 'token' ,
baseUrl: 'https://api.stringboot.com' ,
analyticsHandler: yourAnalyticsHandler ,
});
Analytics events not appearing
Check:
Analytics platform initialized BEFORE Stringboot
Analytics handler function is called (add console.log)
Event name matches your platform’s requirements
No errors in browser console
Analytics SDK loaded correctly (check Network tab)
Debug: const debugAnalyticsHandler = ( experiments ) => {
console . log ( '🔍 Analytics handler called with:' , experiments );
// Your actual analytics code here
};
Device ID changes on every session
Cause: localStorage is being cleared or device ID not persisted.Check:
Browser not in incognito/private mode
localStorage not being cleared by another script
providedDeviceId parameter consistent across sessions
Solution: // Provide a custom device ID that you manage
const deviceId = localStorage . getItem ( 'my_device_id' ) ||
(() => {
const id = crypto . randomUUID ();
localStorage . setItem ( 'my_device_id' , id );
return id ;
})();
await StringBoot . initialize ({
apiToken: 'token' ,
baseUrl: 'https://api.stringboot.com' ,
providedDeviceId: deviceId ,
analyticsHandler: yourAnalyticsHandler ,
});
Environment variables not loading
Vite:
Use VITE_ prefix
Access via import.meta.env.VITE_VAR_NAME
Restart dev server after changing .env.local
Next.js:
Use NEXT_PUBLIC_ prefix for client-side
Access via process.env.NEXT_PUBLIC_VAR_NAME
Restart dev server after changing .env.local
Create React App:
Use REACT_APP_ prefix
Access via process.env.REACT_APP_VAR_NAME
Restart dev server after changing .env
TypeScript errors for ExperimentAssignment type
Solution: Import the type from the SDK:import type { ExperimentAssignment } from '@stringboot/web-sdk' ;
const analyticsHandler = (
experiments : Record < string , ExperimentAssignment >
) => {
// Your code
};
React hooks not updating when language changes
Cause: Hook not subscribed to language changes.Solution: Use useLanguage hook or useString which auto-updates:// ❌ Wrong - doesn't update
const [ text , setText ] = useState ( '' );
useEffect (() => {
StringBoot . get ( 'key' ). then ( setText );
}, []);
// ✅ Correct - auto-updates
const text = useString ( 'key' );
Next Steps
Now that you have Stringboot fully installed with analytics and device ID configured, explore the three core features:
Additional Resources
Configuration Reference
Complete StringBootConfig Interface
interface StringBootConfig {
// REQUIRED: Your Stringboot API token
apiToken : string ;
// Optional: API base URL (default: https://api.stringboot.com)
baseUrl ?: string ;
// Optional: Default language code (default: 'en')
defaultLanguage ?: string ;
// Optional: Memory cache size (default: 1000)
cacheSize ?: number ;
// Optional: Enable debug logging (default: false)
debug ?: boolean ;
// REQUIRED for A/B testing: Analytics handler function
analyticsHandler ?: ( experiments : Record < string , ExperimentAssignment >) => void ;
// REQUIRED for A/B testing: Device ID for consistent variant assignment
// If not provided, SDK auto-generates and persists a UUID
providedDeviceId ?: string ;
}
ExperimentAssignment Interface
interface ExperimentAssignment {
// Unique identifier for the experiment
experimentId : string ;
// Display name of the experiment
experimentName : string ;
// Unique identifier for the assigned variant
variantId : string ;
// Display name of the variant (e.g., "Control", "Variant A")
variantName : string ;
// The string value for this variant
value : string ;
}
Support