> ## Documentation Index
> Fetch the complete documentation index at: https://docs.worthai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide

This guide details steps to migrate from the iframe-based Onboarding SDK 2
integration to the SDK 3 embedded runtime integration.

## What's Changed?

The core change is ownership of the iframe. With SDK 2, your host page creates and
manages a Worth iframe directly. With SDK 3, you give the SDK a DOM element and it
mounts, renders, and tears down the onboarding runtime for you with no iframe and no
`postMessage` subscription required.

|            | SDK 2                                                    | SDK 3                                                          |
| ---------- | -------------------------------------------------------- | -------------------------------------------------------------- |
| Rendering  | Host-managed `<iframe>`                                  | SDK-managed DOM mount                                          |
| Setup      | `createOnboardingApp({ origin, inviteToken, mode })`     | `createWorthOnboarding({ inviteToken, ... })`                  |
| Mounting   | `container.appendChild(onboardingApp.iframe)`            | `await onboarding.mount(target)`                               |
| Events     | `subscribe()` + `postMessage` event stream               | Typed callbacks (`onStepSubmit`, `onComplete`, `onError`, ...) |
| Navigation | `next()`, `prev()`, `skip()`                             | Not exposed; the SDK owns step navigation                      |
| Styling    | `setCustomCss()`                                         | Styles injected automatically on `mount()`                     |
| Cleanup    | `subscription.unsubscribe()` + `onboardingApp.cleanup()` | `onboarding.unmount()`                                         |

## Side-by-Side Comparison

<Tabs>
  <Tab title="Before: SDK 2">
    When using SDK 2, the customer application owns the iframe lifecycle. It creates the
    iframe, appends it to the page, listens for `postMessage` events, and may drive
    navigation by calling helper methods such as `next()`, `prev()`, and `skip()`.

    ```ts theme={null}
    import { createOnboardingApp } from '@worthai/onboarding-sdk';

    const container = document.getElementById('worth-onboarding');
    const inviteToken = 'INVITE_TOKEN';

    const onboardingApp = createOnboardingApp({
      origin: 'https://onboarding.example.com',
      inviteToken,
      mode: 'embedded',
      loadingTimeout: 15000
    });

    const subscription = onboardingApp.subscribe((event) => {
      switch (event.data.type) {
        case 'ONBOARDING_COMPLETED':
          handleComplete();
          break;
        case 'ERROR':
          handleError(event.data.payload.error);
          break;
        case 'STAGE_NAVIGATION':
          updateNavigation(event.data.payload.stageNavigation);
          break;
        default:
          break;
      }
    });

    container?.appendChild(onboardingApp.iframe);

    document.getElementById('worth-back')?.addEventListener('click', () => {
      onboardingApp.prev();
    });

    document.getElementById('worth-next')?.addEventListener('click', () => {
      onboardingApp.next();
    });

    function cleanupOnboarding() {
      subscription.unsubscribe();
      onboardingApp.cleanup();
      onboardingApp.iframe.remove();
    }
    ```
  </Tab>

  <Tab title="After: SDK 3">
    When using SDK 3, the customer application no longer manages an iframe. It creates an
    onboarding instance with a valid invite token and optional callbacks, and mounts
    the SDK into a DOM element. SDK styles are injected automatically during mount.

    ```ts theme={null}
    import { createWorthOnboarding } from '@worthai/onboarding-sdk';

    const onboarding = createWorthOnboarding({
      inviteToken: 'INVITE_TOKEN',
      onStepSubmit: ({ inviteToken, stepId, values }) => {
        // step submission hook for analytics, audit, or synchronization
      },
      onComplete: ({ inviteToken, values }) => {
        // form completion hook - maps to ONBOARDING_COMPLETED event from SDK2
      },
      onError: (error) => {
        // error handling hook - maps to ERROR event from SDK2
      }
    });

    await onboarding.mount('#worth-onboarding');

    function cleanupOnboarding() {
      onboarding.unmount();
    }
    ```
  </Tab>
</Tabs>

## Additional SDK 3 Configuration

For non-production or non-default API environments, pass `apiBaseUrl`:

```ts theme={null}
const onboarding = createWorthOnboarding({
  apiBaseUrl: 'https://api.staging.example.com',
  inviteToken: 'INVITE_TOKEN',
  onComplete: ({ values }) => {},
  onStepSubmit: ({ inviteToken, stepId, values }) => {},
  onError: (error) => {}
});
```

SDK 3 injects its scoped runtime styles automatically during `mount()`. Hosts
with a strict `style-src` Content Security Policy should pass the page's
request-level nonce explicitly with `styleNonce`:

```ts theme={null}
const onboarding = createWorthOnboarding({
  inviteToken: 'INVITE_TOKEN',
  styleNonce: window.__CSP_NONCE__,
  // . . .
});
```

Bundler and module-script integrations should not rely on automatic nonce
discovery. If the host application uses CSP nonces, pass the nonce value from the
host application configuration.

## What changes do you need to make?

The core migration is from iframe orchestration to embedded runtime mounting. SDK 2 iframe-specific code should be replaced with SDK 3 lifecycle callbacks.

Remove SDK 2 iframe ownership:

* Remove `origin`, `mode`, and `loadingTimeout` configuration
* Remove `appendChild(onboardingApp.iframe)` and direct iframe styling
* Remove raw `postMessage` event subscription logic
* Remove calls to `next()`, `prev()`, `skip()`, `setMode()`, `setCustomCss()`,
  and `refreshSize()`
* Remove iframe-specific teardown, except for replacing it with
  `onboarding.unmount()`

Add SDK 3 embedded runtime usage:

* Add a stable mount target, such as `<div id="worth-onboarding"></div>`
* Remove any old SDK stylesheet import or stylesheet `<link>` tag. SDK 3 styles
  are injected automatically during `mount()`
* Create an SDK instance with `createWorthOnboarding({ inviteToken, ... })`
* Use `onComplete` for completion behavior
* Use `onError` for SDK/runtime errors
* Use `onStepSubmit` when the host application needs a step-submission
  analytics, audit, or synchronization hook
* Call `unmount()` when the containing route or component unloads

## Callback Mapping

SDK 2 exposed a broad event stream through `subscribe()`. SDK 3 exposes
structured callbacks on the `createWorthOnboarding` options object.

* Use `onComplete` instead of handling the `ONBOARDING_COMPLETED` message
* Use `onError` instead of handling the `ERROR` message
* Use `onAuthenticated` and `onAuthUnsupported` for authentication-specific
  outcomes when the host application needs to observe those states
* Use `onStepSubmit` for submitted step payloads. The callback receives:

```ts theme={null}
{
  inviteToken: string;
  stepId: string;
  values: Record<string, unknown>;
}
```

SDK 3 does not expose a public step-navigation callback. If the SDK 2
integration used `STAGE_NAVIGATION` only to observe internal step changes, remove
that listener during migration; `onStepSubmit` is only fired for submitted step
payloads and is not a general navigation-event replacement.

## Migration Checklist

Use this checklist to track your migration from start to finish.

<Steps>
  <Step title="Update the SDK package">
    Update the `@worthai/onboarding-sdk` package version that contains SDK 3
  </Step>

  <Step title="Add a mount target">
    Add or reuse a mount target element, such as `<div id="worth-onboarding"></div>`
  </Step>

  <Step title="Remove old stylesheets">
    Remove any old Worth SDK stylesheet import or CDN stylesheet tag. SDK 3 injects its styles automatically during `mount()`
  </Step>

  <Step title="Swap the SDK entry point">
    Replace `createOnboardingApp(...)` with `createWorthOnboarding(...)`
  </Step>

  <Step title="Move event handling to callbacks">
    Move completion and error behavior from `subscribe()` handlers to `onComplete` and `onError`
  </Step>

  <Step title="Add onStepSubmit if needed">
    Add `onStepSubmit` if your application needs a step-submission hook for analytics, auditing, synchronization, etc.
  </Step>

  <Step title="Handle strict CSP, if applicable">
    If your host page enforces a strict `style-src` Content Security Policy, pass its request nonce as `styleNonce` and test in a page with CSP enabled
  </Step>

  <Step title="Remove iframe navigation controls">
    Remove external iframe navigation controls (`next()`, `prev()`, `skip()`) unless SDK 3 explicitly adds a replacement API
  </Step>

  <Step title="Replace cleanup logic">
    Replace iframe cleanup (`subscription.unsubscribe()`, `onboardingApp.cleanup()`) with `onboarding.unmount()`
  </Step>

  <Step title="Test the full flow">
    Test the full onboarding flow in your host page, including route changes, cleanup/remount, completion, and error handling
  </Step>
</Steps>

***

## Support

For questions or issues, please contact your Worth Customer Success team or reach out to [support@joinworth.com](mailto:support@joinworth.com).
