Feedback Widget

Embed an in-app feedback capture widget in your web application.

The ProductSights feedback widget is a lightweight, embeddable component that captures user feedback directly inside your web application. Users can submit feedback without leaving the page, and every submission flows through the same AI triage pipeline as your other sources.

What it does

  • Floating button — a configurable button that opens a feedback panel
  • Feedback form — captures feedback text, optional name/email fields, and shared tags
  • Contextual capture — automatically includes the page URL and title where feedback was submitted
  • Success confirmation — shows a confirmation message after submission

Installation

Add the widget script to your site — just before </body> or anywhere in <head> with async:

<script
  src="https://productsights.io/widget.js"
  data-api-key="ps_your_api_key_here"
  async
></script>

The script auto-initializes when it detects a data-api-key attribute. No additional JavaScript is required.

Script-tag options

You can pass configuration via data-* attributes on the script tag:

<script
  src="https://productsights.io/widget.js"
  data-api-key="ps_your_api_key_here"
  data-position="bottom-left"
  data-button-text="Send feedback"
  data-button-color="#7C3AED"
  data-form-title="We'd love your feedback"
  data-show-name
  data-show-email
  data-show-category
  data-categories="Bug,Feature Request,Question"
  async
></script>

Manual initialization

If you prefer programmatic control, omit data-api-key from the script tag and call init() yourself:

<script src="https://productsights.io/widget.js" async></script>
<script>
  window.addEventListener('load', function () {
    ProductSights.init({
      apiKey: 'ps_your_api_key_here',
      position: 'bottom-right',
      buttonColor: '#4F46E5',
      formTitle: 'Share your feedback',
      showName: true,
      showEmail: true,
    });
  });
</script>

The global ProductSights object also exposes open(), close(), setUser({ name, email }), embed(), and destroy(). Use setUser() to prefill the optional name and email fields before opening the form.

Headless mode

If you want to trigger the feedback panel from your own button instead of the built-in floating button, use headless mode. The widget initializes without any visible UI — call open() when you're ready to show the form:

<script
  src="https://productsights.io/widget.js"
  data-api-key="ps_your_api_key_here"
  data-headless
  async
></script>

<button onclick="ProductSights.open()">Give feedback</button>

Or programmatically:

ProductSights.init({
  apiKey: 'ps_your_api_key_here',
  headless: true,
  formTitle: 'Tell us what you think',
  showName: true,
  showEmail: true,
});

document.getElementById('my-feedback-btn').addEventListener('click', () => {
  ProductSights.open();
});

Embed mode

To render the feedback form directly inside a container on your page — no floating button, no modal overlay — use embed():

<div id="feedback-form"></div>

<script src="https://productsights.io/widget.js" async></script>
<script>
  window.addEventListener('load', function () {
    ProductSights.embed('#feedback-form', {
      apiKey: 'ps_your_api_key_here',
      formTitle: 'Share your feedback',
      showName: true,
      showEmail: true,
      showCategory: true,
      buttonColor: '#7C3AED',
      onSubmit: function (response) {
        console.log('Submitted:', response.id);
      },
    });
  });
</script>

embed() accepts a CSS selector string or an HTMLElement as the first argument. The form renders inside a Shadow DOM to avoid style conflicts with your page. Set formTitle to an empty string to hide the heading.

Configuration

Optiondata-* attributeDescriptionDefault
apiKeydata-api-keyYour ProductSights API keyRequired
endpointdata-endpointCustom API endpoint (self-hosted)https://productsights.io
headlessdata-headlessSkip the floating button and open the form from your own UIfalse
positiondata-positionbottom-right, bottom-left, top-right, top-leftbottom-right
buttonTextdata-button-textText on the floating buttonFeedback
buttonColordata-button-colorBackground color of the button and form accent#4F46E5
textColordata-text-colorText color on the button#FFFFFF
formTitledata-form-titleHeading shown in the feedback panelShare your feedback
showNamedata-show-nameShow an optional name field in the formfalse
showEmaildata-show-emailShow an email field in the formfalse
showCategorydata-show-categoryShow a category dropdownfalse
categoriesdata-categoriesComma-separated list of categoriesBug,Feature Request,Question,Other
tagsdata-tagsComma-separated tags added to every submission
onSubmitJavaScript callback after a successful submission
onErrorJavaScript callback when a submission fails

How it works

  1. A user clicks the floating feedback button (or your own trigger, or interacts with an embedded form)
  2. The feedback form is shown (as a modal panel or inline, depending on mode)
  3. The user enters their feedback and any optional fields you enabled, like name, email, or category
  4. On submission, the widget sends the data to the /api/public/capture endpoint using your API key
  5. The feedback enters the AI triage pipeline — categorized, scored, and structured like any other source

API key

Generate an API key from Settings → API Keys in your ProductSights dashboard. For the widget, use a publishable key (ps_pub_ prefix) — it is safe to include in client-side code because it can only submit feedback, not read your data. You can optionally add domain restrictions to limit which sites can use the key.

The widget uses the same public capture endpoint as the browser extension and custom API capture clients.

API key owners must select their role/department during onboarding before widget submissions will be accepted.

Building from source

If you're working in the monorepo:

cd packages/widget
pnpm install
pnpm build

The build output is copied to apps/web/public/widget/ and served at /widget.js via a rewrite.

Rate limiting

The widget includes built-in client-side rate limiting (5 submissions per 60 seconds) to prevent abuse. Server-side rate limits also apply to the capture endpoint.

Docs Chat

Ask about ProductSights

Sign in to chat with our docs assistant

Sign in