Skip to content
On this page

Guides

Web widgetComing soon

Add a problem form to your site, and links that open your board, with the @shipbell/widget package.

InstallComing soon

Install the package from npm with an exact version:

Shell
npm install --save-exact @shipbell/widget

Create the widget when your app starts, so it can record errors from the whole session. The form itself loads through your bundler's dynamic import() the first time it opens.

TypeScript
import { createFeedback } from '@shipbell/widget';

const feedback = createFeedback({ projectKey: 'sb_pk_live_…', apiOrigin: 'https://api.shipbell.app' });

feedback.identify({
  getToken: async () => {
    const response = await fetch('/api/feedback/token', { method: 'POST' });

    return (await response.json()).token;
  }
});

feedback.open();
feedback.openBoard('/');
feedback.openBoard('/roadmap');
feedback.openBoard('/me/reports');

Connect your sign-in

Pass a getToken function to identify. The widget calls it only when it needs a session, when the form opens or sends, and it returns a token from your backend. See Sign your users in.

When the signed-in user changes in your app, call setUser with the new id, or with null after sign-out, so the widget drops its session. reset() clears it too.

Commands

The npm methods and the script tag commands have the same names:

CommandWhat it does
open({ prefill, sentryEventId })Opens the problem form
openBoard(path)Opens the board, signed in: /, /new, /roadmap, /problems or /me/reports
identify({ getToken })Connects your sign-in. getToken is called only when needed
setUser(id | null), reset()Drops the session when your user changes
setContext(object | () => object)Adds context to reports. A function runs when the report is sent. At most 16 KB, and shown to the user
setTheme('light' | 'dark' | 'auto')Sets the colour scheme
configure({ … })errors (full, metadata or off), route, release, environment, redactSelectors and sentry.eventIds
on('submitted' | 'open' | 'close', callback)Listens to widget events
unreadThe number of unread updates, for a badge

Script tagComing soon

For sites that do not use npm, the widget will also come as a pinned script tag with Subresource Integrity. Replace <version> and the integrity value with the ones for the release you use.

HTML
<script async src="https://widget.shipbell.app/<version>/widget.js"
        integrity="sha384-…" crossorigin="anonymous"
        data-project="sb_pk_live_…"></script>
<script>
  window.Shipbell = window.Shipbell || function () { (Shipbell.q = Shipbell.q || []).push(arguments) };
  Shipbell('identify', { getToken: async () => /* call your backend */ '' });
</script>

What the form shows

  • A required "What went wrong?" field, and a file you can attach or paste (PNG, JPEG or WebP).
  • "Who can see this report?", with a public and a private choice, preselected from your project's settings. A project that keeps every report private shows one line instead.
  • "Sending as", with the user's name or email address.
  • "Included with your report (only the team sees this)", which lists every detail that is sent.
  • After sending: the reference number, how a reply will arrive and, for a public report, a link to it on the board.
  • Links to "Your reports", "Suggest an idea" and "See what we're working on", each shown only when that part of the board is on.

If sending fails, the draft stays while the page is open, with a Retry button and a "Copy text" fallback.

What the widget collects

  • The widget version, and your release and environment
  • The origin and route, without the query and the hash, or the route your route() function returns
  • The browser's user agent and, where available, its low-entropy brands
  • Languages and time zone
  • Viewport, screen size and pixel ratio
  • Colour scheme, reduced motion, standalone display mode and whether the browser is online
  • The last 20 errors and unhandled promise rejections
  • Sentry event ids, only from your own sentry.eventIds() function

It never sends the referrer and does not capture the console. The widget has no Sentry dependency.

Theming

The widget lives in its own shadow DOM and follows these CSS custom properties from your page. Your project's branding only sets their defaults.

  • --shipbell-accent
  • --shipbell-bg
  • --shipbell-fg
  • --shipbell-muted
  • --shipbell-radius
  • --shipbell-font (default inherit)
  • --shipbell-z-launcher

Content Security Policy

The widget works under a strict policy: it uses no inline styles and no eval. Add these sources to your policy:

  • connect-src https://api.shipbell.app and img-src blob:, for the screenshot preview.
  • For the script tag, also script-src https://widget.shipbell.app and style-src https://widget.shipbell.app.