Display surveys on demand

Open surveys from your app when the moment is right.

Last reviewed

Display surveys on demand

Most surveys can be sent automatically from the getuserfeedback.com dashboard. Use Display on demand when your app should decide when to ask, like after setup, from a dedicated feedback button, or from an inline thumbs up/down control.

Set the survey delivery type to Display on demand, then use the flow ID for the survey you want to open. Find it in the getuserfeedback.com dashboard under your survey's settings.

React SDK

TypeScriptfeedback-button.tsx
import { useFlow } from "@getuserfeedback/react";import { Loader2 } from "lucide-react";function FeedbackButton() {const { isLoading, open } = useFlow({ flowId: "YOUR_FLOW_ID" });return (<buttondisabled={isLoading}type="button"onClick={() => open()}>{isLoading ? <Loader2 /> : null}Give feedback</button>);}

Use useFlow inside any component under GetUserFeedbackProvider.

JavaScript SDK

TypeScriptfeedback-button.ts
client.flow("YOUR_FLOW_ID").open();

Both fire-and-forget and await work correctly here. See JavaScript SDK reference.

Use the same flow handle for prefetch(), prerender(), open(), and close() when you want to keep one flow lifecycle together.

If you want to preserve lightweight response metadata, pass it on open():

TypeScriptfeedback-button.ts
await client.flow("YOUR_FLOW_ID").open({metadata: {tags: {journey_stage: "onboarding",survey_moment: "post-action",},},});

Google Tag Manager / loader

window.__getuserfeedback?.flow("YOUR_FLOW_ID").open();

Make opening feel instant

If you know an on-demand survey is likely to open, for example from a help menu item, you can prefetch and prerender it ahead of time:

React SDK

TypeScripthelp-menu-feedback-item.tsx
import { useFlow } from "@getuserfeedback/react";import { Loader2 } from "lucide-react";function HelpMenuFeedbackItem() {const { isLoading, prerender, open } = useFlow({flowId: "YOUR_FLOW_ID",prefetchOnMount: true,});return (<buttondisabled={isLoading}type="button"onMouseEnter={() => prerender()}onFocus={() => prerender()}onClick={() => open()}>{isLoading ? <Loader2 /> : null}Share feedback</button>);}

JavaScript SDK

TypeScripthelp-menu-feedback.ts
const flow = client.flow("YOUR_FLOW_ID");flow.prefetch();flow.prerender();flow.open();

Both fire-and-forget and await work correctly here. Use await only when your app wants to react after a step finishes. See JavaScript SDK reference.

Prefetching loads flow resources over the network. Prerendering warms up the UI before opening. Opening still handles the render step if you have not prerendered first.

Common mistake

Don't call open() before the widget is initialized. If you set disableAutoLoad: true, make sure client.load() has run first.