Docs › Widget

Put your board on your own site with the widget

A launcher on your page, a side panel with your board inside it: ideas, the roadmap and announcements, with an unread count on the launcher. Two script tags, no build step. The panel is the board itself, so what visitors can do there is exactly what they can do on the board.


1. Install

An admin opens Settings → Widget, clicks Create widget and copies the snippet from the Implementation tab. It names the widget by its address; every widget has its own, so a second site or a staging build can have its own look. Place it before the closing </body> tag of every page the launcher should appear on:

On your page
<script>
  window.KjerrWidget = window.KjerrWidget || function () {
    (window.KjerrWidget.q = window.KjerrWidget.q || []).push(arguments);
  };
  KjerrWidget('init', {
    widget: 'https://acme.kjerr.io/widget/x3aso1k9p2',   // from Settings → Widget → Implementation
    selector: '.kjerr-widget',                        // badge launcher only: where the counter goes
    lang: 'en'                                        // optional
  });
</script>
<script async src="https://kjerr.io/static/widget.js"></script>

The first script line is a queue, so the call can run before widget.js has loaded. The launcher appears once the panel has loaded in the background, which is also when the unread count is known.

Allowed sites. Under Layout & General Configuration you can list the sites the widget may be shown on (example.com, *.example.com or https://example.com). Anywhere else the browser refuses to show the panel. Leave the list empty and any site may show it.

Your own Content-Security-Policy. If your page sends one, allow script-src https://kjerr.io and frame-src https://yourname.kjerr.io. The launcher is styled from JavaScript, so no style-src change is needed.

2. Launcher types

BadgeA small counter on an element of your own page, picked by the selector in the snippet.
ButtonA round button floating in a corner of every page.
Side tabA tab stuck to the edge of the screen.
NoneNothing is drawn. Open the widget from your own code with KjerrWidget('open').

The badge type needs the selector option: a CSS selector for the element on your page the counter goes into, usually a “What's new?” link in your navigation. Clicking that element opens the panel. Badge colour, animation, a minimal dot instead of a number, a count on your favicon and hiding the badge when everything is read are all under the Launcher tab, and the preview beside the form shows the result as you change it.

3. Identify your users

Visitors can read everything without signing in. To vote, post an idea or comment they need an identity, and on a board in SSO mode the panel cannot send them to your login page (a login page will not load inside a frame). Hand the widget the same signed token your board's single sign-on uses, and they are signed in before they click:

With a signed-in user
KjerrWidget('init', {
  widget: 'https://acme.kjerr.io/widget/x3aso1k9p2',
  ssoToken: '<token signed by your backend>'   // the same HS256 JWT as /docs/sso
});

// or later, once the user signs in to your product:
KjerrWidget('identify', { ssoToken: '<token>' });

How to mint the token, and what it may carry (name, avatar, company, plan, language), is in the SSO documentation. The token travels in a POST into the panel, never in a URL, and is spent on first use. On a board in standalone mode visitors sign in or create an account inside the panel instead.

Who is counted as having read what. Opening the panel marks every announcement published so far as read. For an identified visitor that is remembered on their profile, on every device. For an anonymous visitor it is remembered in that browser, on that site. A first visit counts the announcements of the last 30 days.

4. Languages

Pass lang (one of ar, de, en, es, fr, it, ko, pl, pt, ro, zh) and the panel opens in that language; without it the board's own rule applies: the visitor's last pick, the browser's language if the workspace allows it, else the workspace language. A language claim in the SSO token does the same. What is translated is what the board translates: the interface, and ideas, topics, statuses and comments when Settings → Language says so. Announcements are shown as written.

5. Styling

The Style tab has six preset palettes and four colours of your own: primary (buttons and the header), secondary (borders), card background and text. Picking a preset fills the four; changing one makes the palette “Custom”. A dark card background switches the panel to dark mode.

Custom CSS is applied inside the panel after Kjerr's own styles. The parts of the shell have stable class names:

Hooks for your stylesheet
/* the header band and its title */
.wg-head { }
.wg-head-name { }
/* the tabs across the top */
.wg-tabs { } .wg-tab { } .wg-tab[aria-current="page"] { }
/* the content area and the Home blocks */
.wg-main { } .wg-block { } .wg-block-h { }
/* the tokens the panel is painted with */
html { --wg-primary: #3778FF; --wg-secondary: #D9E8FF; --wg-card: #FFFFFF; --wg-text: #667D9F; }

The board's own parts keep their names too (.idea-row, .roadmap-col, .post). The stylesheet may not close the style element or pull in another one with @import.

6. JavaScript API

Commands
KjerrWidget('open');                       // open the panel
KjerrWidget('open', { path: '/roadmap' });  // open it on a section: /home, /announcements, /ideas, /roadmap
KjerrWidget('close');
KjerrWidget('toggle');
KjerrWidget('unread');                     // the number of unread announcements, right now
KjerrWidget('on', 'unread', function (n) { /* the count changed */ });
KjerrWidget('on', 'open', function () {});
KjerrWidget('on', 'close', function () {});
KjerrWidget('survey');                     // show the NPS card now, if one is due for this visitor
KjerrWidget('on', 'survey', function (state) { /* 'open' or 'close' */ });

With the launcher type None nothing is drawn on your page and these calls are the only way in: wire KjerrWidget('open') to your own button and KjerrWidget('unread') to your own counter.

7. The NPS survey

A survey from Settings → NPS survey is delivered by the same snippet: when the panel loads it tells the loader whether this visitor is due a card, and after the survey's delay the loader opens /widget/<key>/survey/<survey> in a small frame in the bottom-right corner, painted with the widget's colours and signed in as the panel is. Picking a number records the score at once; the follow-up and the thank-you follow in the same frame, which then goes away by itself.

Page rules are checked on your page, where the address is known: a rule starting with / is matched against the path (/app/*), anything else against the whole address (https://example.com/account*); * stands for anything. Who is asked decides whether a visitor without an SSO token sees the card at all; the cooldown for such a visitor lives in a cookie of the frame, the cooldown for an identified user on their record.

Your own trigger. KjerrWidget('survey') shows the card now, if one is due, ignoring the delay and the page rules: after onboarding, after a support chat, when a feature was used. It returns true when a card opened. Nothing is shown for a visitor who answered within the survey's cadence.

Every answer reaches your other tools through a webhook on the event nps.response (see the API docs) with the score, its group, the comment, the page and the person when known.

8. Troubleshooting

Questions: hello@kjerr.io