Feedback Fin

A tiny widget to collect feedback anywhere on your website. That’s it.


npm version Package size

Demo GIF

Try the widget ↗

Quick Start

  1. Load the widget on your page:

    <script src="[email protected]^1" defer></script>
  2. Configure with a webhook URL and optionally, add user info:

      window.feedbackfin = { config: {}, ...window.feedbackfin };
      window.feedbackfin.config.url = "";
      window.feedbackfin.config.user = { name: "...", email: "..." };
  3. Set a button to open the widget:

    <button data-feedbackfin-button>Feedback</button>

Setting up a webhook URL

This is the URL to send the feedback to. The widget will make a POST request to this URL with the feedback data as a JSON body.

Generate a webhook URL and view the feedback in a spreadsheet UI using Rowy. Learn how  ↗


Options are set in the window.feedbackfin.config object:


The URL to send the feedback to. The widget will make a POST request to this URL with the data as a JSON body. See Setting up a webhook URL above.


An object whose contents will be submitted as part of the form. Note: feedbackType, message, and timestamp are reserved fields and will be overwritten by form values.


window.feedbackfin.config.user = {
  name: "...",
  email: "...",


Optionally, disables displaying alerts if no URL is set or the request fails. Default: disableErrorAlert: false

How it works

When the script is loaded, it looks for any elements with the data-feedbackfin-button attribute and opens the widget when any of those elements are clicked.

<button data-feedbackfin-button>Feedback</button>

The window.feedbackfin object exposes the open, close, and submit methods, so they can also be called directly.

<button onclick="">Feedback</button>

The widget uses to compute its position using Floating UI.


The widget is attached just before the closing </body> tag when it is open and respects your page’s font-family. Styles are attached just before the opening <head> tag so your customizations take precedence.

You can customize the widget’s appearance by:

  • Overriding the CSS variables.

    For example, you can change the primary button color using:

    :root {
      --feedbackfin-primary-color: #007aff;
      --feedbackfin-primary-color-text: #fff;
  • Overriding the CSS rules. Class names are prefixed with feedbackfin__.

Dark mode

Dark mode is activated when either:

  • the user sets their system theme to dark i.e. @media (prefers-color-scheme: dark) is true, or

  • any parent element has a data-theme attribute whose value contains dark. Example: <body data-theme="dark">

Dark mode colors are set using CSS variables. You can override them with:

@media (prefers-color-scheme: dark) {
  :root {

[data-theme*="dark"] {


This widget is built using standard HTML form elements with the appropriate labels.

Focus is trapped within the widget when it is open using focus-trap.


Contribute to Feedback Fin with issues and pull requests in the GitHub repo.



View Github