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) and small: the vanilla build never imports React, so Vue, Svelte, Angular, plain HTML, and Electron apps pay zero React tax.

Install

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):

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:

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>:

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:

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:

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.
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.
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