Feedback Widget SDK
Embed @deck/feedback widgets so in-product feedback flows into Deck.
Feedback Widget SDK
The Feedback Widget SDK (@deck/feedback) lets you embed feedback collection in your product. Submissions land in Deck as a first-class source, appear under Manage → Widgets, and can be synthesized into insights and themes.
Use this when you want customers to share feedback without leaving your app — for example after a new feature, on a settings page, or next to an AI response.
Feedback Widgets is rolling out. The in-product widget setup pages are disabled
by default, and @deck/feedback is not yet published to npm. You may not see
Manage → Widgets or Settings → Feedback Widget SDK, and external apps
cannot install the package until Deck enables and publishes the feature.
What you need
- A widget in Deck (identifies the source of feedback)
- A publishable key (
pk_…) for client-side auth - The
@deck/feedbackReact package in your app
| Item | Where to create it | Safe in the browser? |
|---|---|---|
Widget ID (wgt_…) | Manage → Widgets | Yes (public identifier) |
Publishable key (pk_…) | Settings → Feedback Widget SDK | Yes (client-safe; scoped to widget ingest) |
Secret API key (dk_…) | Settings → Deck API | No — not for this SDK |
Publishable keys are for the widget SDK only. They cannot call the Deck Public API. Use secret dk_… keys for server-side Public API access.
Setup in Deck
1. Create a feedback widget
- Go to Manage → Widgets
- Click Create widget
- Give it a clear name (for example “Settings panel” or “AI message”)
- Copy the widget ID from the widget detail page
Optionally link the widget to a Project so submissions can attach as Project Evidence when free-text is present.
2. Create a publishable key
- Go to Settings → Feedback Widget SDK
- Create a publishable key
- Copy the full
pk_…secret immediately — Deck only shows it once - Store it in your app’s environment (for example
NEXT_PUBLIC_DECK_PUBLISHABLE_KEY)
You can use one publishable key across multiple widgets in the same organization.
3. Install the package after it is published
pnpm add @deck/feedback
# or
npm install @deck/feedbackPeer dependencies: react and react-dom (18+).
Quick start
Wrap your product UI in DeckProvider, then use built-in widgets or your own UI.
import { useState } from "react";
import {
DeckProvider,
FeedbackDialog,
ThumbsFeedback,
} from "@deck/feedback";
function App() {
return (
<DeckProvider
publishableKey={process.env.NEXT_PUBLIC_DECK_PUBLISHABLE_KEY!}
user={{
id: currentUser.id,
email: currentUser.email,
name: currentUser.name,
}}
>
<ProductUi />
</DeckProvider>
);
}
function ProductUi() {
const [open, setOpen] = useState(false);
return (
<>
{/* You own the trigger button */}
<button type="button" onClick={() => setOpen(true)}>
Share feedback
</button>
<FeedbackDialog
widgetId="wgt_your_widget_id"
open={open}
onOpenChange={setOpen}
context={{ surface: "settings" }}
/>
{/* Built-in thumbs; opens the dialog with sentiment pre-set */}
<ThumbsFeedback
widgetId="wgt_your_widget_id"
context={{ messageId: "msg_123" }}
/>
</>
);
}Replace wgt_your_widget_id with the ID from Manage → Widgets.
Components
DeckProvider
Required root. Passes auth and user identity to child widgets.
| Prop | Required | Description |
|---|---|---|
publishableKey | Yes | Your pk_… key |
user | Recommended | At least id; optional email, name for contact matching |
headless | No | Skip Deck theme wrapper when you fully own the UI |
apiUrl | No | Override ingest URL (defaults to Deck production) |
FeedbackDialog
Controlled modal for written feedback. Your app owns the open/close trigger.
ThumbsFeedback
Like / dislike controls that open the dialog with sentiment pre-filled.
Headless submit
Build your own form and submit through the SDK:
import {
DeckProvider,
useSubmitFeedback,
} from "@deck/feedback";
function MyFeedbackForm() {
const { submitFeedback, isSubmitting, lastError } = useSubmitFeedback();
async function onSubmit(message: string) {
const result = await submitFeedback({
widgetId: "wgt_your_widget_id",
sentiment: "positive",
message,
context: { surface: "settings" },
});
if (result.ok) {
// close modal, toast, etc.
}
}
// render your own UI…
}Wrap headless UIs in DeckProvider (optionally with headless).
User identity
Pass a stable product user id on DeckProvider:
user={{
id: currentUser.id, // required for reliable identity
email: currentUser.email,
name: currentUser.name,
}}Deck uses this to attribute submissions and match contacts when possible. Prefer the same id you use elsewhere in your product.
Optional context
context is a free-form object stored with the submission (for example surface name, message id, or feature flag). Use it to filter or debug later in Deck.
context={{ surface: "intelligence-panel", messageId: "msg_123" }}Where feedback goes in Deck
- User submits from your product via
@deck/feedback - Deck stores a raw submission under Manage → Widgets → [your widget]
- When free-text is present, Deck synthesizes the submission into insights (uses organization credits)
- Insights appear in Visualize (themes, categories, etc.)
- If the widget is linked to a Project, evidence can attach to that Project when synthesis runs
Submissions without a message stay raw (no synthesis).
Install snippet in the product
Deck also shows an install snippet in:
- Settings → Feedback Widget SDK
- Manage → Widgets → [widget] (until the widget has submissions)
Use those pages for copy-paste setup while integrating.
Security notes
- Do embed publishable keys (
pk_…) in client apps - Do not put secret Public API keys (
dk_…) in the browser or in@deck/feedback - Revoke a publishable key from Settings → Feedback Widget SDK if it is exposed beyond your control; widgets using that key will stop accepting submissions
- Prefer environment variables (for example
NEXT_PUBLIC_DECK_PUBLISHABLE_KEY) so keys are not hard-coded
Troubleshooting
| Symptom | What to check |
|---|---|
| Submissions never appear | Widget ID and publishable key belong to the same Deck org |
| 401 / unauthorized | Key revoked, mistyped, or not a pk_… publishable key |
| No insights after submit | Message body empty (raw only), or org out of credits |
| Wrong product surface | Confirm widgetId and optional context on the component |
Related
- Public API — server-side access with secret keys (not for widgets)
- Projects — link widgets to Project Evidence
- Getting Started — first-run setup in Deck