Docs
JavaScript SDK
Programmatic widget API: open, identify, events, theming and TypeScript types.
Loading and the early-call queue
The loader is asynchronous. Define this small shim before your own code so calls made early are queued and replayed when the SDK loads:
<script>
window.FeedbackWidget = window.FeedbackWidget || {
_q: [],
open(...args) { this._q.push(['open', args]); },
onReady(callback) { this._q.push(['onReady', [callback]]); }
};
window.FeedbackWidget.onReady(() => {
window.FeedbackWidget.setTheme('auto');
});
</script>
Methods
| Method | Behavior |
|---|---|
init({ publicKey, theme, position, launcher }) | Programmatic alternative to data attributes. Safe to call repeatedly. |
open(tab, options?) | Open 'feedback', 'roadmap', 'changelog' or 'surveys'; optionally pass an item or survey id. |
close() | Close the panel and restore focus to where it was. |
toggle(tab?) | Toggle the panel open or closed. |
identify({ token }) | Pass a short-lived, server-signed identity token for your logged-in user. |
logout() | Clear the identified session from widget memory. |
setTheme('light' | 'dark' | 'auto') | Change the appearance at runtime. |
on(event, cb) / off(event, cb) | Listen to ready, open, close, vote, submit and surveyComplete. |
destroy() | Remove the launcher, iframe and all listeners. |
onReady(cb) | Run a callback once the SDK has initialized. |
Events
| Event | Payload |
|---|---|
ready | — |
open / close | { tab } |
vote | { feedbackId, voted } |
submit | { feedbackId } |
surveyComplete | { surveyId } |
const onVote = (e) => console.log('voted', e.feedbackId, e.voted);
window.FeedbackWidget.on('vote', onVote);
// later
window.FeedbackWidget.off('vote', onVote);
Programmatic init
Omit data-workspace and call init yourself. Repeated calls are safe and never create duplicate launchers.
window.FeedbackWidget.init({
publicKey: 'pub_YOUR_PUBLIC_WORKSPACE_KEY',
theme: 'auto', // 'light' | 'dark' | 'auto'
position: 'right', // 'right' | 'left'
launcher: true
});
TypeScript types
Save as feedback-widget.d.ts in your project:
export type FeedbackWidgetTab = 'feedback' | 'roadmap' | 'changelog' | 'surveys';
export type FeedbackWidgetTheme = 'light' | 'dark' | 'auto';
export interface FeedbackWidgetInitOptions {
publicKey: string;
theme?: FeedbackWidgetTheme;
position?: 'left' | 'right';
launcher?: boolean;
}
export interface FeedbackWidgetOpenOptions {
/** Open a specific feedback post or survey by its public id. */
id?: string;
}
export interface FeedbackWidgetEventMap {
ready: void;
open: { tab: FeedbackWidgetTab };
close: { tab: FeedbackWidgetTab };
vote: { feedbackId: string; voted: boolean };
submit: { feedbackId: string };
surveyComplete: { surveyId: string };
}
export interface FeedbackWidgetApi {
init(options: FeedbackWidgetInitOptions): void;
open(tab?: FeedbackWidgetTab, options?: FeedbackWidgetOpenOptions): void;
close(): void;
toggle(tab?: FeedbackWidgetTab): void;
/** Pass a short-lived token signed by YOUR server. Never sign in the browser. */
identify(params: { token: string }): Promise<void>;
logout(): void;
setTheme(theme: FeedbackWidgetTheme): void;
on<K extends keyof FeedbackWidgetEventMap>(event: K, cb: (payload: FeedbackWidgetEventMap[K]) => void): void;
off<K extends keyof FeedbackWidgetEventMap>(event: K, cb: (payload: FeedbackWidgetEventMap[K]) => void): void;
destroy(): void;
onReady(cb: () => void): void;
}
declare global {
interface Window { FeedbackWidget: FeedbackWidgetApi; }
}
export {};