Reference
SDK API reference
Every function on the global window.releaseo runtime — signatures, parameters, return values, and copy-paste examples for lifecycle, identity, widget controls, analytics, consent, host actions, and events.
The Releaseo SDK exposes a single runtime object. Once the script loads, every
function lives on window.releaseo. When you import the npm package, the default
export is the same runtime with the same methods.
// CDN — the loader assigns the runtime to window.releaseo
window.releaseo.init({ publishKey: "pk_live_xxx" });
// npm — the default export IS the runtime
import releaseo from "@releaseo/sdk-core";
releaseo.init({ publishKey: "pk_live_xxx" });
Loading and readiness
The widget initializes asynchronously: init() fetches your project config and
mounts the launcher. You do not need to wait before calling other methods —
the SDK queues calls made before it is ready and replays them in order once the
runtime and bridge are live. For non-blocking CDN loads, ship the stub queue so
even pre-load calls are buffered:
<script>
// Stub queue — buffers calls until the SDK script finishes loading.
window.releaseo = window.releaseo || { _q: [] };
["init", "identify", "open", "openFocused", "close", "track", "on", "off"].forEach(
function (m) {
window.releaseo[m] =
window.releaseo[m] ||
function () {
window.releaseo._q.push([m, [].slice.call(arguments)]);
};
},
);
</script>
<script src="https://cdn.releaseo.io/sdk/v0/loader.js" async></script>
<script>
window.releaseo.init({ publishKey: "pk_live_xxx" });
</script>
Methods that return a Promise resolve once the underlying action completes. They
never reject for normal control flow, so fire-and-forget with void is safe:
void window.releaseo.open();
Method index
| Method | Group | Summary |
|---|---|---|
init(config) | Lifecycle | Initialize the runtime and mount the launcher. |
endpoint(url) | Lifecycle | Point the SDK at a different API base URL at runtime. |
reset() | Lifecycle | Tear down the iframe, launcher, identity, and state. |
identify(userId, traits?) | Identity | Attach the signed-in viewer to the session. |
logout() | Identity | Clear identity and switch to anonymous mode. |
open() | Widget | Open the drawer on its default tab bar. |
openFocused(tab) | Widget | Open the drawer directly on one tab. |
close() | Widget | Close the drawer. |
track(event, payload?) | Analytics | Send a custom analytics event. |
consent | Privacy | Read the current consent state. |
setConsent(state) | Privacy | Update consent at runtime (GDPR). |
purgeAll() | Privacy | Erase all persisted SDK data (right to erasure). |
registerAction(key, handler) | Host actions | Wire a widget Home action to host-app code. |
unregisterAction(key) | Host actions | Remove a registered host-action handler. |
on(event, handler) | Events | Subscribe to a runtime event. |
off(event, handler) | Events | Unsubscribe a runtime event handler. |
setMockData(posts) | Preview | Swap in mock changelog data. |
setMockFeatureRequests(items) | Preview | Swap in mock feature-request data. |
settings | Diagnostics | Read the resolved runtime snapshot. |
Lifecycle
init()
init(config: ReleaseoInitConfig): void
Initializes the runtime, fetches /sdk/config for your project, and mounts the
launcher when the widget is enabled in dashboard settings. Call it once, as early
as possible. See the ReleaseoInitConfig reference for
every option.
Parameters
| Parameter | Type | Description |
|---|---|---|
config | ReleaseoInitConfig | At minimum a publishKey. All other fields are optional and resolved from dashboard settings. |
Returns void
window.releaseo.init({
publishKey: "pk_live_xxx",
theme: "auto", // "auto" | "light" | "dark"
position: "right", // "left" | "right"
locale: "en",
debug: false,
});
endpoint()
endpoint(endpoint: string): Promise<void>
Updates the API base URL after init(). Use this for self-hosted backends or to
switch environments without re-initializing. The backward-compatible
apiHost init option does the same thing at boot.
Parameters
| Parameter | Type | Description |
|---|---|---|
endpoint | string | Absolute base URL of the Releaseo API. |
Returns Promise<void> — resolves once the new endpoint is applied.
await window.releaseo.endpoint("https://api.example.com");
reset()
reset(): void
Full teardown — clears identity, closes the widget, removes the launcher and
iframe from the DOM, and returns internal state to IDLE. After reset() you
can call init() again with a fresh configuration. Use it for tenant,
organization, or project switches that need a completely clean session.
Returns void
window.releaseo.reset();
window.releaseo.init({ publishKey: "pk_live_other_tenant" });
Identity
identify()
identify(userId: string | number, properties?: ReleaseoIdentifyProperties): Promise<void>
Attaches the current signed-in viewer to the SDK session and opens an
authenticated widget session. Call it as soon as your app knows who the user is.
Identity is persisted (default TTL 30 days, configurable via identityTtl) so it
survives refreshes.
Parameters
| Parameter | Type | Description |
|---|---|---|
userId | string | number | Your stable user identifier. |
properties | ReleaseoIdentifyProperties | Optional flat traits. Values must be string, number, boolean, null, or undefined — no nested objects or arrays. |
Recognized traits include email, name, tenantId, and userHash. See
ReleaseoIdentifyProperties.
Returns Promise<void>
await window.releaseo.identify("u_123", {
tenantId: "t_456",
email: "[email protected]",
name: "Amina",
userHash: "server-generated-hmac", // optional, see below
});
logout()
logout(): void
Clears the current identity and session. The widget stays mounted but switches to
anonymous mode; persisted identity is removed from localStorage and a fresh
anonymous ID is minted on the next interaction. Call it when a user signs out.
Returns void
window.releaseo.logout();
Widget controls
open()
open(): Promise<void>
Opens the widget drawer with its full tab bar. Required when the dashboard trigger mode is set to “Only manually”; otherwise the launcher handles opening for you.
Returns Promise<void> — resolves once the drawer is open.
void window.releaseo.open();
openFocused()
openFocused(tab: ReleaseoFocusableTab): Promise<void>
Opens the drawer directly on a single tab, with the tab bar hidden — ideal for a
dedicated “What’s new” button, an embedded help launcher, or a marketing CTA that
should deep-link to one surface. The drawer returns to its default (full tab bar)
the next time open() is called after close().
Parameters
| Parameter | Type | Description |
|---|---|---|
tab | ReleaseoFocusableTab | One of "home", "changelog", "feature_requests", "roadmap", "help". |
Returns Promise<void>
// Deep-link a "What's new" button straight to the changelog feed
document.querySelector("#whats-new")?.addEventListener("click", () => {
void window.releaseo.openFocused("changelog");
});
close()
close(): void
Closes the widget drawer.
Returns void
window.releaseo.close();
Analytics
track()
track(eventName: string, payload?: Record<string, unknown>): Promise<void>
Sends a custom analytics event. Events appear in dashboard analytics and can be forwarded to selected integrations (PostHog, Webhook Out). Use it to record product moments worth correlating with widget engagement.
Parameters
| Parameter | Type | Description |
|---|---|---|
eventName | string | A stable, snake_case-friendly event name. |
payload | Record<string, unknown> | Optional structured properties for the event. |
Returns Promise<void>
await window.releaseo.track("billing_limit_reached", {
plan: "pro",
source: "settings",
});
Privacy and consent
GDPR / ePrivacy controls for telemetry and persistent storage. Default consent is
"granted", so existing integrations need no changes.
consent
readonly consent: ConsentState
Read-only property holding the current consent state — "granted", "denied", or
"pending".
console.log(window.releaseo.consent); // "granted" | "denied" | "pending"
setConsent()
setConsent(state: ConsentState): Promise<void>
Updates the consent state at runtime — wire it to your cookie banner.
| State | localStorage | Analytics |
|---|---|---|
"granted" | read + write | sent normally (queued telemetry is flushed) |
"pending" | memory only | queued, not sent |
"denied" | memory only | dropped; persistence stays off |
Parameters
| Parameter | Type | Description |
|---|---|---|
state | ConsentState | "granted", "denied", or "pending". |
Returns Promise<void>
// Initialize deferred, then grant after the user accepts the banner
window.releaseo.init({ publishKey: "pk_live_xxx", consent: "pending" });
window.releaseo.setConsent("granted");
purgeAll()
purgeAll(): Promise<void>
GDPR Article 17 (right to erasure). Best-effort wipe of all persisted SDK data:
host-side localStorage/sessionStorage keys, queued telemetry, the in-memory
identity, and widget-side storage. The user becomes anonymous, the SDK stays
mounted, and the promise never rejects.
Returns Promise<void>
// Segment-style reset: wipe everything, mint a fresh anonymous id
await window.releaseo.purgeAll();
// Strict erasure — leave zero releaseo:* keys behind
await window.releaseo.setConsent("denied");
await window.releaseo.purgeAll();
Host actions
A “host action” lets a whitelisted widget Home button trigger code in your app — for example opening your existing support chat. The dashboard stores only an action key; it never stores or executes raw JavaScript.
registerAction()
registerAction(actionKey: string, handler: ReleaseoWidgetActionHandler): void
Registers a handler for a host action key configured in the dashboard.
Parameters
| Parameter | Type | Description |
|---|---|---|
actionKey | string | The key configured on the widget Home action. |
handler | ReleaseoWidgetActionHandler | Receives { actionKey, actionId, label } and may return a Promise. |
Returns void
window.releaseo.registerAction("open_chat", async ({ actionKey, actionId, label }) => {
window.Intercom?.("show");
console.info("Releaseo action", { actionKey, actionId, label });
});
unregisterAction()
unregisterAction(actionKey: string): void
Removes a previously registered host-action handler — call it when the owning app shell unmounts.
Parameters
| Parameter | Type | Description |
|---|---|---|
actionKey | string | The key passed to registerAction(). |
Returns void
window.releaseo.unregisterAction("open_chat");
Events
Subscribe to runtime lifecycle events for custom host behavior — badge counts, analytics bridges, or recovery handling.
on()
on<K extends keyof ReleaseoEventMap>(eventName: K, handler: (payload: ReleaseoEventMap[K]) => void): void
Subscribes a handler to a runtime event.
Returns void
window.releaseo.on("ready", () => console.log("Releaseo is ready"));
window.releaseo.on("unreadChange", (count) => {
document.querySelector("#badge")?.replaceChildren(String(count));
});
window.releaseo.on("error", (error) => console.error("[Releaseo]", error));
off()
off<K extends keyof ReleaseoEventMap>(eventName: K, handler: (payload: ReleaseoEventMap[K]) => void): void
Unsubscribes a previously registered handler. Pass the same function reference you
gave to on().
Returns void
const onUnread = (count: number) => updateBadge(count);
window.releaseo.on("unreadChange", onUnread);
// later…
window.releaseo.off("unreadChange", onUnread);
Event reference
| Event | Payload | Fires when |
|---|---|---|
ready | void | The runtime has initialized and is usable. |
unreadChange | number | The unread announcement count changes. |
error | Error | A non-fatal runtime error occurs. |
stateChange | SDKState | The internal state machine transitions. |
identityChange | { userId, previousUserId } | The identified user changes. |
identityError | Error | Identity handoff (e.g. userHash) fails. |
widgetAction | { actionKey, actionId, label } | A host action is requested from the widget. |
bridge:ready | void | The iframe bridge connects. |
bridge:lost | void | The iframe bridge disconnects. |
bridge:recovered | void | The iframe bridge reconnects after a loss. |
Preview and mock data
Swap in mock content for demos, local development, and dashboard previews without
reloading. After init(), these update the widget immediately.
setMockData()
setMockData(posts: ReleaseoChangelogListItem[]): void
Replaces the changelog posts shown in the widget.
Returns void
setMockFeatureRequests()
setMockFeatureRequests(featureRequests: ReleaseoFeatureRequestListItem[]): void
Replaces the feature-request items shown in the widget.
Returns void
window.releaseo.setMockFeatureRequests([
{
id: "fr_1",
projectId: "proj_demo",
kind: "feature_request",
title: "Clearer export labels",
description: "Let customers request clearer export names.",
status: "open",
reviewStatus: "approved",
upvotes: 12,
downvotes: 0,
score: 12,
commentCount: 0,
authorName: "Anonymous",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
]);
Diagnostics
settings
readonly settings: ReleaseoSettingsSnapshot | undefined
Read-only snapshot of the resolved configuration and live runtime state. undefined
until init() has resolved. Useful for debugging and for reading values like the
current unread count or session state.
Frequently used fields
| Field | Type | Description |
|---|---|---|
state | SDKState | Current state-machine value (e.g. "IDENTIFIED", "OPENED"). |
unreadCount | number | Current unread announcement count. |
hasSession | boolean | Whether an authenticated session is active. |
bridgeReady | boolean | Whether the iframe bridge is connected. |
consent | ConsentState | Effective consent state. |
userid | string | number | null | The identified user id, or null when anonymous. |
anonymousId | string | The current anonymous id. |
version | string | Runtime version. |
theme / position / locale | — | Resolved widget presentation settings. |
console.log(window.releaseo.settings?.unreadCount); // e.g. 8
console.log(window.releaseo.settings?.state); // e.g. "IDENTIFIED"
Type reference
ReleaseoInitConfig
| Field | Type | Default | Description |
|---|---|---|---|
publishKey | string | — | Project publish key. Required unless mock content is provided. |
endpoint | string | Releaseo API | Preferred API base URL. Takes precedence over apiHost. |
apiHost | string | — | Backward-compatible alias for endpoint. |
widgetUrl | string | Releaseo CDN | Override only for self-hosted or local dev. |
analyticsEndpoint | string | same as endpoint | Analytics ingestion endpoint. |
productId | string | from /sdk/config | Override only if needed. |
theme | "auto" | "light" | "dark" | dashboard | Widget theme preference. |
position | "left" | "right" | dashboard | Launcher / drawer position. |
locale | string | dashboard | Widget locale. |
debug | boolean | false | Verbose runtime diagnostics and dev warnings. |
consent | ConsentState | "granted" | Telemetry/storage consent (GDPR). |
respectDoNotTrack | boolean | false | Treat navigator.doNotTrack as "denied". |
styleNonce | string | — | CSP nonce for injected host <style> tags. |
identityTtl | number | 2_592_000_000 | Persisted-identity lifetime in ms (30 days). |
mockPosts | ReleaseoChangelogListItem[] | — | Bypass the API and serve these changelog posts. |
mockFeatureRequests | ReleaseoFeatureRequestListItem[] | — | Bypass the API and serve these feature requests. |
ReleaseoIdentifyProperties
type TraitValue = string | number | boolean | null | undefined;
type ReleaseoIdentifyProperties = Record<string, TraitValue>;
Flat key/value traits only — nested objects and arrays are not allowed. Reserved
keys with special handling: email, name, tenantId, and userHash (the
server-generated HMAC for trusted identity).
ReleaseoFocusableTab
type ReleaseoFocusableTab =
| "home"
| "changelog"
| "feature_requests"
| "roadmap"
| "help";
The strict set of tabs accepted by openFocused(). feedback and
messages are widget tabs but are not navigable content views, so they are
intentionally excluded.
ConsentState
type ConsentState = "granted" | "denied" | "pending";
ReleaseoEventMap
interface ReleaseoEventMap {
ready: void;
unreadChange: number;
error: Error;
stateChange: SDKState;
identityChange: { userId: string; previousUserId: string | null };
identityError: Error;
widgetAction: { actionKey: string; actionId: string; label: string };
"bridge:ready": void;
"bridge:lost": void;
"bridge:recovered": void;
}
Thanks — your feedback helps us improve the docs.