@intentai/react
v1.0.2
Published
Official React SDK for Intent AI - AI-powered feedback collection widget
Maintainers
Readme
@intentai/react
Official React SDK for Intent AI - AI-powered feedback collection widget.
Installation
npm install @intentai/react
# or
yarn add @intentai/react
# or
pnpm add @intentai/reactQuick Start
1. Get your Public Key
Get your public key (pk_live_* or pk_test_*) from the Intent AI Dashboard.
2. Add the Provider
Wrap your app with IntentAIProvider:
// app/layout.tsx (Next.js App Router)
import { IntentAIProvider } from '@intentai/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
<IntentAIProvider apiKey="pk_live_xxxxx">
{children}
</IntentAIProvider>
</body>
</html>
);
}That's it! The feedback widget will appear in the bottom-right corner.
Environment Variables
The SDK automatically detects your API key from environment variables:
# Next.js
NEXT_PUBLIC_INTENT_AI_KEY=pk_live_xxxxx
# Create React App
REACT_APP_INTENT_AI_KEY=pk_live_xxxxx
# Vite
VITE_INTENT_AI_KEY=pk_live_xxxxxWith environment variables set, you can omit the apiKey prop:
<IntentAIProvider>
{children}
</IntentAIProvider>Usage
Basic Setup
import { IntentAIProvider } from '@intentai/react';
function App() {
return (
<IntentAIProvider
apiKey="pk_live_xxxxx"
position="bottom-right"
theme="auto"
>
<YourApp />
</IntentAIProvider>
);
}Custom Feedback Button
import { IntentAIProvider, FeedbackButton } from '@intentai/react';
function App() {
return (
<IntentAIProvider apiKey="pk_live_xxxxx" autoShow={false}>
<FeedbackButton className="btn btn-primary">
Send Feedback
</FeedbackButton>
</IntentAIProvider>
);
}Using the Hook
import { useIntentAI } from '@intentai/react';
function MyComponent() {
const { open, close, isReady, error } = useIntentAI();
if (error) {
return <div>Failed to load feedback widget</div>;
}
return (
<button onClick={() => open()} disabled={!isReady}>
Give Feedback
</button>
);
}Identify Users
Using the useIdentify hook (recommended):
import { useIdentify } from '@intentai/react';
function AuthenticatedApp({ user }) {
// Automatically identifies user when ready
useIdentify(user ? {
id: user.id,
email: user.email,
name: user.name,
plan: user.subscription.plan,
} : null);
return <YourApp />;
}Using the IdentifyUser component:
import { IntentAIProvider, IdentifyUser } from '@intentai/react';
function App({ user }) {
return (
<IntentAIProvider apiKey="pk_live_xxxxx">
<IdentifyUser user={{
id: user.id,
email: user.email,
name: user.name
}}>
<YourApp />
</IdentifyUser>
</IntentAIProvider>
);
}Or using the hook directly:
import { useIntentAI } from '@intentai/react';
function AuthenticatedApp({ user }) {
const { identify, isReady } = useIntentAI();
useEffect(() => {
if (isReady && user) {
identify({
id: user.id,
email: user.email,
name: user.name,
plan: user.subscription.plan, // Custom properties
});
}
}, [isReady, user]);
return <YourApp />;
}Add Metadata
import { SetMetadata } from '@intentai/react';
function PricingPage() {
return (
<SetMetadata metadata={{ page: 'pricing', feature: 'comparison' }}>
<PricingContent />
</SetMetadata>
);
}Or using the hook:
const { setMetadata } = useIntentAI();
useEffect(() => {
setMetadata({
page: window.location.pathname,
viewport: `${window.innerWidth}x${window.innerHeight}`
});
}, []);Track Events
Using the TrackEvent component:
import { TrackEvent } from '@intentai/react';
function CheckoutPage() {
return (
<TrackEvent event="checkout_viewed" properties={{ items: 3 }}>
<CheckoutContent />
</TrackEvent>
);
}Using the hook:
const { track } = useIntentAI();
function handlePurchase(item) {
track('purchase', {
itemId: item.id,
price: item.price
});
}Custom Trigger with FeedbackTrigger
import { FeedbackTrigger } from '@intentai/react';
function App() {
return (
<FeedbackTrigger>
{({ open, isReady }) => (
<MyCustomButton onClick={() => open()} disabled={!isReady}>
Feedback
</MyCustomButton>
)}
</FeedbackTrigger>
);
}Pre-fill Feedback
const { open } = useIntentAI();
// Open with pre-selected type and prefilled text
open({
type: 'bug',
prefill: { text: 'I found an issue with...' },
metadata: { page: 'checkout' }
});Configuration
IntentAIProvider Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| apiKey | string | - | Your Intent AI public key (or use env vars) |
| position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Widget position |
| theme | 'light' \| 'dark' \| 'auto' | 'auto' | Color theme |
| primaryColor | string | '#6366f1' | Primary brand color (hex) |
| autoShow | boolean | true | Show widget button automatically |
| user | UserIdentity | - | Initial user identification |
| metadata | Record<string, unknown> | - | Custom metadata |
| onReady | () => void | - | Called when widget is ready |
| onOpen | () => void | - | Called when widget opens |
| onClose | () => void | - | Called when widget closes |
| onSubmit | (data: FeedbackData) => void | - | Called on feedback submission |
| onError | (error: Error) => void | - | Called on errors |
useIntentAI Hook
const {
isReady, // boolean - Widget loaded and ready
error, // Error | null - Error if widget failed to load
open, // (options?: OpenOptions) => void - Open the widget
close, // () => void - Close the widget
identify, // (user: UserIdentity) => void - Identify user
setMetadata,// (data: Record<string, unknown>) => void - Set metadata
track, // (event: string, properties?: Record<string, unknown>) => void - Track event
} = useIntentAI();useIdentify Hook
// Automatically identifies user when widget is ready
useIdentify({
id: 'user_123',
email: '[email protected]',
name: 'John Doe',
plan: 'pro',
company: 'Acme Inc',
});
// Pass null to skip identification
useIdentify(user ? { id: user.id, email: user.email } : null);OpenOptions
interface OpenOptions {
type?: 'bug' | 'feature' | 'question' | 'praise' | 'other';
prefill?: { text?: string };
metadata?: Record<string, unknown>;
}UserIdentity
interface UserIdentity {
id: string; // Required
email?: string;
name?: string;
avatar?: string;
plan?: string;
company?: string;
[key: string]: string | number | boolean | undefined; // Custom properties
}Next.js App Router
The SDK is fully compatible with Next.js App Router and Server Components:
// app/providers.tsx
'use client';
import { IntentAIProvider } from '@intentai/react';
export function Providers({ children }) {
return (
<IntentAIProvider>
{children}
</IntentAIProvider>
);
}
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}TypeScript
Full TypeScript support with exported types:
import type {
UserIdentity,
IntentAIConfig,
FeedbackData,
OpenOptions,
FeedbackType,
} from '@intentai/react';
const user: UserIdentity = {
id: '123',
email: '[email protected]',
name: 'John Doe',
};Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
License
MIT © Intent AI
