npm package: @getversive/embed
Description: Embed Versive studies in any web app
Latest version: 0.1.2

# @getversive/embed

Embed Versive studies (surveys, AI interviews) in any web app. Lightweight (~4KB gzipped), framework-agnostic, zero dependencies.

## Quick Start

### Script Tag (Zero-Code)

```html
<script src="https://getversive.com/embed.js"></script>

<!-- Inline study -->
<div data-versive-study="YOUR_STUDY_ID" data-versive-mode="inline"></div>

<!-- Button that opens modal -->
<button data-versive-study="YOUR_STUDY_ID" data-versive-mode="modal">
  Share Feedback
</button>
```

### JavaScript SDK

```bash
npm install @getversive/embed
```

```javascript
import Versive from '@getversive/embed';

// Initialize once — use anywhere in your app
const versive = Versive.init();

// Open a study as a modal
versive.open('YOUR_STUDY_ID', {
  context: {
    userId: 'user_123',
    plan: 'enterprise',
  },
  on: {
    ready:    () => console.log('Study loaded'),
    start:    (data) => console.log('Started:', data.interviewId),
    complete: (data) => console.log('Done:', data.responseId),
    close:    (reason) => console.log('Closed:', reason),
    error:    (err) => console.error(err),
  },
});

// Or embed inline
versive.embed('YOUR_STUDY_ID', '#feedback-container');
```

## Display Modes

### Modal

Opens the study in a centered overlay with backdrop, close button, escape key, and click-outside-to-close.

```javascript
const versive = Versive.init();

versive.open('abc123', {
  display: {
    width: '480px',
    maxHeight: '90vh',
    closeOnOverlayClick: true,
    closeOnEscape: true,
    zIndex: 999999,
  },
});
```

### Inline

Embeds the study directly in a container element. The iframe height auto-adjusts to match content.

```javascript
const versive = Versive.init();

const session = versive.embed('abc123', '#my-container', {
  on: {
    heightChange: (height) => console.log('New height:', height),
  },
});
```

## API Reference

### `Versive.init(config?)`

Creates a Versive client with global configuration. Call once, use everywhere.

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `baseUrl` | `string` | Auto-detected from script src, or `'https://www.getversive.com'` | Versive app URL |
| `preview` | `boolean` | `false` | Preview mode — responses won't be saved |
| `display` | `object` | — | Default display config for all modals |
| `on` | `object` | — | Default event callbacks for all studies |

### `versive.open(studyId, options?)`

Opens a study in a modal overlay. Returns a `StudySession` for event subscriptions.

| Option | Type | Description |
|--------|------|-------------|
| `preview` | `boolean` | Override global preview mode for this study |
| `context` | `Record<string, string>` | Key-value pairs forwarded as query params. Avoid sensitive values — they appear in the study URL. |
| `display` | `object` | Override global display config (see below) |
| `on` | `object` | Event callbacks for this study (merged with global) |

### `versive.embed(studyId, container, options?)`

Embeds a study inline in a container (CSS selector or HTMLElement). Returns a `StudySession`.

| Option | Type | Description |
|--------|------|-------------|
| `preview` | `boolean` | Override global preview mode for this study |
| `context` | `Record<string, string>` | Key-value pairs forwarded as query params. Avoid sensitive values — they appear in the study URL. |
| `on` | `object` | Event callbacks for this study (merged with global) |

### `versive.close()`

Closes the active modal session.

### `versive.destroy()`

Destroys the client and cleans up all resources.

### StudySession Methods

The `open()` and `embed()` methods return a `StudySession` for direct control:

| Method | Description |
|--------|-------------|
| `session.close()` | Close this specific study |
| `session.destroy()` | Close and remove all event listeners |
| `session.on(event, handler)` | Subscribe to an event. Returns an unsubscribe function |
| `session.off(event, handler)` | Unsubscribe from an event |

### Display Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `width` | `string` | `'480px'` | Modal width |
| `maxHeight` | `string` | `'90vh'` | Modal max height |
| `closeOnOverlayClick` | `boolean` | `true` | Close modal when clicking backdrop |
| `closeOnEscape` | `boolean` | `true` | Close modal on Escape key |
| `zIndex` | `number` | `999999` | z-index of modal overlay |

### Events

| Event | Callback Signature | Description |
|-------|-------------------|-------------|
| `ready` | `() => void` | Study iframe loaded and ready |
| `start` | `(data: { interviewId: string }) => void` | Participant started the interview |
| `complete` | `(data: { interviewId: string; responseId: string }) => void` | Interview completed |
| `close` | `(reason: 'completed' \| 'dismissed' \| 'error') => void` | Study closed |
| `error` | `(err: { code: string; message: string }) => void` | Error occurred |
| `heightChange` | `(height: number) => void` | iframe content height changed (inline mode) |
| `permissionRequired` | `(type: 'microphone' \| 'camera') => void` | Browser permission prompt incoming |

## Data Attributes (Script Tag)

| Attribute | Required | Values | Description |
|-----------|----------|--------|-------------|
| `data-versive-study` | Yes | Study ID | The study to embed |
| `data-versive-mode` | No | `inline` (default), `modal` | Display mode |
| `data-versive-context-*` | No | Any string | Context passed as query params (e.g., `data-versive-context-plan="pro"` becomes `?plan=pro`). Avoid sensitive values — they appear in the study URL. |
| `data-versive-preview` | No | Present = preview mode | Responses won't be saved |

## Content Security Policy

If your site uses a CSP, add the Versive domain to `frame-src`:

```text
frame-src https://getversive.com;
```

For voice/video studies, ensure your `Permissions-Policy` allows `microphone` and `camera` for the Versive domain.

## Supported Study Modes

- **Text surveys** — Standard form-based surveys
- **AI interviews (voice + video)** — Conversational AI with microphone/camera. The SDK automatically sets `allow="microphone; camera"` on the iframe.

## Preview Mode

Pass `preview: true` (SDK) or add `data-versive-preview` (script tag) to run the study without saving responses. This uses the same preview mode as the study editor.

## Development

```bash
npm install
npm run build     # Build IIFE + ESM bundles
npm run dev       # Watch mode
npm run type-check
```

Build outputs:
- `dist/embed.js` — IIFE bundle (for `<script>` tag)
- `dist/embed.min.js` — Minified IIFE
- `dist/embed.esm.js` — ES module (for `import`)
- `dist/index.d.ts` — TypeScript declarations

## Architecture

The SDK is a thin client-side wrapper (~4KB gzipped) that manages:

1. **iframe creation** — Loads the study at `{baseUrl}/s/{studyId}?embed=true`
2. **postMessage bridge** — Namespaced `versive:*` messages with origin validation
3. **Modal rendering** — Backdrop, close button, escape key, animations
4. **Inline rendering** — Auto-height via `versive:heightChange` messages
5. **Loading state** — Spinner with 10-second timeout

All study logic, AI moderation, and branding live server-side inside the iframe. The SDK never touches study content.