Skip to main content

In-App Feedback

Let users report bugs and request features from inside your app — recording their screen and voice, annotating a screenshot, and submitting it in one flow. Captures land on your dashboard Feedback board, where Gemini has already transcribed the narration and drafted a title, type, priority and summary.

Everything here uses a public key (pk_*), safe for the browser.

The drop-in widget

The fastest path is the <simplr-feedback> web component from @simplr-ai/web-components — it works in any framework or plain HTML.

<script src="https://cdn.jsdelivr.net/npm/@simplr-ai/web-components/dist/simplr-web-components.global.js"></script>
<script>
SimplrWebComponents.SimplrElements.configure({
apiKey: "pk_live_xxx",
rum: { applicationId: "my-app" }, // optional; links the report to the RUM session
user: { id: currentUser.id, email: currentUser.email, name: currentUser.name },
});
SimplrWebComponents.defineSimplrElements();
</script>

<simplr-feedback position="bottom-right"></simplr-feedback>

That renders a floating button. When opened, the user can:

  • Record screen + voicegetDisplayMedia + microphone, mixed into one recording.
  • Screenshot + annotate — capture a frame and draw with pen / arrow / box / highlight.
  • Pick a type — bug, feature, question, other — add an optional title/description, and submit.
  • Stay identified — signed-in users are attached automatically; otherwise the widget asks for an email so received, in-progress, testable, and release updates can be delivered.

position accepts bottom-right (default), bottom-left, top-right, top-left. Listen for completion:

window.addEventListener("simplr-feedback-submitted", (e) => console.log("sent", e.detail.id));

For apps where the user signs in after the SDK is configured, identify them when the session becomes available:

SimplrWebComponents.SimplrElements.identify({
id: currentUser.id,
email: currentUser.email,
name: currentUser.name,
});

React hook

Prefer to build your own trigger UI? Use useSimplrFeedback from @simplr-ai/js/react.

import { useSimplrFeedback } from "@simplr-ai/js/react";

function ReportButton() {
const fb = useSimplrFeedback({ apiKey: "pk_live_xxx", applicationId: "my-app" });

async function report() {
await fb.startRecording({ microphone: true });
// user narrates while using the app…
const recording = await fb.stopRecording();
await fb.submit({ type: "bug", title: "Checkout 404", attachments: recording ? [recording] : [] });
}

return <button onClick={report}>{fb.isRecording ? "Stop recording" : "Report a bug"}</button>;
}

The hook exposes isRecording, isSubmitting, progress, error, plus startRecording, stopRecording, cancelRecording, captureScreenshot, and submit.

Programmatic client

For full control, use the SimplrFeedback class and the capture helpers directly.

import { SimplrFeedback, ScreenRecorder, captureScreenshot, CanvasAnnotator } from "@simplr-ai/js";

const client = new SimplrFeedback({
apiKey: "pk_live_xxx",
applicationId: "my-app",
user: { id: currentUser.id, email: currentUser.email, name: currentUser.name },
});

const shot = await captureScreenshot();
await client.submit({
type: "feature",
title: "Add dark mode",
attachments: [{ kind: "screenshot", blob: shot.blob, mimeType: "image/png", width: shot.width, height: shot.height }],
});

submit() accepts an onProgress(fraction) callback so you can show upload progress.

Call client.identify(user) when the signed-in user changes. Your application user id is stored as an external reference; it is not treated as a Simplr portal user id.

How uploads work

submit() never streams large files through your server:

  1. It POSTs the item to /v1/feedback with the attachment list.
  2. The API returns a short-lived signed upload URL per attachment.
  3. The SDK PUTs each blob directly to storage, then calls the complete endpoint.
  4. Once all uploads finish, AI enrichment (transcription + drafting) runs automatically.

Privacy

By default the widget strips the query string from the captured page URL (redactUrl: true) and only sends benign device context (user agent, viewport, language, timezone). Recordings and screenshots are stored privately and only ever served to your dashboard through short-lived signed URLs.

Reference

EndpointAuthPurpose
POST /v1/feedbackpk_*Create an item; returns signed upload URLs
POST /v1/feedback/:id/attachments/:attId/completepk_*Confirm an upload finished