Documentation Index
Fetch the complete documentation index at: https://docs.revrag.ai/llms.txt
Use this file to discover all available pages before exploring further.
π Complete Integration Guide
π¦ Installation
npm install @revrag-ai/embed-react
# or
yarn add @revrag-ai/embed-react
β οΈ Important: CSS Import (REQUIRED)
The CSS file MUST be imported for the widget to display correctly. Without it, the widget will appear unstyled.
Option 1: Global Import (Recommended)
React/Vite:
// src/main.tsx or src/index.tsx
import '@revrag-ai/embed-react/style.css';
import App from './App';
import ReactDOM from 'react-dom/client';
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
Next.js App Router:
// app/layout.tsx
import '@revrag-ai/embed-react/style.css';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Next.js Pages Router:
// pages/_app.tsx
import '@revrag-ai/embed-react/style.css';
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
Option 2: Component-Level Import
// YourComponent.tsx
import { EmbedButton, useInitialize } from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
Option 3: CSS File Import
/* In your global styles.css */
@import '@revrag-ai/embed-react/style.css';
π― Basic Usage
Fixed Positioning (Default)
import { EmbedButton, useInitialize } from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
function App() {
const { isInitialized } = useInitialize("your-api-key");
if (!isInitialized) {
return <div>Loading AI Assistant...</div>;
}
return (
<div>
<h1>My Application</h1>
{/* Widget will appear at bottom-right corner */}
<EmbedButton positioning="fixed" />
</div>
);
}
Embedded Positioning
import { EmbedButton, useInitialize } from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
function HelpSection() {
const { isInitialized } = useInitialize("your-api-key");
if (!isInitialized) return null;
return (
<div style={{
position: 'relative',
height: '500px',
background: '#f5f5f5',
borderRadius: '12px'
}}>
<h2>Need Help?</h2>
<p>Chat with our AI assistant</p>
{/* Widget will appear at bottom-left of this container */}
<EmbedButton
positioning="embedded"
side="left"
/>
</div>
);
}
π§© EmbedProvider (Recommended)
Instead of manually placing <EmbedButton /> on every page, wrap your app once with EmbedProvider and let it handle widget visibility automatically.
BEST PRACTICE: Use EmbedProvider to automatically manage the EmbedButton based on the current route.The EmbedProvider component:
- β
Automatically tracks route changes and shows/hides the widget
- β
Conditionally renders the EmbedButton based on the current page
- β
Supports delays before the button appears on a route
- β
Supports visibility groups for per-route delay, continuity, and position
- β
Built-in component - no need to create a custom provider
Basic Setup
import { EmbedProvider, useInitialize } from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
function App() {
const { isInitialized } = useInitialize("your-api-key");
if (!isInitialized) return <div>Loading...</div>;
return (
<EmbedProvider appVersion="1.0.0">
{/* Your app / router */}
</EmbedProvider>
);
}
Show on specific routes only
<EmbedProvider
appVersion="1.0.0"
includeScreens={['/home', '/dashboard', '/profile']}
>
{/* Widget only visible on the listed routes */}
</EmbedProvider>
EmbedProvider Props
| Property | Type | Required | Description |
|---|
children | ReactNode | β
| Your app or router |
appVersion | string | β
| App version string used in analytics |
includeScreens | string[] | β | Routes where the button appears. Omit to show on all routes |
matchMode | βexactβ | βprefixβ | β | Route matching mode (default: βexactβ) |
currentPath | string | β | Current route path (auto-detected if not provided) |
usePathHook | () => string | β | Custom hook for path detection (e.g., Next.js usePathname) |
embedButtonDelayMs | number | β | Delay (ms) before the button appears on a route |
embedButtonVisibilityConfig | EmbedButtonVisibilityConfig | β | Advanced per-group delay, continuity, and inset config |
embedButtonPosition | βtopβ | βbottomβ | βleftβ | βrightβ | β | Button position for fixed positioning |
Advanced usage guide β
π¨ Responsive Behavior
Fixed Positioning
- Desktop (> 500px): Widget stays at specified position
- Mobile (β€ 500px): Widget expands to full width with 1rem padding from edges
Embedded Positioning
- Wide parent (> 400px): Widget aligns to left/right based on
side prop
- Narrow parent (β€ 400px): Widget auto-centers with equal padding
π§ API Reference
interface EmbedButtonProps {
// Positioning mode
positioning?: 'fixed' | 'embedded'; // default: 'fixed'
// Position configuration (for fixed mode)
position?: {
top?: string;
bottom?: string;
left?: string;
right?: string;
};
// Easy positioning (for embedded mode)
side?: 'left' | 'right';
// Offset from bottom (useful for bottom navbars)
bottomOffset?: number; // in pixels
// Custom className
className?: string;
}
useInitialize
const { isInitialized, error } = useInitialize(apiKey: string);
Initializes the SDK with your API key. Must be called before using any other SDK features.
useEmbed
const { currentPath } = useEmbed();
Reads currentPath from EmbedProvider context. Useful for accessing the current route within your components.
useLiveKit
const { connect, disconnect, toggleMute } = useLiveKit();
Provides programmatic control over voice calls:
connect(): Initiate a voice call
disconnect(): End the current voice call
toggleMute(): Mute/unmute the microphone
useSSRSafe / useBrowserSafe
const isMounted = useSSRSafe();
// or
const isMounted = useBrowserSafe();
SSR-safe mount detection hooks. Returns true when component is mounted on the client side. Useful for Next.js and other SSR frameworks to prevent hydration mismatches.
π‘ Event Management
The SDK provides a powerful event system for tracking user data, custom events, and listening to agent state changes.
EventKeys
Available event types:
import { EventKeys } from '@revrag-ai/embed-react';
EventKeys.USER_DATA // 'user_data' - User identification and profile data
EventKeys.CUSTOM_EVENT // 'custom_event' - Custom application events
EventKeys.AGENT_CONNECTED // 'agent_start' - Voice agent connection (auto-tracked)
EventKeys.AGENT_DISCONNECTED // 'agent_end' - Voice agent disconnection (auto-tracked)
EventKeys.ANALYTICS_DATA // 'analytics_data'
Note: Only USER_DATA , CUSTOM_EVENT and ANALYTICS_DATA are available for manual use. Agent connection events are automatically tracked by the SDK and can be listened to via callbacks.
Sending Events with embedEvent API
The embedEvent object provides methods for sending events to track user data and custom application events.
Send User Data
import { embedEvent, EventKeys } from '@revrag-ai/embed-react';
// Send user data
const response = await embedEvent.event({
eventKey: EventKeys.USER_DATA,
data: {
app_user_id: 'user-123',
email: 'user@example.com',
name: 'John Doe',
plan: 'premium'
}
});
if (response.success) {
console.log('User data sent successfully');
}
Send Custom Events
import { embedEvent, EventKeys } from '@revrag-ai/embed-react';
// Track custom application event
await embedEvent.event({
eventKey: EventKeys.CUSTOM_EVENT,
data: {
event_name: 'purchase_completed',
product_id: 'prod-123',
amount: 99.99
}
});
Send Analytics Events
import { embedEvent, EventKeys } from '@revrag-ai/embed-react';
// Track custom application event
await embedEvent.event({
eventKey: EventKeys.ANALYTICS_DATA,
data: {
event_name: 'purchase_completed', // event_name is compulsory in analytics_data event
product_id: 'prod-123',
amount: 99.99
}
});
Event Method Signature
embedEvent.event(params: UpdateDataRequest): Promise<ApiResponse>
interface UpdateDataRequest {
eventKey: EventKey; // Event type from EventKeys
data: {
app_user_id?: string; // User ID (required for USER_DATA)
[key: string]: unknown; // Additional data
};
session_id?: string; // Optional session ID
}
interface ApiResponse {
success: boolean;
data?: unknown;
message?: string;
error?: string;
}
Listening to Agent Events
Monitor voice agent connection status in real-time. These events are automatically sent to your backend AND emitted locally for you to listen to.
Available Event Types for Listening
import { EventKeys } from '@revrag-ai/embed-react';
// Available events for listening:
EventKeys.AGENT_CONNECTED // 'agent_start' - Voice agent connected
EventKeys.AGENT_DISCONNECTED // 'agent_end' - Voice agent disconnected
Automatic Backend Sync:
- Agent events are automatically sent to your backend with
app_user_id
- Events are also emitted locally for real-time UI updates
- Backend receives all event data including timestamps and metadata
- No manual API calls needed - itβs all handled automatically
Event Listener Methods
import { embedEvent } from '@revrag-ai/embed-react';
// Add event listener
embedEvent.addCallback(callback);
// Remove event listener
embedEvent.removeCallback(callback);
Basic Event Listening Example
import React, { useEffect } from 'react';
import { embedEvent, EventKeys, EmbedButton } from '@revrag-ai/embed-react';
function MyComponent() {
useEffect(() => {
// Define event handler
const handleAgentEvent = (event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
console.log('β
Agent connected:', event.data);
// Update UI to show agent is available
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
console.log('β Agent disconnected:', event.data);
// Update UI to show agent is unavailable
}
};
// Register callback
embedEvent.addCallback(handleAgentEvent);
// Cleanup
return () => {
embedEvent.removeCallback(handleAgentEvent);
};
}, []);
return <EmbedButton />;
}
Complete Agent Monitoring Example
import React, { useEffect, useState } from 'react';
import { embedEvent, EventKeys, EmbedButton } from '@revrag-ai/embed-react';
function VoiceAgentMonitor() {
const [agentStatus, setAgentStatus] = useState<'idle' | 'connected' | 'disconnected'>('idle');
const [agentIdentity, setAgentIdentity] = useState<string>('');
const [connectionTime, setConnectionTime] = useState<Date | null>(null);
useEffect(() => {
const handleEvent = (event) => {
// Handle agent connection
if (event.type === EventKeys.AGENT_CONNECTED) {
console.log('β
Agent connected:', event);
console.log('Identity:', event.data?.identity);
console.log('Metadata:', event.data?.metadata);
console.log('Timestamp:', event.timestamp);
setAgentStatus('connected');
setAgentIdentity(event.data?.identity || 'Unknown');
setConnectionTime(new Date(event.timestamp));
// Update UI - show green indicator, enable features, etc.
// Example: Show notification, start analytics timer
}
// Handle agent disconnection
if (event.type === EventKeys.AGENT_DISCONNECTED) {
console.log('β Agent disconnected:', event);
console.log('Identity:', event.data?.identity);
console.log('Metadata:', event.data?.metadata);
console.log('Timestamp:', event.timestamp);
setAgentStatus('disconnected');
// Calculate call duration if needed
if (connectionTime) {
const duration = Date.now() - connectionTime.getTime();
console.log('Call duration:', duration / 1000, 'seconds');
}
// Update UI - show gray indicator, disable features, etc.
// Example: Show feedback form, log analytics
}
};
// Register event listener
embedEvent.addCallback(handleEvent);
// Cleanup listener on unmount
return () => {
embedEvent.removeCallback(handleEvent);
};
}, [connectionTime]);
return (
<div className="agent-monitor">
<div className="status-indicator">
<span className={`status-dot ${agentStatus}`} />
<span>Agent Status: {agentStatus}</span>
</div>
{agentStatus === 'connected' && (
<div className="agent-info">
<p>β Voice agent is active</p>
<p>Identity: {agentIdentity}</p>
{connectionTime && (
<p>Connected at: {connectionTime.toLocaleTimeString()}</p>
)}
</div>
)}
<EmbedButton />
</div>
);
}
Advanced: Multiple Event Listeners
import { useEffect } from 'react';
import { embedEvent, EventKeys } from '@revrag-ai/embed-react';
function MyApp() {
useEffect(() => {
// Analytics tracking
const analyticsCallback = (event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
// Track to analytics service
analytics.track('voice_agent_connected', {
identity: event.data?.identity,
timestamp: event.timestamp,
});
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
analytics.track('voice_agent_disconnected', {
identity: event.data?.identity,
timestamp: event.timestamp,
});
}
};
// UI updates
const uiCallback = (event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
showNotification('Voice agent connected');
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
showNotification('Voice agent disconnected');
}
};
// Register multiple callbacks
embedEvent.addCallback(analyticsCallback);
embedEvent.addCallback(uiCallback);
// Cleanup
return () => {
embedEvent.removeCallback(analyticsCallback);
embedEvent.removeCallback(uiCallback);
};
}, []);
return <YourApp />;
}
Use Cases for Agent Events
AGENT_CONNECTED:
- Show visual indicators (green dot, badge)
- Enable voice-related features in UI
- Start analytics timers
- Update user presence status
- Show notifications to user
- Pause background music/media
AGENT_DISCONNECTED:
- Update UI to show agent unavailable
- Log analytics (call duration, success)
- Show feedback forms
- Resume background media
- Clean up resources
- Save conversation state
What Gets Sent to Backend
When an agent event fires, the SDK automatically sends this data to your backend:
{
event_id: "evt_1234567890_abc", // Unique event ID
type: "agent_start", // Event type (agent_start or agent_end)
app_user_id: "user-123", // Auto-added from USER_DATA
session_id: "embed_session_...", // Session identifier
timestamp: "2024-01-15T10:30:00Z", // ISO timestamp
sdk: {
sdk_name: "@revrag-ai/embed-react",
sdk_version: "1.3.7",
platform: "web"
},
data: {
identity: "agent-001", // Agent identity
metadata: { // Additional metadata
// ... agent-specific data
}
}
}
This allows you to:
- Track agent usage analytics
- Monitor call durations
- Understand user engagement patterns
- Build reports on voice agent interactions
- Audit agent connections
Event Data Structure
// Agent Connected Event
interface AgentConnectedEvent {
type: 'agent_start';
target: string;
timestamp: number; // Unix timestamp
data?: {
identity?: string; // Agent identity
metadata?: Record<string, unknown>;
};
userId?: string;
sessionId: string;
metadata?: Record<string, unknown>;
}
// Agent Disconnected Event
interface AgentDisconnectedEvent {
type: 'agent_end';
target: string;
timestamp: number; // Unix timestamp
data?: {
identity?: string; // Agent identity
metadata?: Record<string, unknown>;
};
userId?: string;
sessionId: string;
metadata?: Record<string, unknown>;
}
Handling Connection Errors
import { useEffect, useState } from 'react';
import { embed, EventKeys, EmbedButton } from '@revrag-ai/embed-react';
function AgentWithErrorHandling() {
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const handleEvent = (event) => {
try {
if (event.type === EventKeys.AGENT_CONNECTED) {
setError(null);
// Handle successful connection
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
// Check if disconnection was due to error
if (event.data?.metadata?.error) {
setError('Agent connection lost: ' + event.data.metadata.error);
}
}
} catch (err) {
console.error('Error handling agent event:', err);
setError('Failed to process agent event');
}
};
embed.addCallback(handleEvent);
return () => embed.removeCallback(handleEvent);
}, []);
return (
<div>
{error && (
<div className="error-banner">
{error}
</div>
)}
<EmbedButton />
</div>
);
}
π± Mobile Optimization
The widget automatically adjusts for mobile devices:
- iPhone SE, small Android devices
- Reduced padding and font sizes
- Optimized button and text layouts
Small Screens (376px - 500px)
- Standard smartphones
- Balanced sizing for readability
π― Common Use Cases
import { EmbedButton, useInitialize, embedEvent, EventKeys } from '@revrag-ai/embed-react';
import { useEffect } from 'react';
function App() {
const { isInitialized } = useInitialize("your-api-key");
const currentUser = useAuthUser(); // Your auth hook
useEffect(() => {
if (isInitialized && currentUser) {
// Send user data when user logs in
embedEvent.event({
eventKey: EventKeys.USER_DATA,
data: {
app_user_id: currentUser.id,
email: currentUser.email,
name: currentUser.name,
subscription_tier: currentUser.plan
}
});
}
}, [isInitialized, currentUser]);
return (
<>
<YourMainContent />
{isInitialized && (
<EmbedButton
positioning="fixed"
position={{ bottom: "24px", right: "24px" }}
/>
)}
</>
);
}
2. E-commerce with Purchase Tracking
import { EmbedButton, useInitialize, embedEvent, EventKeys } from '@revrag-ai/embed-react';
function CheckoutPage() {
const { isInitialized } = useInitialize("your-api-key");
const handleCheckout = async (orderData) => {
// ... process order
// Track purchase event
await embedEvent.event({
eventKey: EventKeys.CUSTOM_EVENT,
data: {
event_name: 'purchase_completed',
order_id: orderData.id,
total: orderData.total,
items: orderData.items.length
}
});
};
if (!isInitialized) return null;
return (
<div>
<CheckoutForm onSubmit={handleCheckout} />
<EmbedButton positioning="embedded" side="right" />
</div>
);
}
import { EmbedButton, useInitialize, embedEvent, EventKeys } from '@revrag-ai/embed-react';
import { useState, useEffect } from 'react';
function HelpPage() {
const { isInitialized } = useInitialize("your-api-key");
const [agentConnected, setAgentConnected] = useState(false);
useEffect(() => {
const handleAgentEvent = (event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
setAgentConnected(true);
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
setAgentConnected(false);
}
};
embedEvent.addCallback(handleAgentEvent);
return () => embedEvent.removeCallback(handleAgentEvent);
}, []);
return (
<div className="help-container">
<h1>Help & Support</h1>
{agentConnected && (
<div className="status-badge">π’ Agent Connected</div>
)}
<div style={{ position: 'relative', minHeight: '400px' }}>
{isInitialized && (
<EmbedButton
positioning="embedded"
side="right"
/>
)}
</div>
</div>
);
}
4. With Bottom Navigation
function MobileApp() {
const { isInitialized } = useInitialize("your-api-key");
return (
<>
<YourContent />
<BottomNavigation /> {/* height: 60px */}
{isInitialized && (
<EmbedButton
positioning="fixed"
bottomOffset={60} // Offset by navbar height
/>
)}
</>
);
}
5. Multi-Department Support
function SupportPage() {
const { isInitialized } = useInitialize("your-api-key");
if (!isInitialized) return <div>Loading...</div>;
return (
<div className="support-grid">
<div className="support-card">
<h3>Sales Support</h3>
<p>Questions about pricing and plans</p>
<div style={{ position: 'relative', height: '400px' }}>
<EmbedButton positioning="embedded" side="left" />
</div>
</div>
<div className="support-card">
<h3>Technical Support</h3>
<p>Help with technical issues</p>
<div style={{ position: 'relative', height: '400px' }}>
<EmbedButton positioning="embedded" side="right" />
</div>
</div>
</div>
);
}
6. Contextual Events Based on User Actions
import { embedEvent, EventKeys, EmbedButton, useInitialize } from '@revrag-ai/embed-react';
function ProductPage({ product }) {
const { isInitialized } = useInitialize("your-api-key");
const handleAddToCart = async () => {
// Send custom event when user adds to cart
await embedEvent.event({
eventKey: EventKeys.CUSTOM_EVENT,
data: {
event_name: 'product_added_to_cart',
product_id: product.id,
product_name: product.name,
price: product.price
}
});
};
return (
<div>
<ProductDetails product={product} />
<button onClick={handleAddToCart}>Add to Cart</button>
{isInitialized && <EmbedButton />}
</div>
);
}
π Complete Integration Example
Hereβs a complete example showing initialization, user tracking, event listening, and the widget all working together:
import React, { useEffect, useState } from 'react';
import { EmbedButton, useInitialize, embedEvent, EventKeys } from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
function App() {
const { isInitialized, isLoading, error } = useInitialize("your-api-key");
const [agentStatus, setAgentStatus] = useState('idle');
const [userDataSent, setUserDataSent] = useState(false);
// Initialize user data when SDK is ready
useEffect(() => {
if (isInitialized && !userDataSent) {
initializeUserData();
}
}, [isInitialized, userDataSent]);
// Listen to agent events
useEffect(() => {
const handleAgentEvent = (event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
console.log('Agent connected:', event);
setAgentStatus('connected');
// Show notification, enable features, etc.
}
if (event.type === EventKeys.AGENT_DISCONNECTED) {
console.log('Agent disconnected:', event);
setAgentStatus('disconnected');
// Show feedback form, log analytics, etc.
}
};
embedEvent.addCallback(handleAgentEvent);
return () => embedEvent.removeCallback(handleAgentEvent);
}, []);
const initializeUserData = async () => {
try {
// Send user data first (required)
await embedEvent.event({
eventKey: EventKeys.USER_DATA,
data: {
app_user_id: 'user-123',
email: 'user@example.com',
name: 'John Doe',
subscription: 'premium'
}
});
setUserDataSent(true);
} catch (error) {
console.error('Failed to initialize user data:', error);
}
};
// Send custom event on button click
const handlePurchase = async () => {
await embedEvent.event({
eventKey: EventKeys.CUSTOM_EVENT,
data: {
event_name: 'purchase_completed',
amount: 99.99,
product_id: 'prod-123'
}
});
};
// Handle loading states
if (isLoading) {
return <div>Initializing AI Assistant...</div>;
}
if (error) {
return <div>Error: {error}</div>;
}
if (!isInitialized || !userDataSent) {
return <div>Loading...</div>;
}
return (
<div className="app">
<header>
<h1>My Application</h1>
<div className="status">
Agent Status: <span className={agentStatus}>{agentStatus}</span>
</div>
</header>
<main>
<YourMainContent />
<button onClick={handlePurchase}>Complete Purchase</button>
</main>
{/* AI Widget - will appear at bottom-right */}
<EmbedButton />
</div>
);
}
export default App;
Key Points in This Example:
- β
CSS Import: Imported at the top of the file
- β
SDK Initialization: Using
useInitialize hook with loading/error states
- β
User Data: Sent first before rendering the widget
- β
Event Listeners: Set up to monitor agent connection status
- β
Custom Events: Tracked when user performs actions
- β
Widget Rendering: Only rendered after successful initialization
β‘ Framework-Specific Notes
React + Vite
β
Works perfectly with no additional configuration
Next.js
β
Fully compatible with both App Router and Pages Router
β οΈ Import CSS in root layout or _app file
Create React App
β
Works out of the box
β οΈ Import CSS in index.tsx
Tailwind CSS Projects
β
No conflicts! The library uses custom embed-* prefixed classes
β
Your Tailwind styles wonβt affect the widget
β
Widget styles wonβt affect your app
π Troubleshooting
Solution: Make sure youβve imported the CSS file:
import '@revrag-ai/embed-react/style.css';
Solution: Ensure useInitialize has completed:
const { isInitialized } = useInitialize("your-api-key");
if (!isInitialized) return <div>Loading...</div>;
Solution: Use the bottomOffset prop:
<EmbedButton positioning="fixed" bottomOffset={60} />
Solution: This is handled automatically! The widget is fully responsive.
Events not being sent
Solution: Ensure youβve sent USER_DATA event first with app_user_id:
await embedEvent.event({
eventKey: EventKeys.USER_DATA,
data: {
app_user_id: 'user-123',
// ... other data
}
});
Agent event listeners not firing
Solution: Make sure callbacks are registered before agent connection:
useEffect(() => {
const handleEvent = (event) => {
// Your event handling logic
};
embedEvent.addCallback(handleEvent);
return () => embedEvent.removeCallback(handleEvent);
}, []);
βUser identity not foundβ error
Solution: Send USER_DATA event before any other events:
// β
Correct order
await embedEvent.event({ eventKey: EventKeys.USER_DATA, data: { app_user_id: 'user-123' } });
await embedEvent.event({ eventKey: EventKeys.CUSTOM_EVENT, data: { ... } });
// β Wrong order
await embedEvent.event({ eventKey: EventKeys.CUSTOM_EVENT, data: { ... } }); // Error!
Custom events being blocked
Solution: Only USER_DATA and CUSTOM_EVENT are allowed for manual sending. Agent events (AGENT_CONNECTED, AGENT_DISCONNECTED) are auto-tracked and can only be listened to, not manually sent.
π Checklist
Before deploying, ensure:
Basic Setup:
Event System:
Production Readiness:
π Support
π Youβre All Set!
The widget is now ready to use. Itβs:
- β
Fully responsive
- β
Framework-agnostic
- β
Tailwind-compatible
- β
Production-ready
- β
Mobile-optimized
- β
Real-time event tracking
- β
Voice agent monitoring
- β
User context aware
Quick Reference
Import everything you need:
import {
EmbedButton, // The main widget component
EmbedProvider, // Built-in provider for automatic widget management
useInitialize, // SDK initialization hook
embedEvent, // Event management API
EventKeys, // Event type constants
} from '@revrag-ai/embed-react';
import '@revrag-ai/embed-react/style.css';
Initialize and track:
// 1. Initialize SDK
const { isInitialized } = useInitialize("your-api-key");
// 2. Send user data
await embedEvent.event({
eventKey: EventKeys.USER_DATA,
data: { app_user_id: 'user-123' }
});
// 3. Listen to agent events
embedEvent.addCallback((event) => {
if (event.type === EventKeys.AGENT_CONNECTED) {
console.log('Agent connected!');
}
});
// 4. Render widget
<EmbedButton />
Happy coding! π