JavaScript
One script tag puts a feedback button at the corner of your pages. It opens your widget in a panel, with your user already signed in.
Add the script#
Your portal serves the script. Copy the tag from Settings → Widget, under Install, or write it with your portal's address:
<script src="https://acme.example.com/widget/v1.js" data-token-url="/feedback-token" async></script>The button takes your widget's accent color, and sits on the side you chose under Settings → Widget. It opens a panel with your widget: feedback, the roadmap and the changelog, as on your portal. On a phone, the panel takes the screen above the button. Escape closes it.
The script loads nothing more until the button is pressed, but its settings: your portal's colors and the button's side, in the reader's language.
Sign your user in#
data-token-url names an endpoint of your server. Each time the widget opens, the script asks it for the signed-in
user's identity token, with your page's cookies:
- Answer
{ "token": "…" }with a token your server signs: Signing in your users shows how. - Answer
{ "token": null }, a 401 or a 403 when nobody is signed in. The widget then ends the session of a user it had, and keeps a guest's.
Without data-token-url, people read the widget, and writing asks them to sign in to your product, or to continue as
guests where your portal takes them.
Options#
| Attribute | What it does |
|---|---|
data-token-url | The endpoint that answers with the signed-in user's identity token. |
data-launcher="false" | No button: your own control calls Swingback.open(). A close button shows while the panel is open. |
data-manual | Nothing starts until your page calls Swingback.init({ ... }). |
From your code#
Once loaded, the script is window.Swingback:
Swingback.open(); // the feedback
Swingback.open("changelog"); // or "roadmap", "new", { post: "dark-mode" }, { board: "ideas" }
Swingback.close();
Swingback.identify(); // after your user signs in or out: the widget asks for a token again
Swingback.logout(); // ends the widget's session, a guest's too
Swingback.on("error", (event) => console.warn("Feedback widget:", event.code));Its events are ready, identified, signed-out, error, open and close. An error has the code of
the widget's errors, or token_unavailable when your endpoint couldn't be asked.
Content Security Policy#
If your pages send one, allow your portal's address in script-src (the script), connect-src (its settings) and
frame-src (the widget). The button needs no inline style. A browser too old to adopt a stylesheet gets a <style>
element instead, with the script tag's own nonce, if it has one.
The npm package#
The same widget, from your bundle:
import { createSwingback, embed } from "@swingback/js";
const swingback = createSwingback({
portal: "https://acme.example.com",
tokenUrl: "/feedback-token", // or token: async () => (await yourApi.feedbackToken()) ?? null
});
swingback.open("roadmap");
// Or the widget inside an element of your page, filling it:
embed(document.getElementById("feedback"), { portal: "https://acme.example.com", tokenUrl: "/feedback-token" });For React, see the React SDK.
