9 kB gzipped · no audio stored

Let people say what they think.

A feedback widget for any website. Visitors type — or tap the microphone and speak. Their browser turns speech into text they can edit before sending. Two script tags to install.

Voice input uses the browser’s own speech recognition. Where a browser doesn’t support it, typing still works.

This page has one

The widget in the corner is the real product, not a screenshot. Open it and tell us what you think — by typing, or by speaking.

Your browser will ask before the microphone is used.

Install
<script src="https://feedback.embarko.app/widget.js"></script>
<script>
  FeedbackWidget.init({
    widgetId: "widget_..."
  });
</script>

How it works

Type it or say it, review it, send it

Voice is an input method, not a separate kind of feedback. That one decision keeps the interface to a single field people already understand.

  1. 1

    See

    A small launcher sits in the corner. One click opens it — no page navigation, no modal takeover unless you want one.

  2. 2

    Speak or type

    One text field. The microphone is just another way to fill it, so there is no choice to make between “text feedback” and “voice feedback”.

  3. 3

    Review

    Speech lands as editable text. People fix a misheard word, add a sentence, or delete the lot and start again.

  4. 4

    Send

    Only the final text they chose to submit is stored. If the network fails, their words stay on screen with a retry.

Built in

The unglamorous parts, done

The things that decide whether a third-party widget is safe to put on a real site.

Won't touch your CSS

The widget renders inside a Shadow DOM. Your styles can't reach in and its styles can't leak out — tested against a page that tries.

9 kB gzipped

No framework, no dependencies, nothing fetched at runtime. The build fails if the bundle ever grows past its budget.

Degrades honestly

No speech support, a blocked microphone, a failed request — each says what happened and leaves the person able to type and retry.

Keyboard and screen reader

Focus management, Escape to close, labelled controls, and microphone state announced rather than shown only in colour.

Works on phones

A bottom sheet sized for thumbs, inputs that don't trigger zoom, and drag support if you let people move the launcher.

Locked to your domains

An allowlist decides which origins may submit, enforced on the server. Rate limiting comes as standard.

Privacy

The audio never leaves the page

Speech is transcribed by the visitor's own browser. Nothing is recorded, nothing is uploaded, and there is no audio file to leak, subpoena or forget to delete.

  • Only the text a person chooses to submit is stored.
  • Metadata is opt-in per widget — turn a field off and the widget stops sending it.
  • The microphone is only live while someone is actually speaking, and says so clearly.
What actually travels
  1. Someone speaksin the browser
  2. Browser speech recognitionon their device
  3. Editable textthey can change it
  4. They press sendtheir decision
  5. Text storedand nothing else

No audio is recorded or transmitted at any point.

Configuration

Change it without touching their site

Appearance, position, copy and behaviour all come from the server. Your customers paste the snippet once; after that you change things from the dashboard and their pages pick it up.

Appearance

Theme, colours, radius, font, launcher style, size.

Position

Four corners, centred, or draggable by the visitor.

Content

Every visible string, so it can be translated per widget.

Behaviour

Backdrop, click-outside, auto-open, character limit.

The dashboard previews changes with the real widget running beside the settings, not a picture of one.

Install

Two script tags

Drop it in before the closing body tag. It loads asynchronously and never blocks rendering.

Add to any page
<script src="https://feedback.embarko.app/widget.js"></script>
<script>
  FeedbackWidget.init({
    widgetId: "widget_..."
  });
</script>

Drive it from your own code

FeedbackWidget.open();
FeedbackWidget.close();
FeedbackWidget.destroy();

FeedbackWidget.on("submit", ({ id, source }) => {
  analytics.track("feedback", { id, source });
});

source is text, voice or mixed, so you can see how people actually prefer to give feedback.

Find out what your users would tell you

Create a widget, paste two script tags, and read what comes back.