Documentation
Everything you need to integrate FeatureBot into your product. From widget installation to webhooks and the JavaScript API.
Widget Installation
Basic Installation
Add this snippet before the closing </body> tag on every page where you want the widget to appear.
<script async src="https://cdn.featurebot.com/widget.js" data-key="YOUR_PUBLIC_KEY" ></script>
Replace YOUR_PUBLIC_KEY with your workspace public key from Settings → Install.
With User Context
Pass user information to enable personalization, MRR tracking, and segment-based analytics.
<script
async
src="https://cdn.featurebot.com/widget.js"
data-key="YOUR_PUBLIC_KEY"
data-user-id="USER_ID"
data-email="USER_EMAIL"
data-name="USER_NAME"
data-plan="PLAN_NAME"
data-mrr="MRR_IN_CENTS"
data-company="COMPANY_NAME"
data-role="USER_ROLE"
data-company-size="COMPANY_SIZE"
data-attributes='{"key": "value"}'
></script>Available Attributes:
data-user-id- Your internal user IDdata-email- User's email addressdata-name- User's display namedata-plan- Subscription plan name (e.g., "Pro", "Enterprise")data-mrr- Monthly recurring revenue in centsdata-company- Company or organization namedata-role- User's role in the company (e.g., "Admin", "Developer")data-company-size- Company size or headcount (e.g., "10-50", "Enterprise")data-attributes- JSON string of custom key-value pairs
Single Page Applications
For React, Vue, Angular, or other SPAs where the user logs in after page load, use the JavaScript API to identify users dynamically.
// After user logs in
window.FeatureBot.identify({
userId: user.id,
email: user.email,
name: user.name,
plan: user.subscription.plan,
mrr: user.subscription.mrr,
company: user.company.name,
role: user.role,
companySize: user.company.size,
attributes: {
team: user.team,
signupSource: user.signupSource,
betaFeatures: user.betaFeatures
}
});
// When user logs out
window.FeatureBot.reset();Custom Styling
CSS Variables API
Customize the widget appearance using CSS variables. Pass them via the data-css-vars attribute or dynamically with FeatureBot.setTheme().
<script
async
src="https://cdn.featurebot.com/widget.js"
data-key="YOUR_PUBLIC_KEY"
data-css-vars='{
"--fb-primary-color": "#0066cc",
"--fb-user-message-bg": "#0066cc",
"--fb-input-bg": "#f0f0f0"
}'
></script>Available Variables
Trigger Button
--fb-button-bg- Button background color--fb-button-text- Button text color--fb-button-border- Button border style (none, thin, thick)--fb-button-border-color- Button border color--fb-button-emoji- Button icon/emoji (e.g., "💬", "🚀", or empty string)
Chat Container
--fb-chat-border-radius- Chat window corner radius (e.g., "0", "12px", "24px")--fb-shadow- Chat window box shadow
Chat Interior
--fb-primary-color- Accent color for header, buttons, focus states--fb-chat-bg- Chat window background--fb-text-color- Primary text color--fb-muted-text- Secondary/muted text color--fb-input-bg- Input field background--fb-input-border- Input field border color--fb-input-text- Input field text color--fb-user-message-bg- User message bubble background--fb-user-message-text- User message text color--fb-bot-message-bg- Bot message bubble background--fb-bot-message-text- Bot message text color
Note on Fonts
Only preset fonts are available: Inter, Poppins, Roboto, Open Sans, Lato, and System UI. Configure fonts in your dashboard under Widget Settings. Need a different font? Request it via the FeatureBot feedback button in your dashboard.
Webhooks
Overview
Webhooks allow you to receive real-time notifications when events occur in FeatureBot. Configure webhook endpoints in Settings → Webhooks.
Available Events
feedback.createdTriggered when new feedback is submitted via the widget, API, or public board.
voice.addedTriggered when a user adds their voice to existing feedback (me too!).
feedback.status_changedTriggered when feedback status changes (e.g., Open → In Progress → Completed).
feedback.clusteredTriggered when feedback is grouped into a cluster by AI or manually.
Example Payload
Here's an example payload for the feedback.created event:
{
"event": "feedback.created",
"timestamp": "2024-01-15T10:30:00.000Z",
"feedback": {
"id": "fb_abc123",
"title": "Add dark mode support",
"description": "It would be great to have a dark mode option",
"category": "FEATURE_REQUEST",
"status": "OPEN",
"priority": "MEDIUM",
"voiceCount": 1,
"totalMrr": 9900,
"avgSentiment": 0.8,
"aiSummary": null,
"aiTags": ["ui", "accessibility"],
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
},
"workspace": {
"id": "ws_xyz789",
"name": "Acme Corp",
"slug": "acme-corp"
},
"triggeredBy": "widget"
}Request Headers
Each webhook request includes the following headers:
X-Webhook-SignatureHMAC-SHA256 signature for verification
X-Webhook-EventThe event type (e.g., FEEDBACK_CREATED)
X-Webhook-Delivery-IdUnique ID for this delivery attempt
Content-Typeapplication/json
Verifying Signatures
Always verify webhook signatures to ensure requests are from FeatureBot. The signature format is: t=timestamp,v1=signature
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
// Parse signature: t=<timestamp>,v1=<signature>
const parts = signature.split(',');
const timestamp = parts.find(p => p.startsWith('t='))?.slice(2);
const sig = parts.find(p => p.startsWith('v1='))?.slice(3);
if (!timestamp || !sig) return false;
// Check timestamp (within 5 minutes)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) return false;
// Verify signature
const signedPayload = `${timestamp}.${payload}`;
const expectedSig = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(sig),
Buffer.from(expectedSig)
);
}
// In your webhook handler
app.post('/webhooks/featurebot', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(
JSON.stringify(req.body),
signature,
process.env.FEATUREBOT_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process the webhook...
res.status(200).json({ received: true });
});Delivery & Retries
- • Webhooks timeout after 30 seconds by default
- • Failed deliveries are retried up to 3 times
- • Retries use exponential backoff
- • Return a 2xx status code to acknowledge receipt
- • View delivery history in Settings → Webhooks
JavaScript API
Control the widget programmatically using the global window.FeatureBot object.
window.FeatureBot.open()Open the feedback widget
window.FeatureBot.open({ prefill: "I want..." })Open with pre-filled text
window.FeatureBot.close()Close the widget
window.FeatureBot.isOpen()Returns true if the widget is currently open
window.FeatureBot.identify({ userId, email, name, plan, mrr, company, role, companySize, attributes })Identify the current user (for SPAs). All fields are optional. The attributes field accepts any JSON object for custom data.
window.FeatureBot.reset()Clear user identity (on logout)
window.FeatureBot.setTheme({ cssVars })Customize widget colors dynamically using CSS variables. Changes apply immediately if the widget is open.
// Customize widget colors dynamically
window.FeatureBot.setTheme({
'--fb-primary-color': '#0066cc',
'--fb-chat-bg': '#fafafa',
'--fb-user-message-bg': '#0066cc',
'--fb-bot-message-bg': '#e5e5e5'
});window.FeatureBot.hide()Hide the widget completely (button and chat window)
window.FeatureBot.show()Show the widget again after hiding
Ready to Get Started?
Create your free account and start collecting feedback in minutes.
Get Started Free