React SDK
Integrate Klero feedback, roadmap, changelog, surveys, and widgets into your React application.
Requirements
- React >= 18.0.0
Installation
npm install @kleroai/reactQuick Start
Pass projectSlug directly to any component — no extra setup needed:
import { KleroFeedback } from '@kleroai/react';
function FeedbackPage() {
return <KleroFeedback projectSlug="myproject" />;
}Components
KleroFeedback
<KleroFeedback projectSlug="myproject" />Accepts any div HTML attributes (className, style, etc.).
KleroRoadmap
<KleroRoadmap projectSlug="myproject" />To show a specific roadmap, pass roadmapSlug:
<KleroRoadmap projectSlug="myproject" roadmapSlug="public-roadmap" />KleroChangelog
<KleroChangelog projectSlug="myproject" />KleroWidget
Renders a floating button attached to the page body. Appearance and tabs are configured in the dashboard.
<KleroWidget projectSlug="myproject" />KleroSurvey
<KleroSurvey
projectSlug="myproject"
surveyUlid="01ABC123..."
onComplete={(data) => console.log('Completed:', data.responseUlid)}
onClose={(data) => console.log('Closed, completed:', data.completed)}
onError={(data) => console.error('Error:', data.error)}
/>| Prop | Type | Required | Description |
|---|---|---|---|
surveyUlid | string | Yes | The survey's unique identifier |
onComplete | (data: KleroSurveyCompletedEvent) => void | No | Survey completed |
onClose | (data: KleroSurveyClosedEvent) => void | No | Survey closed |
onError | (data: KleroSurveyErrorEvent) => void | No | Survey failed to load |
Shared Config with KleroProvider
When using multiple Klero components, wrap them in KleroProvider to share config and avoid repeating props:
import { KleroProvider, KleroFeedback, KleroWidget } from '@kleroai/react';
function App() {
return (
<KleroProvider projectSlug="myproject" customerToken="user-jwt-token">
<KleroWidget />
{/* KleroFeedback, KleroRoadmap, etc. inherit config from the provider */}
</KleroProvider>
);
}The provider also loads the Klero script once for all child components.
Note: When using components without a provider, the script is still loaded only once regardless of how many components are on the page.
KleroProvider Props
| Prop | Type | Required | Description |
|---|---|---|---|
projectSlug | string | Yes | Your Klero project slug |
customerToken | string | No | JWT token for authenticated users |
loginUrl | string | No | URL to redirect unauthenticated users |
baseUrl | string | No | Custom base URL for custom domains |
Authentication
Pass customerToken to identify logged-in users:
// Standalone
<KleroFeedback projectSlug="myproject" customerToken="user-jwt-token" />
// With provider (applies to all components)
<KleroProvider projectSlug="myproject" customerToken="user-jwt-token">
<KleroFeedback />
<KleroWidget />
</KleroProvider>See the Authentication Guide for token generation.
Hooks
All hooks work with or without KleroProvider.
useKleroWidget
Programmatically open or close the widget:
import { useKleroWidget } from '@kleroai/react';
function OpenFeedbackButton() {
const { open, close } = useKleroWidget();
return <button onClick={open}>Open Widget</button>;
}useKleroSurvey
Programmatically open or close a survey:
import { useKleroSurvey } from '@kleroai/react';
function TriggerSurvey() {
const { open } = useKleroSurvey();
return <button onClick={() => open('01ABC123...')}>Take Survey</button>;
}useKleroEvents
Listen for Klero events:
import { useKleroEvents } from '@kleroai/react';
function MyComponent() {
useKleroEvents({
'klero:survey:completed': (data) => {
console.log('Survey completed:', data.responseUlid);
},
'klero:widget:opened': () => {
console.log('Widget opened');
},
});
return null;
}Available Events
| Event | Data |
|---|---|
klero:survey:completed | { surveyUlid, responseUlid, answers } |
klero:survey:closed | { surveyUlid, completed } |
klero:survey:error | { surveyUlid, error } |
klero:widget:opened | — |
klero:widget:closed | — |
Custom Domain
If your project uses a custom domain, pass baseUrl:
<KleroFeedback projectSlug="myproject" baseUrl="https://feedback.mycompany.com" />