API Reference

Complete reference for every method on the CADENCE SDK.

Constructor

typescript
import { CadenceClient } from '@cadence/sdk'

const cadence = new CadenceClient({
  sdkKey: 'your_sdk_key',
  userId: 'optional_user_id',
  apiUrl: 'https://your-cadence-instance.com',
  attributes: { plan: 'pro' },
})

Configuration options

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | sdkKey | string | Yes | — | Your project's SDK key | | userId | string | No | Auto-generated | Stable user identifier. Persisted in localStorage if not provided | | apiUrl | string | No | window.location.origin | Base URL for the CADENCE API | | attributes | Record<string, unknown> | No | {} | User attributes for targeting rules |

Methods

ready()

typescript
await cadence.ready()

Waits for the SDK to finish fetching experiment configuration from the server. Must be called before getVariant(), isFeatureEnabled(), or getFeatureValue().

  • Returns a Promise<void> that resolves when config is loaded
  • Safe to call multiple times (returns the same promise)
  • If the config fetch fails, the promise still resolves (methods return safe defaults)

getVariant(experimentName)

typescript
const variant: string = cadence.getVariant('button-color-test')

Returns the variant name assigned to the current user for the given experiment.

Parameters:

| Name | Type | Description | |------|------|-------------| | experimentName | string | The name of the experiment (as created in the dashboard) |

Returns: string — The variant name (e.g., 'control', 'blue-button')

Behavior:

  1. Looks up the experiment by name
  2. Checks if the user falls within the traffic allocation (deterministic hash)
  3. If yes, assigns a variant based on traffic weights
  4. Automatically tracks an exposure event
  5. Applies visual mutations if the variant has them
  6. Returns the variant name

Edge cases:

  • If the experiment doesn't exist, returns 'control'
  • If the user is outside the traffic allocation, returns the control variant
  • Assignment is deterministic: same userId + experimentId always produces the same variant
typescript
// Full example
await cadence.ready()
const variant = cadence.getVariant('hero-headline')

switch (variant) {
  case 'urgency':
    return <h1>Limited time offer</h1>
  case 'social-proof':
    return <h1>Join 10,000+ teams</h1>
  default:
    return <h1>Start your free trial</h1>
}

isFeatureEnabled(featureKey)

typescript
const enabled: boolean = cadence.isFeatureEnabled('new-checkout')

Checks if a feature flag is enabled for the current user.

Parameters:

| Name | Type | Description | |------|------|-------------| | featureKey | string | The key of the feature flag |

Returns: boolean

Behavior:

  • Returns false if the flag doesn't exist or is disabled
  • Uses deterministic hashing against the rollout percentage
  • Same user always gets the same result for the same flag

getFeatureValue(featureKey, defaultValue?)

typescript
const price: unknown = cadence.getFeatureValue('hero-price', 9.99)

Gets a feature value, checking experiment overrides first, then feature flags.

Parameters:

| Name | Type | Description | |------|------|-------------| | featureKey | string | The key of the feature | | defaultValue | unknown | Fallback value if not found (default: null) |

Returns: unknown — The feature value or the default

Resolution order:

  1. Checks all active experiment variants for a matching feature_overrides key
  2. Falls back to isFeatureEnabled() (returns true if enabled, otherwise defaultValue)

track(eventName, properties?)

typescript
cadence.track('button-click', { location: 'hero', color: 'blue' })

Tracks a custom event. Events are batched and sent automatically.

Parameters:

| Name | Type | Description | |------|------|-------------| | eventName | string | Name of the event | | properties | Record<string, unknown> | Optional key-value pairs |


trackConversion(conversionName, properties?)

typescript
cadence.trackConversion('purchase', { value: 49.99, plan: 'pro' })

Tracks a conversion event. This is the primary metric used for experiment results in the dashboard.

Parameters:

| Name | Type | Description | |------|------|-------------| | conversionName | string | Name of the conversion | | properties | Record<string, unknown> | Optional key-value pairs (e.g., revenue) |

Track at the point of success

Call trackConversion() after the action succeeds (e.g., after the API confirms a purchase), not on button click. This ensures you only count real conversions.


enableAntiFlicker(timeout?)

typescript
cadence.enableAntiFlicker(2000)

Hides the page content until visual mutations are applied, preventing a flash of unstyled content. Must be called before getVariant().

Parameters:

| Name | Type | Default | Description | |------|------|---------|-------------| | timeout | number | 2000 | Safety timeout in milliseconds. Content becomes visible after this time even if mutations haven't loaded. |

typescript
// Recommended usage order
cadence.enableAntiFlicker(2000)
await cadence.ready()
cadence.getVariant('my-visual-test') // Content appears after mutations apply

destroy()

typescript
cadence.destroy()

Cleans up the SDK instance. Flushes any remaining queued events and stops the background flush timer.

  • Sends remaining events via navigator.sendBeacon (works even during page unload)
  • Clears the flush interval timer
  • Further track() or trackConversion() calls become no-ops
typescript
// React cleanup
useEffect(() => {
  const client = new CadenceClient({ sdkKey: '...' })
  return () => client.destroy()
}, [])

Event batching

The SDK batches events for efficient network usage:

| Setting | Value | Description | |---------|-------|-------------| | Flush interval | 5 seconds | Events are sent every 5 seconds if the queue is non-empty | | Flush threshold | 10 events | If 10+ events queue up, they're sent immediately | | Page unload | sendBeacon | Remaining events are sent synchronously on beforeunload | | Retry on failure | Yes | Failed events are re-queued for the next flush attempt |

API endpoints

The SDK communicates with two endpoints:

GET /api/sdk/[sdkKey]/config

Fetches experiment and feature flag configuration. Called once during ready(). Response is cached for 60 seconds on the server.

POST /api/sdk/[sdkKey]/events

Receives batched events. Accepts up to 100 events per request. The server validates the SDK key, associates events with the project, and inserts them into the database.

Next steps