SurveysProvider
Root provider that manages survey state, fatigue prevention, persistence, and analytics callbacks for all surveys in your application
The root provider for @tour-kit/surveys. Place it once, high in your component tree. All display components and hooks must be descendants of this provider.
Import
import { SurveysProvider } from '@tour-kit/surveys';Usage
import { SurveysProvider } from '@tour-kit/surveys';
import type { SurveyConfig } from '@tour-kit/surveys';
const surveys: SurveyConfig[] = [
{
id: 'nps-q1',
type: 'nps',
displayMode: 'modal',
title: 'How likely are you to recommend us?',
questions: [
{
id: 'score',
type: 'rating',
text: 'Rate us 0–10',
ratingScale: { min: 0, max: 10 },
},
],
},
];
export function App() {
return (
<SurveysProvider
surveys={surveys}
globalCooldownDays={14}
maxPerSession={1}
onSurveyComplete={(id, responses) => {
analytics.track('survey_completed', { id, responses: Object.fromEntries(responses) });
}}
>
<YourApp />
</SurveysProvider>
);
}Props
Prop
Type
Persistence
The provider persists full survey state to storage on every state change and hydrates on mount. The stored JSON includes isCompleted, isDismissed, isSnoozed, snoozeUntil, viewCount, lastViewedAt, responses, and the current queue.
Disable persistence entirely:
<SurveysProvider surveys={surveys} storage={null}>
<App />
</SurveysProvider>Use a custom adapter (for example, a server-side or encrypted store):
const adapter: Storage = {
getItem: (key) => myDb.get(key),
setItem: (key, value) => myDb.set(key, value),
removeItem: (key) => myDb.delete(key),
};
<SurveysProvider surveys={surveys} storage={adapter}>
<App />
</SurveysProvider>Global cooldown is the first gate evaluated. If the provider's globalCooldownDays has not
elapsed since the last shown survey, no individual survey's frequency rule is evaluated and
show() is a no-op. If you are testing frequency behaviour, set globalCooldownDays={0} or
clear localStorage between runs.
Tour suppression
The provider reads from @tour-kit/core's TourContext. If a guided tour is active, surveys are suppressed automatically — show() becomes a no-op and any currently visible survey is hidden until the tour ends.
Queue configuration
By default, only one survey shows at a time. Requesting a second survey while one is active adds it to an internal priority queue.
<SurveysProvider
surveys={surveys}
queueConfig={{
maxConcurrent: 1,
priorityOrder: 'priority', // 'priority' | 'fifo' | 'lifo'
stackBehavior: 'queue', // 'queue' | 'replace' | 'stack'
delayBetween: 500, // ms between consecutive surveys
autoShow: true, // drain queue automatically
}}
>
<App />
</SurveysProvider>useSurveysContext
Low-level context hook that returns the full SurveysContextValue. Prefer useSurvey and useSurveys for most use-cases.
import { useSurveysContext } from '@tour-kit/surveys';
function AdminDebugPanel() {
const ctx = useSurveysContext();
return (
<ul>
{Array.from(ctx.surveys.entries()).map(([id, state]) => (
<li key={id}>
{id}: visible={String(state.isVisible)}, completed={String(state.isCompleted)}
</li>
))}
</ul>
);
}Throws if called outside a SurveysProvider.
Related
- useSurvey — Control a single survey
- useSurveys — Full context access
- Types — SurveyConfig, SurveysProviderProps