Widget Integration
Embed the FWD Hub widget on your website with a single script tag. Optionally pass user identity for a seamless, personalized support experience.
Installation
Add the loader script to your HTML. The data-workspace attribute must match your workspace slug from the FWD Hub dashboard.
<script
src="https://hub.flyweight.dev/widget/loader.js"
data-workspace="your-workspace-slug"
></script>The script creates a floating launcher button and loads the widget in an iframe. It works on any website — static HTML, React, Vue, Next.js, WordPress, etc. No build step required.
Single-Page Apps
The loader automatically tracks client-side navigation by intercepting pushState, replaceState, and popstate. No extra configuration needed for React Router, Next.js, Vue Router, or similar.
Next.js
Use the Next.js Script component for optimal loading:
import Script from "next/script";
export default function Layout({ children }) {
return (
<html>
<body>
{children}
<Script
src="https://hub.flyweight.dev/widget/loader.js"
data-workspace="your-workspace-slug"
strategy="lazyOnload"
/>
</body>
</html>
);
}JavaScript API
The loader exposes a global window.FWDHub object with the following methods:
Open the widget. Optionally pass a module name to open a specific tab: "messages", "help", "feedback", or "changelog".
// Open the widget
FWDHub.open();
// Open directly to the feedback tab
FWDHub.open("feedback");Close the widget.
Identify the current user. See User Identification below.
Remove the widget from the page entirely. Useful for cleanup on logout or when navigating to pages where the widget shouldn't appear.
User Identification
By default, visitors must enter their name and email before they can send messages or feedback. If your app already knows who the user is (they're logged in), you can pass their identity to the widget programmatically — skipping the identification form entirely.
FWDHub.identify({
userId: "usr_123", // Required — your system's user ID
name: "Jane Doe", // Optional — display name
email: "jane@example.com", // Optional — email address
avatarUrl: "https://...", // Optional — profile picture URL
customData: { // Optional — any metadata
plan: "pro",
company: "Acme Inc"
}
});| Property | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | Your application's unique user ID. Used to link widget visitors to your user records. |
| name | string | No | Display name shown in conversations. |
| string | No | Email address for notifications and identification. | |
| avatarUrl | string | No | URL to the user's profile picture. |
| hmac | string | No* | HMAC-SHA256 signature for secure identification. Required if your workspace has HMAC verification enabled. |
| customData | object | No | Arbitrary key-value data attached to the visitor (plan, company, etc.). |
Timing
You can call FWDHub.identify() at any time — before or after the widget has loaded. If called before the widget iframe is ready, the data is queued and sent automatically once the widget initializes.
When both name and email are provided (either via identify() or the manual form), the visitor is considered identified and can access Messages and Feedback without the form prompt.
Example: React App
import { useEffect } from "react";
import { useUser } from "./auth"; // your auth hook
function App() {
const user = useUser();
useEffect(() => {
if (user && window.FWDHub) {
FWDHub.identify({
userId: user.id,
name: user.name,
email: user.email,
avatarUrl: user.avatarUrl,
customData: {
plan: user.plan,
role: user.role,
},
});
}
}, [user]);
return <div>...</div>;
}HMAC Verification
HMAC verification prevents user impersonation. When enabled, the widget will reject identify() calls that don't include a valid HMAC signature. This ensures that only your server can identify users.
Setup
1. Go to your workspace Settings → API & Security in the dashboard.
2. Generate an HMAC secret. Keep this secret server-side only — never expose it in client-side code.
3. On your server, compute the HMAC-SHA256 of the userId using your secret, and pass it to the widget.
Server-Side Signature
import crypto from "crypto";
function generateHmac(userId, secret) {
return crypto
.createHmac("sha256", secret)
.update(userId)
.digest("hex");
}
// In your API endpoint:
const hmac = generateHmac(user.id, process.env.FWD_HUB_HMAC_SECRET);
// Pass this hmac to your frontendClient-Side Usage
// hmac comes from your server, NOT computed client-side
FWDHub.identify({
userId: "usr_123",
name: "Jane Doe",
email: "jane@example.com",
hmac: hmacFromServer,
});When HMAC verification is enabled on your workspace and a visitor calls identify() without a valid hmac, the call will be rejected with an error.
Modules
The widget includes four modules. Each can be enabled or disabled from your workspace settings in the dashboard.
Real-time conversations between visitors and your team. Supports file attachments and screenshot capture.
Searchable knowledge base organized into collections and articles. Full-text search included.
Feature requests and bug reports from visitors. Conversations are threaded for follow-up.
Product updates categorized as New, Improved, or Fixed. Tracks read state per visitor.