Customization Guide
Learn how to customize the appearance and behavior of the Traise Widget to match your application's needs.
Theme Customization
Built-in Themes
The widget comes with two built-in themes:
// Light theme (default)
TraiseWidget.init({
apiKey: 'your-api-key',
mode: 'light'
});
// Dark theme
TraiseWidget.init({
apiKey: 'your-api-key',
mode: 'dark'
});
Dynamic Theme Switching
Change themes at runtime:
// Switch to dark theme
TraiseWidget.updateConfig({ mode: 'dark' });
// Switch back to light theme
TraiseWidget.updateConfig({ mode: 'light' });
// React to system theme
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
TraiseWidget.updateConfig({
mode: mediaQuery.matches ? 'dark' : 'light'
});
mediaQuery.addEventListener('change', (e) => {
TraiseWidget.updateConfig({
mode: e.matches ? 'dark' : 'light'
});
});
Position Customization
Built-in Positions
The widget supports four corner positions:
// Bottom right (default)
TraiseWidget.init({
apiKey: 'your-api-key',
position: 'bottom-right'
});
// Other positions
TraiseWidget.updateConfig({ position: 'bottom-left' });
TraiseWidget.updateConfig({ position: 'top-right' });
TraiseWidget.updateConfig({ position: 'top-left' });
Dynamic Position Changes
// Change position based on viewport
function updatePosition() {
const isMobile = window.innerWidth < 768;
TraiseWidget.updateConfig({
position: isMobile ? 'bottom-right' : 'bottom-left'
});
}
window.addEventListener('resize', updatePosition);
updatePosition();
Behavioral Customization
Auto-Show Widget
// Show widget automatically after page load
setTimeout(() => {
TraiseWidget.show();
}, 5000); // 5 seconds delay
// Show based on user behavior
let scrollCount = 0;
window.addEventListener('scroll', () => {
scrollCount++;
if (scrollCount >= 3 && !TraiseWidget.getStatus().visible) {
TraiseWidget.show();
}
});
// Show on specific pages
if (window.location.pathname === '/contact') {
setTimeout(() => TraiseWidget.show(), 2000);
}
Event-Based Customization
// React to widget events
TraiseWidget.on('widgetShown', () => {
console.log('Widget opened');
// Track analytics event
});
TraiseWidget.on('widgetHidden', () => {
console.log('Widget closed');
});
TraiseWidget.on('messageReceived', (message) => {
// Play notification sound
const audio = new Audio('/sounds/notification.mp3');
audio.play();
});
TraiseWidget.on('callStarted', (call) => {
console.log('Call initiated to:', call.phoneNumber);
});
Keyboard Shortcuts
// Custom keyboard shortcuts
document.addEventListener('keydown', (e) => {
// Ctrl/Cmd + Shift + C to toggle widget
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'C') {
e.preventDefault();
const status = TraiseWidget.getStatus();
if (status.visible) {
TraiseWidget.hide();
} else {
TraiseWidget.show();
}
}
// Escape to close widget
if (e.key === 'Escape' && TraiseWidget.getStatus().visible) {
TraiseWidget.hide();
}
});
Debug Mode
Enable debug mode for development and troubleshooting:
TraiseWidget.init({
apiKey: 'your-api-key',
debug: true // Shows debug panel and verbose logging
});
// Toggle debug mode at runtime
const currentConfig = TraiseWidget.getConfig();
TraiseWidget.updateConfig({
debug: !currentConfig.debug
});
// Access debug panel with Shift+D when widget is open
Demo Mode
Use demo mode for testing without connecting to backend services:
TraiseWidget.init({
apiKey: 'demo-key',
demoMode: true // Uses simulated data
});
Performance Optimization
Lazy Loading
// Load widget only when needed
let widgetLoaded = false;
async function loadWidget() {
if (!widgetLoaded) {
const { init, show } = await import('traise-widget');
await init({ apiKey: 'your-api-key' });
show();
widgetLoaded = true;
}
}
// Load on user interaction
document.querySelector('#support-button').addEventListener('click', loadWidget);
// Or load on scroll
window.addEventListener('scroll', loadWidget, { once: true });
Conditional Loading
// Only load widget for logged-in users
if (user.isAuthenticated) {
TraiseWidget.init({ apiKey: 'your-api-key' });
}
// Load based on business hours
const hour = new Date().getHours();
if (hour >= 9 && hour < 17) {
TraiseWidget.init({ apiKey: 'your-api-key' });
}
Client Context
Preload client information for personalized experience:
// Load client data on initialization
TraiseWidget.init({
apiKey: 'your-api-key'
}).then(widget => {
if (widget && user.isAuthenticated) {
TraiseWidget.loadClient({
name: user.name,
phoneNumber: user.phone,
email: user.email
});
}
});
// Update client context dynamically
TraiseWidget.loadClient({
name: 'John Doe',
phoneNumber: '+1234567890'
});
Testing Configurations
// Test different configurations
const configs = [
{ mode: 'light', position: 'bottom-right' },
{ mode: 'dark', position: 'bottom-left' },
{ mode: 'light', position: 'top-right' },
{ mode: 'dark', position: 'top-left' }
];
let currentConfig = 0;
function rotateConfig() {
TraiseWidget.updateConfig(configs[currentConfig]);
currentConfig = (currentConfig + 1) % configs.length;
console.log('Applied config:', configs[currentConfig - 1]);
}
// Rotate configurations for testing
// rotateConfig(); // Uncomment to test
Common Patterns
Support Hours Indicator
// Show widget only during support hours
function isWithinSupportHours() {
const now = new Date();
const day = now.getDay();
const hour = now.getHours();
// Monday-Friday, 9 AM - 5 PM
return day >= 1 && day <= 5 && hour >= 9 && hour < 17;
}
if (isWithinSupportHours()) {
TraiseWidget.init({ apiKey: 'your-api-key' });
} else {
console.log('Support widget not available outside business hours');
}
Page-Specific Behavior
// Different behavior for different pages
const pageConfigs = {
'/': { position: 'bottom-right', mode: 'light' },
'/pricing': { position: 'bottom-left', mode: 'light' },
'/contact': { position: 'top-right', mode: 'dark', autoShow: true }
};
const currentPath = window.location.pathname;
const config = pageConfigs[currentPath] || pageConfigs['/'];
TraiseWidget.init({
apiKey: 'your-api-key',
...config
});
if (config.autoShow) {
setTimeout(() => TraiseWidget.show(), 1000);
}