Upgrade from SDK 0.2

Last updated @userreason/js 0.5.4Added in 0.4.0
On this page

SDK 0.4.0 changes how surveys are configured and how visitor state is stored. Update your integration before replacing a 0.2 installation. Keep your existing integration available until you have verified the new setup with a test site.

What changes

In an older integration In SDK 0.4.0
Survey definitions passed to init({ surveys }) Create and publish surveys in the dashboard, CLI or MCP.
Your own response endpoint or submit callback UserReason receives responses. Use SDK notifications for application reactions and the dashboard or CLI to read responses.
Initialization without a managed site siteId is required and must be the site's public UUID.
Memory storage when storage is omitted The default is now 'local'. Set 'memory' explicitly if you want to avoid device persistence.
Client-side dismissalCooldownMs Configure frequency in the site settings and each survey's delivery settings.
Local survey IDs in show(id) Use the published survey ID from the dashboard or CLI.
Survey, Response or RemoteResponse types Local survey types are removed. Accepted response notifications use PromptResponse.

1. Create and publish your surveys

Create a site in the dashboard and copy its site UUID. A site ID is public configuration, not a management credential. Keep separate sites for testing and real visitors.

Recreate each local survey as a published survey with its questions, audience, trigger, sampling and frequency. Follow Your first survey for a complete example. Save the published survey IDs if your application calls show() directly.

An initialized site with no eligible published survey displays nothing. There is no local-survey fallback if the UserReason API is unavailable. apiBaseUrl selects a compatible UserReason API origin; it does not replace the removed custom response endpoint.

2. Update the package and initialization

Terminalsh
npm install @userreason/js@0.5.0

Remove surveys, endpoint, submit and dismissalCooldownMs from your initialization. Initialize once in the browser entry and reuse the same instance throughout your app:

src/userreason.tsts
import UserReason from '@userreason/js';

UserReason.on((notification) => {
  if (notification.type === 'error') {
    console.error('UserReason could not complete an operation', notification.error);
  }
});

UserReason.init({
  siteId: 'YOUR_SITE_ID',
  storage: 'memory',
});

await UserReason.ready();

Replace YOUR_SITE_ID with the site UUID. The explicit memory setting preserves a no-persistence choice while you review storage; choose 'local' or 'cookie' if that fits your integration. ready() rejects when configuration or the visitor session cannot load. Handle that failure in your app without blocking its own startup.

The default export is a shared instance. Repeated init() calls on an initialized instance do nothing; they do not update options. Valid initialization is inert during server rendering, so ensure the browser also runs it. See Initialization and lifecycle for independent instances and teardown.

When storage is omitted, SDK 0.4.0 persists an anonymous visitor token, a short-lived session and configured event summaries in first-party localStorage. This is a change from an older integration that relied on the memory default.

Use storage: 'memory' to avoid device persistence. If your app permits UserReason requests before persistence, connect your consent handler to setStorage():

ts
import UserReason from '@userreason/js';

// Call after initializing UserReason, whenever the app's storage choice changes.
export function setFeedbackPersistence(allowed: boolean): void {
  UserReason.setStorage(allowed ? 'local' : 'memory');
}

Switching to memory removes persisted UserReason data for this site from the device and keeps the current page's in-memory state. It does not stop network requests or delete responses already held by UserReason. If your policy requires no UserReason requests before consent, defer init() until consent is given. To stop an active integration on the page, call destroy() and do not initialize it again until your app permits it; destroy() alone does not remove stored visitor data.

See Storage and consent for cookie storage, retention and the difference between device data and server data.

4. Update event and response handling

event(name, properties?, options?) reports a completed action and checks matching published surveys. track(name) remains an alias without properties or options. Neither method defines a survey locally.

For a feedback button, configure a page-load trigger on the published survey, set automaticTriggers: false at initialization if you want to prevent automatic display, and call show(publishedSurveyId). show() still checks eligibility, sampling and server frequency; force: true does not override them.

Replace the old submission callback with a notification listener for application reactions:

ts
import UserReason from '@userreason/js';

const unsubscribe = UserReason.on((notification) => {
  if (notification.type === 'submitted') {
    const response = notification.response;
    console.info('Feedback accepted', response.responseId);
  }
});

// Call unsubscribe() when this application listener is no longer needed.

submitted fires after UserReason accepts the final response, including a screened-out response. Partial saves do not emit it. Notifications do not let the app replace response delivery. Read SDK notifications for the PromptResponse shape and PostHog integration for forwarding selected activity to your existing analytics client.

New sites use explicit event collection policies. An unknown event can stay local rather than create retained server history. Review event collection and register the business events you need; existing sites keep their previous capture mode until you change it.

5. Check identity and interface overrides

Call identify(accountId, traits) after your app authenticates the visitor, and reset() after sign-out. A backend assertion is optional for ordinary attribution and required when you need verified ownership or trusted traits. When restoring authentication asynchronously, use waitForIdentity: true and resolve authentication before awaiting ready(). See Identity and traits.

If you override interface messages, replace the removed chooseAtMost key with chooseUpTo. Keep {min} and {max} in a custom chooseRating message. Use the exported Messages type to check overrides against the current message keys.

6. Verify before rolling out

On a test site, confirm that a published survey displays, a final response reaches the dashboard, and sign-in and sign-out associate responses with the intended visitor. Check both permitted and denied persistence choices in your browser's storage tools. Verify event-triggered and manually opened surveys separately, including frequency limits and partial responses if enabled.

Then replace the test site ID with the production site ID, publish the intended surveys and release the updated application. Keep management credentials out of browser code throughout the migration.