Universal JavaScript SDK for RI Survey integration
npm install ri-survey-sdkA universal JavaScript SDK for integrating surveys into external SaaS applications. This SDK handles user identification, survey targeting, and response collection with native JavaScript rendering for better control and performance.
✅ Native JavaScript Rendering - No iframe limitations, full control over survey appearance and behavior
✅ Multiple Question Types - Text, multiple choice, rating, scale, yes/no, checkbox, matrix, and more
✅ URL-Based Targeting - Automatic survey display based on current page URL
✅ Smart Route Detection - Handles SPA navigation and route changes with debouncing
✅ Progress Tracking - Visual progress bar and step indicators
✅ Responsive Design - Works seamlessly on all devices
✅ Customizable Styling - Theme colors, layout options, and branding
✅ Real-time Validation - Form validation and error handling
✅ Event Callbacks - Complete control over survey lifecycle events
✅ Cross-browser Compatibility - Works in all modern browsers
``bash`
npm install ri-survey-sdk
`javascript
import RISurveySDK from 'ri-survey-sdk';
// Initialize the SDK with URL-based targeting
const sdk = new RISurveySDK({
apiUrl: 'https://api.yoursurvey.com/backend/v1',
token: 'your-api-token',
autoFetchOnRouteChange: true, // Enable automatic URL targeting
routeChangeDebounceMs: 500 // Debounce route changes
});
// Identify the user
await sdk.identify({
external_user_id: 'user123',
external_user_email: 'user@example.com',
user_role: 'customer'
});
// Surveys will now automatically show based on URL targeting!
// Or manually show a specific survey:
await sdk.showSurvey('survey-id', {
onComplete: (response) => {
console.log('Survey completed:', response);
},
onError: (error) => {
console.error('Survey error:', error);
},
skippable: true
});
`
`javascript`
const sdk = new RISurveySDK({
apiUrl?: string, // Optional, defaults to http://localhost:8000/backend/v1
token: string // Required API token
});
`javascript`
await sdk.identify({
external_user_id: string,
external_user_email: string,
user_role?: string, // Optional, defaults to 'user'
metadata?: Record
});
#### Modal Survey (showSurvey)
`javascript`
await sdk.showSurvey(surveyId, {
onComplete?: (response: any) => void,
onError?: (error: Error) => void,
onClose?: () => void,
skippable?: boolean, // Allow users to close the survey
userId?: string // Override user ID for this survey
});
#### Embedded Survey (embedSurvey)
`javascript`
await sdk.embedSurvey(surveyId, 'container-id', {
// All showSurvey options plus:
width?: string, // e.g., '100%', '600px'
height?: string, // e.g., '400px', '100vh'
theme?: string, // 'light' or 'dark'
primaryColor?: string, // e.g., '#3B82F6'
showProgressBar?: boolean,
allowBack?: boolean, // Allow navigation back to previous questions
borderRadius?: string, // e.g., '8px'
backgroundColor?: string // e.g., '#ffffff'
});
`javascript
// Get all surveys for the current user
const surveys = await sdk.getSurveys(includeDrafts?: boolean);
// Get a specific survey
const survey = await sdk.getSurvey(surveyId);
// Submit a response manually
await sdk.submitResponse(surveyId, {
survey_id: surveyId,
responses: { questionId: 'answer' },
metadata?: Record
});
`
The SDK natively renders all major question types:
`javascript`
await sdk.embedSurvey(surveyId, 'container', {
primaryColor: '#3B82F6', // Blue
backgroundColor: '#ffffff', // White background
theme: 'light' // Light theme
});
`javascript`
await sdk.embedSurvey(surveyId, 'container', {
width: '100%',
height: '600px',
borderRadius: '12px',
showProgressBar: true,
allowBack: true
});
`javascript`
await sdk.showSurvey(surveyId, {
onComplete: (response) => {
// Survey was completed successfully
console.log('Responses:', response.responses);
console.log('Metadata:', response.metadata);
},
onError: (error) => {
// Survey encountered an error
console.error('Survey error:', error.message);
},
onClose: () => {
// Survey was closed (if skippable)
console.log('Survey closed by user');
}
});
`javascript`
{
survey_id: 'survey-123',
responses: {
'question-1': 'User answer',
'question-2': ['option1', 'option2'],
'question-3': 5
},
metadata: {
user_id: 'user-123',
completed_at: '2024-01-15T10:30:00Z'
}
}
- ✅ Chrome 60+
- ✅ Firefox 55+
- ✅ Safari 12+
- ✅ Edge 79+
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
The SDK provides comprehensive error handling:
`javascript`
try {
await sdk.showSurvey(surveyId, {
onError: (error) => {
// Handle specific survey errors
if (error.message.includes('not found')) {
console.log('Survey not available');
}
}
});
} catch (error) {
// Handle SDK initialization errors
console.error('SDK error:', error);
}
`javascript
// The SDK handles basic validation automatically
// For custom validation, you can intercept responses:
await sdk.showSurvey(surveyId, {
onComplete: (response) => {
// Custom validation logic
const hasRequiredFields = Object.values(response.responses)
.every(value => value !== null && value !== '');
if (!hasRequiredFields) {
alert('Please complete all required fields');
return;
}
// Submit to your backend
submitToBackend(response);
}
});
`
`javascript
// Get surveys based on user context
const surveys = await sdk.getSurveys(false);
// Filter surveys based on your business logic
const relevantSurveys = surveys.filter(survey => {
return survey.targeting_conditions?.some(condition => {
// Custom targeting logic
return condition.field === 'user_role' &&
condition.value === user.role;
});
});
`
If you're migrating from the iframe approach:
1. Replace iframe calls with native SDK methods
2. Update event listeners to use SDK callbacks
3. Customize styling using SDK options
4. Test thoroughly across different browsers
javascript
// Old iframe approach
const iframe = document.createElement('iframe');
iframe.src = 'https://survey.com/embed/survey-id';
container.appendChild(iframe);// Listen for messages
window.addEventListener('message', (event) => {
if (event.data.type === 'SURVEY_COMPLETED') {
handleCompletion(event.data.response);
}
});
`$3
`javascript
// New native approach
await sdk.embedSurvey('survey-id', 'container-id', {
onComplete: (response) => {
handleCompletion(response);
}
});
`Troubleshooting
$3
Survey not loading
- Check API token validity
- Verify survey ID exists
- Ensure user is properly identified
Styling issues
- Check CSS specificity
- Verify container dimensions
- Test in different browsers
Performance problems
- Monitor network requests
- Check browser console for errors
- Verify API endpoint availability
$3
Enable debug logging:
`javascript
const sdk = new RISurveySDK({
apiUrl: 'https://api.yoursurvey.com/backend/v1',
token: 'your-token',
debug: true // Enable debug logging
});
``1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
MIT License - see LICENSE file for details.