Skip to content
UpVoiced Docs

UpVoiced Docs · Widget

Install the feedback widget

The widget puts your boards, roadmap and changelog inside your own site or app: a launcher opens a panel where people vote, post and see what shipped, without leaving the page. It is one script tag, under 20 KB compressed, and it never touches your page’s styles, cookies or storage.

1. Add the script tag

In the dashboard, open Settings → Widget and copy the snippet: it already contains your workspace slug. Paste it before </body> on every page that should show the widget.

<!-- UpVoiced widget: paste before </body> on every page that shows it. -->
<!-- Replace your-slug with your workspace slug (Settings → Widget shows the exact snippet). -->
<script async src="https://cdn.upvoiced.com/w.js" data-workspace="your-slug"></script>

The script is async: it never blocks your page. Launcher, position, colours and tabs come from your settings, so you don’t change the snippet when they change. If you want to call the JavaScript API before the script has loaded, add the queue stub first:

<!-- The queue stub lets you call UpVoiced before w.js has loaded; calls run in order once it has. -->
<script>
  window.UpVoiced = window.UpVoiced || { q: [] };
  ['identify', 'config', 'open', 'close', 'on', 'track'].forEach(function (m) {
    window.UpVoiced[m] =
      window.UpVoiced[m] ||
      function () {
        window.UpVoiced.q.push([m].concat([].slice.call(arguments)));
      };
  });
  UpVoiced.on('ready', function () {
    document.documentElement.setAttribute('data-feedback-ready', 'yes');
  });
</script>
<script async src="https://cdn.upvoiced.com/w.js" data-workspace="your-slug"></script>

Using React, Next.js, Vue, Nuxt, Svelte, Angular, Webflow or WordPress? Seeframeworks and site builders.

2. Allow your site’s origin

For security the widget only lets people sign in, vote and post from sites you list. In Settings → Widget → Allowed origins, add the exact origin of each site: scheme, host and port, as your browser’s address bar shows it before the first /. Only owners and admins can change the list; members see it read-only.

https://app.example.com        ✓ exact scheme and host
https://app.example.com:8443   ✓ with a port
http://localhost:3000          ✓ local development (http only for localhost, 127.0.0.1, [::1])
https://*.example.com          ✗ no wildcards: add each subdomain
https://example.com/app        ✗ no paths
http://app.example.com         ✗ plain http
  • Until you add a site, the widget there still shows your public boards, but signing in, voting and posting are refused. Your own portal (https://your-slug.upvoiced.com) is always allowed and needs no entry; other UpVoiced addresses can’t be listed.
  • The dashboard checks each entry with the same rules as the API and saves it in its normal form (lower case, default port and trailing slash removed). Up to 50 origins.
  • Removing an origin takes effect at once. Browsers may keep an allowed preflight for up to 10 minutes, but every request is checked again.
  • From a site that isn’t listed, the API answers 403 origin_denied without CORS headers, so the browser console shows a CORS error and UpVoiced.identifyresolves { ok: false, error: "network_error" }.

3. Tabs, launcher and theme

Settings → Widget → Tabs and launcher chooses the tabs (Feedback, Roadmap, What’s new), the launcher (pill, icon or side tab) and its position, with a preview in light and dark. Colours, font and corner radius follow Settings → Brandingand pass the contrast guard. Changes reach visitors within about a minute (the settings are cached briefly). The Roadmap tab shows only while your public roadmap is on.

A page can override the look with attributes on the script tag; anything not listed, or not valid, is ignored. UpVoiced.config() overrides both (API reference).

Script tag attributes
AttributeValuesExample
data-workspaceYour workspace slug. Required.acme
data-launchericon, pill, tab (a side tab on the edge of the page) or none (no launcher; open the panel from your own button).pill
data-positionbottom-right, bottom-left, right-middle or left-middle.bottom-right
data-offsetDistance from the edge in px, 0–200: one number for both axes or "x,y".16
data-themelight, dark or auto (follows the visitor’s system setting).auto
data-accentA #rrggbb colour. It goes through the same contrast guard as your branding, so text stays readable.#2f63c4
data-radiusnone, sm, md, lg or full.md
data-mountA CSS selector. The panel renders inside that element, always open, with no launcher.#feedback
data-nonceYour page’s CSP nonce (see the strict CSP guide).—

Inline instead of floating

With data-mount the panel renders inside your element, always open, with no launcher or close button. Useful for a “Feedback” page in your app:

<section id="feedback" aria-label="Feedback"></section>
<script async src="https://cdn.upvoiced.com/w.js" data-workspace="your-slug" data-mount="#feedback"></script>

4. Sign people in with your app’s account

Without more setup, visitors confirm their email with a 6-digit code inside the panel the first time they vote or post. If they are already signed in to your app, your server can sign a short-lived token so they never see that step:identify signed-in users.

What the widget does on your page

  • Adds one <uv-widget> element with a Shadow DOM; its styles can’t leak into your page and yours can’t break it. No global CSS, no inline styles on your elements.
  • Reads no cookies, localStorage or sessionStorage; a signed-in session lives in memory only. No eval.
  • Loads its panel script only when someone opens it. Keyboard and screen-reader accessible (WCAG 2.2 AA), respects reduced motion, in English, Portuguese (Brazil), Spanish, German or French, following your portal language.
  • Talks to https://api.upvoiced.com and loads scripts from https://cdn.upvoiced.com; allow both if your site has a Content Security Policy (strict CSP guide).

Troubleshooting

SymptomCheck
No launcher appearsThe slug in data-workspace (the console warns when it is missing or invalid), that the script loads (network tab), and data-launcher="none".
People can read but not vote, post or sign inAdd the page’s exact origin under Allowed origins (step 2).
A tab is missingThe tab is off in Settings → Widget, the roadmap is not public, or the page narrowed the tabs with UpVoiced.config({ tabs }).
Blocked by Content Security PolicyFollow the strict CSP guide.