npm package: @sessionsight/split-testing
Description: A/B and split testing SDK for SessionSight.
Author: SessionSight
Latest version: 1.0.1

# @sessionsight/split-testing

Split testing SDK for SessionSight. Framework-agnostic, zero-flicker, server-driven.

## Installation

```bash
npm install @sessionsight/split-testing
```

Or use via script tag:

```html
<script src="https://cdn.sessionsight.com/split-testing.js"></script>
```

## Quick Start

```typescript
import SplitTesting from '@sessionsight/split-testing';

await SplitTesting.init({
  publicApiKey: 'sessionsight_pub_...',
  propertyId: 'your-property-id',
});

// ID-based test (component branching)
const checkout = SplitTesting.get('checkout-flow', 'control');
if (checkout === 'single-page') {
  renderSinglePageCheckout();
} else {
  renderDefaultCheckout();
}

// Text test (copy testing)
const headline = SplitTesting.get('hero-headline', 'Welcome');

// JSON test (structured data)
const layout = SplitTesting.get('pricing-layout', { columns: 3 });

// Track conversions
SplitTesting.trackConversion('signup-goal');
SplitTesting.trackConversion('purchase-goal', { value: 99.99, currency: 'USD' });
```

## Configuration

```typescript
await SplitTesting.init({
  // Required
  publicApiKey: 'sessionsight_pub_...',
  propertyId: 'your-property-id',

  // Optional
  apiUrl: 'https://api.sessionsight.com',  // Custom API URL
  visitorId: 'user-123',                    // Stable visitor ID (auto-generated if omitted)
  attributes: { plan: 'pro' },              // Visitor attributes for targeting
  bootstrap: { 'hero-headline': 1 },        // SSR: pre-resolved assignments
  antiFlicker: true,                         // Hide [data-ss-split] elements until ready
  staleTTL: 0,                              // ms before cached config triggers background refresh (default: 0)
  maxAge: 86400000,                          // ms before cached config is expired (default: 24h)
  onAssignment: (key, variation) => {},      // Callback when a variation is assigned
});
```

## Anti-Flicker

The SDK uses a three-tier approach to prevent content flashing:

1. **localStorage cache**: On repeat visits, cached assignments are used instantly (synchronous, no network call).
2. **SSR bootstrap**: Pass pre-evaluated assignments from the server. Zero network calls, zero flicker.
3. **Anti-flicker snippet**: Set `antiFlicker: true` to hide `[data-ss-split]` elements until assignments resolve.

### SSR Bootstrap Example

```typescript
// Server-side
import SplitTesting from '@sessionsight/split-testing';
await SplitTesting.init({ publicApiKey: 'sessionsight_pub_...', propertyId: '...' });
const bootstrap = SplitTesting.getAssignments();

// Client-side (pass bootstrap from server)
await SplitTesting.init({
  publicApiKey: 'sessionsight_pub_...',
  propertyId: '...',
  bootstrap,
});
```

## API

### `SplitTesting.init(config)`

Initialize the SDK. Fetches test configuration and assigns variations. Returns a Promise that resolves when ready.

### `SplitTesting.get(testKey, defaultValue, options?)`

Get the assigned value for a split test. Returns synchronously after init.

- **ID tests**: Returns the variation key string (e.g., `"control"`, `"variant-a"`)
- **Text tests**: Returns the variation text string
- **JSON tests**: Returns the parsed JSON object

Returns `defaultValue` if the test is not found or the visitor is not in the test.

### `SplitTesting.trackConversion(goalId, options?)`

Track a conversion event. The backend automatically attributes it to all relevant split tests the visitor is participating in.

### `SplitTesting.setAttributes(attrs)`

Update visitor attributes for targeting.

### `SplitTesting.getAssignments()`

Get all current assignments as `{ testKey: variationIndex }`. Use this for SSR bootstrap.

### `SplitTesting.refresh()`

Force refresh the test configuration from the server.

### `SplitTesting.clearCache()`

Clear locally cached test assignments and configuration. The next call to `get()` will use fresh data from the server after a `refresh()`.

### `SplitTesting.destroy()`

Clean up the SDK instance and flush pending events.

## Script Tag Usage

```html
<script src="https://cdn.sessionsight.com/split-testing.js"></script>
<script>
  SessionSightSplitTesting.init({
    publicApiKey: 'sessionsight_pub_...',
    propertyId: '...',
  }).then(function() {
    var headline = SessionSightSplitTesting.get('hero-headline', 'Welcome');
    document.getElementById('hero').textContent = headline;
  });
</script>
```