Skip to content

FlatFilers/obvious-feedback-sdk

Repository files navigation

Obvious Feedback SDK

Embeddable browser widget that lets users submit feedback from any web app. Feedback is routed to Obvious where it is triaged, tracked, and optionally auto-fixed by Autobuild.

Install

npm / yarn / pnpm / bun

npm install @obvi/feedback-sdk

Script tag (CDN)

<script
  src="https://cdn.jsdelivr.net/npm/@obvi/feedback-sdk@latest/dist/index.global.js"
  data-pub-key="fsk_pub_..."
></script>

Or via unpkg:

<script
  src="https://unpkg.com/@obvi/feedback-sdk@latest/dist/index.global.js"
  data-pub-key="fsk_pub_..."
></script>

The script auto-initializes the widget when data-pub-key is present.

Quick start

ES module

import { ObviousFeedback } from "@obvi/feedback-sdk";

const widget = ObviousFeedback.init({
  publicKey: "fsk_pub_...",
});

// Later: widget.destroy()

Script tag with options

<script
  src="https://cdn.jsdelivr.net/npm/@obvi/feedback-sdk@latest/dist/index.global.js"
  data-pub-key="fsk_pub_..."
  data-theme="dark"
  data-env="staging"
></script>

Configuration

Pass options to ObviousFeedback.init() or use data-* attributes on the script tag.

Option data-* attribute Type Default Description
publicKey data-pub-key string Required Your workspace feedback key.
apiBaseUrl data-api-base-url string https://api.app.obvious.ai Base URL for the Obvious API.
identityToken data-identity-token string n/a Signed JWT for verified identity (see below).
env data-env string production Environment label attached to submissions.
prNumber data-pr-number number n/a PR number for preview environment routing.
theme data-theme 'light' | 'dark' | 'system' light Widget color scheme.
triggerLabel data-trigger-label string Open feedback Tooltip text on the trigger button.
assistantPosition n/a 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' bottom-right Corner for the floating trigger.
redactSelectors n/a string[] [] CSS selectors for elements to redact from DOM snapshots.
capturePageContext n/a boolean false Include a redacted DOM snapshot with submissions.
captureConsole n/a boolean false Include recent console logs with submissions.
captureNetwork n/a boolean false Include recent network requests with submissions.
sessionReplayUrlResolver n/a () => string | null | Promise<string | null> n/a Returns a session replay URL (e.g. FullStory, LogRocket).
visualSuggestions n/a { enabled?: boolean } { enabled: false } Let reporters preview narrow visual changes before submit.
previewOnly n/a boolean false Show the widget in read-only mode without submitting.

Setup

1. Create a feedback key

In your Obvious workspace, go to Autobuild > Settings and create a Feedback SDK key. You'll get:

  • A public key (fsk_pub_...) — used in the browser SDK.
  • A private key (fsk_secret_...) — used server-side to sign identity tokens. Store it securely; it is only shown once.

Configure allowed domains to restrict which origins can submit feedback with this key.

2. (Optional) Verify user identity

To attach verified user information to feedback submissions, sign an identity token on your server using the private key:

import { SignJWT } from "jose";

const identityToken = await new SignJWT({
  identity: { email: user.email, name: user.name },
})
  .setProtectedHeader({ alg: "HS256", typ: "JWT" })
  .setSubject("fsk_pub_...")
  .setIssuedAt()
  .setExpirationTime("1h")
  .sign(new TextEncoder().encode("fsk_secret_..."));

Pass the resulting token as identityToken in the SDK config. If the token is missing or invalid, feedback is still accepted but marked as unverified.

Theming

The widget uses Shadow DOM and does not inherit host-page styles. Control appearance with:

Theme presets

ObviousFeedback.init({
  publicKey: "fsk_pub_...",
  theme: "dark", // 'light' (default) | 'dark' | 'system'
});
  • light — Always light. Safe for light-only host pages.
  • dark — Always dark.
  • system — Follows the browser prefers-color-scheme media query. Only use when the host page also follows system preference, otherwise the widget may be invisible against the background.

CSS custom properties

Override individual tokens on :root or the widget host element:

:root {
  --obv-feedback-bg: #fafafa;
  --obv-feedback-primary: #0066ff;
  --obv-feedback-text: #1a1a1a;
  --obv-feedback-border: rgba(0, 0, 0, 0.1);
}

Available tokens: --obv-feedback-bg, --obv-feedback-bg-subtle, --obv-feedback-trigger-bg, --obv-feedback-text, --obv-feedback-muted, --obv-feedback-border, --obv-feedback-border-strong, --obv-feedback-primary, --obv-feedback-primary-foreground, --obv-feedback-radius, --obv-feedback-radius-card.

API

ObviousFeedback.init(config): FeedbackSdkHandle

Initialize the widget. Only one instance can be active at a time; calling init again destroys the previous instance.

Returns a handle with:

Method Description
destroy() Remove the widget from the page.
open() Programmatically open the feedback card.
getOpenIssueCount() Number of non-terminal issues submitted in this session.
subscribeToOpenIssueCount(listener) Subscribe to open issue count changes. Returns an unsubscribe function.

Keyboard shortcut

Press Cmd/Ctrl + Shift + . to open the feedback card when the widget is active.

Attachments

Users can attach files (up to 25 MB each, 10 per submission) via drag-and-drop or the file picker in the widget. Attachments are uploaded directly to secure storage via pre-signed URLs.

Visual Suggestions

Visual suggestions are default-off for external consumers. Enable them when you want reporters to select a page element, preview a narrow style change live, and submit that intent with the feedback payload:

ObviousFeedback.init({
  publicKey: "fsk_pub_...",
  visualSuggestions: { enabled: true },
});

Submitted feedback includes context.visualSuggestions with { version: 1, suggestions: [...] }. The SDK only accepts font size, border radius, padding, gap, text color, and background color, and it rejects unsafe CSS syntax before applying or submitting a preview.

Local Dashboard Dogfood

Use a local package link to test SDK changes inside the Obvious dashboard before publishing:

cd /Users/alexolyaiy/Repositories/obvious-feedback-sdk
bun install
bun link
bun run dev

In the dashboard package:

cd /Users/alexolyaiy/Repositories/obvious/dashboard
bun link @obvi/feedback-sdk --no-save

Restart the dashboard so Vite reloads the linked package. Before committing dashboard dependency changes, remove the local link and depend on the published prerelease package.

Status polling

The widget tracks submitted issues and shows their current status (received, in progress, resolved, etc.) in the feedback card. Status is refreshed automatically when the card is opened.

Browser support

The SDK targets ES2020 and uses Shadow DOM, ResizeObserver, and crypto.randomUUID (with fallback). It works in all modern browsers (Chrome, Firefox, Safari, Edge).

Troubleshooting

Widget is invisible

If the widget trigger blends into the page background:

  • Check the theme setting. If your page is light-only, use theme: 'light' (the default), not 'system'.
  • On macOS with auto light/dark mode, theme: 'system' will switch the widget to dark when the OS is in dark mode, even if the host page stays light.

Content Security Policy (CSP)

In browsers that support constructable stylesheets, the widget applies its Shadow DOM CSS with adoptedStyleSheets, which avoids an inline <style> tag. Older browsers fall back to injecting a Shadow DOM <style> tag. If your CSP blocks inline styles in those fallback browsers, add 'unsafe-inline' to style-src for pages that load the widget.

Submissions rejected with 403

The feedback key's allowed domains must include the hostname where the SDK runs. Check your key configuration in Obvious.

License

MIT

About

Embeddable browser feedback widget — drop into any web app to collect user feedback

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors