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

# SvelteKit Integration

> Install Userplane in a SvelteKit application using onMount in the root layout

This guide covers how to install Userplane in a SvelteKit application.

## Adding the script

The fastest way to add Userplane is the CDN embed. Add these two tags to the `<head>` in `src/app.html`:

```html theme={null}
<meta name="userplane:workspace" content="YOUR_WORKSPACE_ID" />
<script type="module" src="https://cdn.userplane.io/embed/script.js"></script>
```

You can copy the snippet with your workspace ID pre-filled from **Workspace Settings > Domains** in the Userplane dashboard.

## npm SDK

Use the npm SDK when you need programmatic control — triggering recordings from a button, attaching user metadata, or reading recording state.

### Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @userplane/sdk
  ```

  ```bash yarn theme={null}
  yarn add @userplane/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @userplane/sdk
  ```

  ```bash bun theme={null}
  bun add @userplane/sdk
  ```
</CodeGroup>

### Initialization

Initialize the SDK in `src/routes/+layout.svelte` using `onMount`. `onMount` only runs in the browser, so it is safe to import and call the SDK there.

```svelte theme={null}
<!-- src/routes/+layout.svelte -->
<script>
  import { onMount } from 'svelte';
  import { PUBLIC_USERPLANE_WORKSPACE_ID } from '$env/static/public';

  onMount(async () => {
    const { initialize } = await import('@userplane/sdk');
    initialize({ workspaceId: PUBLIC_USERPLANE_WORKSPACE_ID });
  });
</script>

<slot />
```

Set the variable in your `.env` file:

```
PUBLIC_USERPLANE_WORKSPACE_ID=ws_abc123
```

SvelteKit's `$env/static/public` module only exposes variables prefixed with `PUBLIC_`, and the module is inlined at build time.

### URL parameters

When a customer opens a recording link, Userplane appends `userplane-token` and `userplane-action` to the URL. If your app uses a SvelteKit server hook or layout `load` function that redirects unauthenticated users, preserve the `userplane-` prefixed parameters through the redirect:

```typescript theme={null}
// src/hooks.server.ts
import { redirect } from '@sveltejs/kit';
import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
  if (requiresAuth(event) && !isAuthenticated(event)) {
    const url = event.url;
    const loginUrl = new URL('/login', url.origin);

    for (const [key, value] of url.searchParams) {
      if (key.startsWith('userplane-')) {
        loginUrl.searchParams.set(key, value);
      }
    }

    redirect(302, loginUrl.toString());
  }

  return resolve(event);
};
```

See [Installation](/developer/installation) for the full list of parameters.

## Sensitive data

Add `data-userplane-blur` to any element you want blurred in recordings. See [Sensitive Data Redaction](/developer/sensitive-data-redaction) for the full reference.

## Metadata

Call `set()` inside `onMount` after `initialize()`:

```svelte theme={null}
<script>
  import { onMount } from 'svelte';
  import { PUBLIC_USERPLANE_WORKSPACE_ID } from '$env/static/public';

  onMount(async () => {
    const { initialize, set } = await import('@userplane/sdk');
    initialize({ workspaceId: PUBLIC_USERPLANE_WORKSPACE_ID });
    set('environment', 'production');
  });
</script>

<slot />
```

See [Metadata SDK](/developer/metadata-sdk) for the full API.

## SSR

`@userplane/sdk` is SSR-safe to import — it does not reference `window` or `document` at module evaluation time. The `initialize()` call must run client-side, which `onMount` guarantees. You do not need `export const ssr = false` in your layout.

| Concern                                         | Safe?      | Notes                         |
| ----------------------------------------------- | ---------- | ----------------------------- |
| Static `import` at top of `<script>`            | Yes        | Module is SSR-safe            |
| Calling `initialize()` inside `onMount`         | Yes        | Runs browser-only             |
| Dynamic `import('@userplane/sdk')` in `onMount` | Yes        | Bundle-size optimization only |
| Calling `initialize()` in a `load` function     | No         | `load` runs on the server     |
| `export const ssr = false`                      | Not needed | `onMount` is sufficient       |

## Example app

A complete SvelteKit example is available at [github.com/userplanehq/userplane-sdk-examples/tree/main/examples/sveltekit](https://github.com/userplanehq/userplane-sdk-examples/tree/main/examples/sveltekit).

<Frame caption="Example app">
  <img src="https://mintcdn.com/userplane/iHJrxtyvOmNXmfMS/media/developer/framework/sveltekit-example-app.png?fit=max&auto=format&n=iHJrxtyvOmNXmfMS&q=85&s=359f3fef186325ddf29837731866150f" width="1920" height="1440" data-path="media/developer/framework/sveltekit-example-app.png" />
</Frame>

| Variable                        | Description                 |
| ------------------------------- | --------------------------- |
| `PUBLIC_USERPLANE_WORKSPACE_ID` | Your Userplane workspace ID |

```bash theme={null}
cd examples/sveltekit && npm install && npm run dev
```

## Related articles

* [Installation](/developer/installation) — CDN script placement, CSP, and redirect handling.
* [Web SDK](/developer/web-sdk) — full SDK API reference.
* [Metadata SDK](/developer/metadata-sdk) — attach user context to recordings.
* [Sensitive Data Redaction](/developer/sensitive-data-redaction) — blur sensitive content in recordings.
