Skip to main content

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

1

Install Package

Add the SDK to your project via npm, yarn, or pnpm
2

Configure Analytics

REQUIRED: Set up experiment tracking with your analytics provider
3

Configure Device ID

REQUIRED: Set up device identification for A/B testing
4

Initialize SDK

Complete initialization with all required parameters
5

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:
@stringboot/[email protected]

Step 2: Configure Analytics (REQUIRED)

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:
  1. Track which variant they received
  2. Send this data to your analytics platform
  3. Allow you to correlate experiment variants with user behavior
  4. 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:
global.d.ts
interface Window {
  dataLayer: any[];
  gtag: (...args: any[]) => void;
}

Usage in Initialization

main.ts
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

  1. Go to AdminCustom definitions
  2. Create custom event parameters:
    • experiment_key
    • variant_id
    • variant_name
    • experiment_name
  3. View events in ReportsEventsstringboot_experiment_assigned
Pro Tip: Initialize your analytics platform BEFORE initializing Stringboot to ensure experiment assignments are tracked immediately.

Step 3: Configure Device ID (REQUIRED)

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

  • Auto-Generated UUID
  • Google Analytics Client ID
  • Custom User ID

Automatic Device ID (Default)

The SDK automatically generates and persists a UUID in localStorage:
main.ts
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

  1. First initialization: SDK generates a UUID v4
  2. UUID is saved to localStorage with key stringboot_device_id
  3. Subsequent initializations: SDK reads the same UUID from storage
  4. 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

  • TypeScript
  • JavaScript
src/main.ts
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
src/App.tsx
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

  • App Router
  • Pages Router
app/layout.tsx
'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:
.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

  • Vanilla JS
  • React
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:
  1. Go to ExperimentsCreate New Experiment
  2. Select a string key
  3. Create 2 variants (Control and Variant A)
  4. Set to RUNNING status
  5. 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();

Check Browser DevTools

Open browser DevTools (F12) and verify:
  1. Console: No errors, initialization success messages
  2. ApplicationLocal Storage: stringboot_device_id exists
  3. Network: Successful API calls to https://api.stringboot.com
  4. Console: Analytics events logged (if debug mode enabled)

Verify in Analytics Platform

  • Google Analytics 4
  • Mixpanel
  • Amplitude
  1. Go to ReportsRealtime
  2. Look for event: stringboot_experiment_assigned
  3. Check event parameters include:
    • experiment_key
    • variant_id
    • variant_name
    • experiment_name

Troubleshooting

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,
});
Check:
  1. Analytics platform initialized BEFORE Stringboot
  2. Analytics handler function is called (add console.log)
  3. Event name matches your platform’s requirements
  4. No errors in browser console
  5. Analytics SDK loaded correctly (check Network tab)
Debug:
const debugAnalyticsHandler = (experiments) => {
  console.log('🔍 Analytics handler called with:', experiments);
  // Your actual analytics code here
};
Cause: localStorage is being cleared or device ID not persisted.Check:
  1. Browser not in incognito/private mode
  2. localStorage not being cleared by another script
  3. 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,
});
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
Solution: Import the type from the SDK:
import type { ExperimentAssignment } from '@stringboot/web-sdk';

const analyticsHandler = (
  experiments: Record<string, ExperimentAssignment>
) => {
  // Your code
};
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