Shipeasy
ReferenceTypeScript / JavaScript

Advanced

LaunchDarkly / Statsig parity features. All are set as options on configure() (or on shipeasy() for SSR), or read through the bound Client.

Generated from the SDK's own /docs/ — also served raw at https://shipeasy-ai.github.io/sdk/pages/advanced.md.

LaunchDarkly / Statsig parity features. All are set as options on configure() (or on shipeasy() for SSR), or read through the bound Client.

Manual exposure

By default reading an experiment fires one exposure beacon. To control exactly when the exposure is logged (e.g. only when the treatment actually renders), read without auto-exposure and call logExposure(name) on the bound Client:

const flags = new Client(req.user); // construct once per callsite

// Read the params, then…
const { params } = flags.getExperiment("hero_cta", { primary_label: "Sign up" });

// …log the exposure at the moment you actually render the treatment:
flags.logExposure("hero_cta");

On the server logExposure(name) re-evaluates enrolment for the bound user and emits the exposure (no-op when the user isn't enrolled). In the browser, set autoExposure: false on configure() to make manual exposure the default for every read.

Private attributes

Attributes you mark private are used for evaluation but stripped from every outbound track() payload (LD/Statsig privateAttributes):

configure({
  apiKey: process.env.SHIPEASY_SERVER_KEY!,
  privateAttributes: ["email", "ip"],
});

On the browser they are still sent to /sdk/evaluate under private_attributes so the edge can evaluate with them (unavoidable), but they never appear in tracked event props.

bucketBy — custom bucketing unit

Bucketing hashes on user_id (falling back to anonymous_id) by default. An experiment can carry its own bucketBy (e.g. company_id) so all users in a company get the same variant — set on the experiment in the dashboard, no SDK change needed. When bucketBy is set, the value of that attribute is the hash unit; if it's missing on the user, evaluation falls back to the standard identifier. Make sure your attributes transform surfaces the bucketing attribute:

configure({
  apiKey: process.env.SHIPEASY_SERVER_KEY!,
  attributes: (u: MyUser) => ({ user_id: u.id, company_id: u.orgId }),
});

Sticky bucketing

Lock a unit into the first variant it was assigned even if the experiment's allocation later changes. On the server, pass a stickyStore to configure() to persist assignments across requests:

import { configure, createInMemoryStickyStore } from "@shipeasy/sdk/server";

configure({
  apiKey: process.env.SHIPEASY_SERVER_KEY!,
  stickyStore: createInMemoryStickyStore(), // or a cookie-bridge over __se_sticky
});

createInMemoryStickyStore() is process-local (good for a single-process server or tests); for a multi-process deployment back the StickyBucketStore interface (get(unit) / set(unit, exp, entry)) with shared storage or a request-cookie bridge. In the browser, sticky bucketing is on by default (persisted in the __se_sticky cookie so SSR server eval and the browser agree).

Anonymous-id bucketing

The browser persists an anonymous_id (and the SSR bootstrap mints a matching __se_anon_id cookie) so a logged-out visitor buckets identically before and after the server pre-evaluation — no flag flicker on first paint.

Change listeners

The package-level onChange() fires after a background poll returns new data (HTTP 200, not 304) and returns an unsubscribe callable. It requires configure({ poll: true }) (no poll thread runs otherwise) and never fires in test/offline mode:

import { configure, onChange } from "@shipeasy/sdk/server";

configure({ apiKey: process.env.SHIPEASY_SERVER_KEY!, poll: true });

const unsubscribe = onChange(() => {
  /* re-evaluate / invalidate cache */
});

In the browser, onChange() fires after each identify() / override change.

Devtools overlay

Press Shift+Alt+S on any page running the SDK (or append ?se=1). The Shipeasy devtools panel mounts in a Shadow DOM overlay and lets you flip every gate / config / experiment / translation for the current session only — handy for QA, demos, and bug repro.

Was this page helpful?
✎ Edit this page

On this page