# Feedback widget (@usero/sdk)

A drop-in feedback button for the web. Vanilla JS, React component, or a `<script>` tag. The widget renders a floating button;
users click it to leave a 1 to 4 rating, an optional comment, and optional screenshots. Everything lands in your [dashboard](/)
automatically.

The package is open source ([github.com/usero-feedback/usero](https://github.com/usero-feedback/usero)) and small: the vanilla
build never imports React, so Vue, Svelte, Angular, plain HTML, and Electron apps pay zero React tax.

## Install

```bash title=npm
npm install @usero/sdk
```

## React

Mount it once in your root layout (it renders a fixed-position floating button, so do not put it inside individual pages):

```tsx title=React
import { UseroFeedbackWidget } from '@usero/sdk/react'

export function App() {
	return (
		<>
			{/* your app */}
			<UseroFeedbackWidget clientId='YOUR_CLIENT_ID' environment={process.env.NODE_ENV} />
		</>
	)
}
```

## Vanilla JS (Vue, Svelte, Angular, Astro, Electron, anything)

Call it once at app startup:

```ts title=Vanilla
import { initUseroFeedbackWidget } from '@usero/sdk'

const widget = initUseroFeedbackWidget({
	clientId: 'YOUR_CLIENT_ID',
	environment: import.meta.env.MODE,
})

// later, if you need to remove it:
widget.destroy()
```

## Script tag (CDN, no bundler)

Add these two tags just before `</body>`:

```html title=Script tag
<script src="https://unpkg.com/@usero/sdk"></script>
<script>
	Usero.initUseroFeedbackWidget({ clientId: 'YOUR_CLIENT_ID' })
</script>
```

`unpkg` and `jsDelivr` both serve the IIFE bundle automatically.

> [!WARNING] **Omit the `environment` option for your default environment.** Do not pass a placeholder like `"no-env"` or
> `"default"`. The dashboard treats an absent environment as the default; a placeholder string creates a separate environment and
> your feedback will not appear in the default inbox.

## Identify your users (optional)

The widget works fully anonymous. If you have a logged-in user, identifying them lights up "who is this person" on session replays
and lets you filter feedback by email in the dashboard.

React: pass the `user` prop (omit or pass `null` for logged-out visitors). The widget re-identifies automatically when the prop
changes:

```tsx title=React
<UseroFeedbackWidget
	clientId='YOUR_CLIENT_ID'
	user={{ id: currentUser.id, email: currentUser.email, displayName: currentUser.name }}
/>
```

Vanilla: pass a `getUser` callback, called at session start:

```ts title=Vanilla
initUseroFeedbackWidget({
	clientId: 'YOUR_CLIENT_ID',
	getUser: () => (currentUser ? { id: currentUser.id, email: currentUser.email } : null),
})
```

## Options

| Option                 | Type                      | Default                                  | Description                                                                                                                                                                                       |
| ---------------------- | ------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId`             | `string`                  | required                                 | Your Usero client id. See [Find your clientId](/docs/find-your-client-id).                                                                                                                        |
| `position`             | `'left' \| 'right'`       | `'right'`                                | Which side of the viewport the button sits on.                                                                                                                                                    |
| `theme`                | `Partial<WidgetTheme>`    | auto                                     | Override colors. By default the widget follows the OS color scheme (`prefers-color-scheme`), with dark as the fallback. Explicit values win; partial overrides merge on top of the detected base. |
| `title`                | `string`                  | `'Share Feedback'`                       | Panel header.                                                                                                                                                                                     |
| `placeholder`          | `string`                  | `'Tell us what you think... (optional)'` | Comment placeholder.                                                                                                                                                                              |
| `showEmailOption`      | `boolean`                 | `true`                                   | Show the "share my email" checkbox.                                                                                                                                                               |
| `showScreenshotOption` | `boolean`                 | `true`                                   | Show the screenshot upload button (up to 3 images, 10MB each).                                                                                                                                    |
| `environment`          | `string`                  | undefined                                | Tag feedback with an environment. Omit for your default environment, see the warning above.                                                                                                       |
| `metadata`             | `Record<string, unknown>` | undefined                                | Arbitrary metadata attached to every submission.                                                                                                                                                  |
| `baseUrl`              | `string`                  | `'https://usero.io'`                     | Override the API host (self-hosted Usero).                                                                                                                                                        |
| `plugins`              | `UseroPlugin[]`           | undefined                                | Opt-in plugins, for example [session replay](/docs/widget/session-replay).                                                                                                                        |
| `getUser`              | `() => User \| null`      | undefined                                | Vanilla only. Returns the current logged-in user (or null for anonymous). React uses the `user` prop instead.                                                                                     |
| `onSubmit`             | `(data) => void`          | undefined                                | Fires after a successful submission.                                                                                                                                                              |
| `onError`              | `(err: Error) => void`    | undefined                                | Fires on init or submission error.                                                                                                                                                                |
| `onOpen` / `onClose`   | `() => void`              | undefined                                | Fire when the panel opens or closes.                                                                                                                                                              |

## Content Security Policy

If your app has a strict CSP, allow `https://usero.io` in `connect-src` (and `https://unpkg.com` in `script-src` if you use the
script tag). The widget makes no other cross-origin requests.

## Next

- [Session replay plugin](/docs/widget/session-replay): attach a recording of the last 30 seconds to each feedback
- [POST /api/feedback](/docs/api/feedback): the API the widget submits to, if you would rather build your own UI
