Website Integration Guide
Learn how to integrate your Optimly agents into your website for seamless customer interactions.
Quick Start Integration
1. Basic Chat Widget Setup
Add this code to your website's HTML:
<!-- Optimly Chat Widget -->
<div id="optimly-chat-widget"></div>
<script>
(function() {
// Configuration
const config = {
agentId: 'YOUR_AGENT_ID',
apiKey: 'YOUR_API_KEY',
baseUrl: 'https://api.optimly.io'
};
// Create chat interface
function createChatWidget() {
const widget = document.getElementById('optimly-chat-widget');
widget.innerHTML = `
`;
}
// Send message function
window.sendMessage = async function() {
const input = document.getElementById('message-input');
const message = input.value.trim();
if (!message) return;
// Add user message to chat
addMessageToChat(message, 'user');
input.value = '';
try {
// Send to Optimly API
const response = await fetch(`${config.baseUrl}/external/agent/v2`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${config.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
chat_id: getCurrentChatId(),
content: message
})
});
const data = await response.json();
addMessageToChat(data.response, 'bot');
} catch (error) {
addMessageToChat('Sorry, I\'m having trouble connecting. Please try again.', 'bot');
}
};
// Add message to chat display
function addMessageToChat(message, sender) {
const messagesContainer = document.getElementById('chat-messages');
const messageDiv = document.createElement('div');
messageDiv.className = sender === 'user' ? 'user-message' : 'bot-message';
messageDiv.style.cssText = `
margin: 10px 0;
padding: 10px;
border-radius: 10px;
${sender === 'user'
? 'background: #007bff; color: white; margin-left: 50px; text-align: right;'
: 'background: #f1f1f1; margin-right: 50px;'
}
`;
messageDiv.textContent = message;
messagesContainer.appendChild(messageDiv);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// Get or create chat ID
function getCurrentChatId() {
let chatId = localStorage.getItem('optimly-chat-id');
if (!chatId) {
chatId = 'chat_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
localStorage.setItem('optimly-chat-id', chatId);
}
return chatId;
}
// Handle Enter key
document.addEventListener('keypress', function(e) {
if (e.key === 'Enter' && e.target.id === 'message-input') {
sendMessage();
}
});
// Initialize when page loads
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', createChatWidget);
} else {
createChatWidget();
}
})();
</script>
2. Configuration
Replace these values in the code above:
YOUR_AGENT_ID
: Your agent's unique identifierYOUR_API_KEY
: Your agent's API key from the dashboard
Advanced Integration Options
Custom Styling
Customize the chat widget appearance:
/* Add to your CSS file */
.chat-container {
font-family: 'Arial', sans-serif;
box-shadow: 0 5px 40px rgba(0,0,0,0.16);
z-index: 1000;
}
.chat-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.user-message {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.bot-message {
background: #f8f9fa;
border-left: 3px solid #667eea;
}
React Integration
For React applications:
import React, { useState, useEffect } from 'react';
const OptimlyChat = ({ agentId, apiKey }) => {
const [messages, setMessages] = useState([
{ text: 'Hi! How can I help you today?', sender: 'bot' }
]);
const [input, setInput] = useState('');
const [chatId, setChatId] = useState(null);
useEffect(() => {
// Generate chat ID
const id = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
setChatId(id);
}, []);
const sendMessage = async () => {
if (!input.trim()) return;
const userMessage = { text: input, sender: 'user' };
setMessages(prev => [...prev, userMessage]);
setInput('');
try {
const response = await fetch('https://api.optimly.io/external/agent/v2', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
chat_id: chatId,
content: input
})
});
const data = await response.json();
const botMessage = { text: data.response, sender: 'bot' };
setMessages(prev => [...prev, botMessage]);
} catch (error) {
const errorMessage = {
text: 'Sorry, I\'m having trouble connecting. Please try again.',
sender: 'bot'
};
setMessages(prev => [...prev, errorMessage]);
}
};
return (
<div className="optimly-chat">
<div className="chat-header">
<h4>Chat with us</h4>
</div>
<div className="chat-messages">
{messages.map((msg, index) => (
<div key={index} className={`message ${msg.sender}`}>
{msg.text}
</div>
))}
</div>
<div className="chat-input">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
placeholder="Type your message..."
/>
<button onClick={sendMessage}>Send</button>
</div>
</div>
);
};
export default OptimlyChat;
Vue.js Integration
For Vue.js applications:
<template>
<div class="optimly-chat">
<div class="chat-header">
<h4>Chat with us</h4>
</div>
<div class="chat-messages" ref="messagesContainer">
<div
v-for="(message, index) in messages"
:key="index"
:class="`message ${message.sender}`"
>
{{ message.text }}
</div>
</div>
<div class="chat-input">
<input
v-model="input"
@keyup.enter="sendMessage"
placeholder="Type your message..."
type="text"
/>
<button @click="sendMessage">Send</button>
</div>
</div>
</template>
<script>
export default {
name: 'OptimlyChat',
props: {
agentId: String,
apiKey: String
},
data() {
return {
messages: [
{ text: 'Hi! How can I help you today?', sender: 'bot' }
],
input: '',
chatId: null
}
},
mounted() {
this.chatId = `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
},
methods: {
async sendMessage() {
if (!this.input.trim()) return;
this.messages.push({ text: this.input, sender: 'user' });
const messageText = this.input;
this.input = '';
try {
const response = await fetch('https://api.optimly.io/external/agent/v2', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
chat_id: this.chatId,
content: messageText
})
});
const data = await response.json();
this.messages.push({ text: data.response, sender: 'bot' });
} catch (error) {
this.messages.push({
text: 'Sorry, I\'m having trouble connecting. Please try again.',
sender: 'bot'
});
}
this.$nextTick(() => {
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
});
}
}
}
</script>
Integration Features
Lead Capture Integration
Automatically capture leads from your chat:
// Enhanced sendMessage function with lead detection
window.sendMessage = async function() {
const input = document.getElementById('message-input');
const message = input.value.trim();
if (!message) return;
addMessageToChat(message, 'user');
input.value = '';
try {
const response = await fetch(`${config.baseUrl}/external/agent/v2`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${config.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
chat_id: getCurrentChatId(),
content: message
})
});
const data = await response.json();
addMessageToChat(data.response, 'bot');
// Check if lead was captured
if (data.lead_captured) {
showLeadConfirmation();
}
} catch (error) {
addMessageToChat('Sorry, I\'m having trouble connecting. Please try again.', 'bot');
}
};
function showLeadConfirmation() {
const confirmation = document.createElement('div');
confirmation.innerHTML = `
<div style="background: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 10px; border-radius: 5px; margin: 10px 0;">
✅ Thank you! We've captured your information and will be in touch soon.
</div>
`;
document.getElementById('chat-messages').appendChild(confirmation);
}
Appointment Booking Integration
Enable appointment scheduling through chat:
// Monitor for appointment booking
function checkForAppointment(response) {
if (response.appointment_scheduled) {
showAppointmentConfirmation(response.appointment_details);
}
}
function showAppointmentConfirmation(details) {
const confirmation = document.createElement('div');
confirmation.innerHTML = `
<div style="background: #cce5ff; border: 1px solid #99ccff; color: #004085; padding: 15px; border-radius: 5px; margin: 10px 0;">
📅 <strong>Appointment Scheduled!</strong><br>
Date: ${details.date}<br>
Time: ${details.time}<br>
Duration: ${details.duration} minutes
</div>
`;
document.getElementById('chat-messages').appendChild(confirmation);
}
Mobile Optimization
Responsive Design
Make your chat widget mobile-friendly:
@media (max-width: 768px) {
.chat-container {
position: fixed !important;
bottom: 0 !important;
right: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
border-radius: 0 !important;
}
.chat-header {
border-radius: 0 !important;
}
}
Touch Optimization
Improve touch experience:
// Add touch-friendly interactions
document.addEventListener('touchstart', function(e) {
if (e.target.closest('.chat-container')) {
e.stopPropagation();
}
});
// Prevent zoom on input focus (iOS)
document.addEventListener('touchstart', function(e) {
if (e.target.tagName === 'INPUT') {
e.target.style.fontSize = '16px';
}
});
Analytics Integration
Track Chat Interactions
Monitor chat usage with Google Analytics:
// Add to your chat widget
function trackChatEvent(action, message) {
if (typeof gtag !== 'undefined') {
gtag('event', action, {
event_category: 'Chat',
event_label: message.substring(0, 50) // First 50 chars
});
}
}
// Use in sendMessage function
trackChatEvent('message_sent', message);
trackChatEvent('bot_response', data.response);
Monitor Performance
Track response times and user satisfaction:
let chatStartTime = Date.now();
function trackChatMetrics(responseTime, satisfied) {
// Send to your analytics service
fetch('/analytics/chat-metrics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
response_time: responseTime,
user_satisfied: satisfied,
session_duration: Date.now() - chatStartTime
})
});
}
Security Best Practices
API Key Security
Never expose your API key in frontend code! Instead:
- Use a backend proxy:
// Frontend - secure approach
const response = await fetch('/api/chat-proxy', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: message })
});
// Backend proxy (Node.js/Express example)
app.post('/api/chat-proxy', async (req, res) => {
try {
const response = await fetch('https://api.optimly.io/external/agent/v2', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPTIMLY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
chat_id: req.body.chat_id,
content: req.body.message
})
});
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({ error: 'Chat service unavailable' });
}
});
Input Validation
Sanitize user input:
function sanitizeInput(input) {
return input
.trim()
.substring(0, 1000) // Limit length
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '') // Remove scripts
.replace(/[<>]/g, ''); // Remove HTML tags
}
Troubleshooting
Common Issues
Chat widget not appearing:
- Check console for JavaScript errors
- Verify API key is correct
- Ensure all required files are loaded
Messages not sending:
- Check network connectivity
- Verify API endpoints are accessible
- Check browser console for error messages
Styling issues:
- Check for CSS conflicts
- Verify z-index is high enough
- Test across different browsers
Debug Mode
Add debug logging to your integration:
const DEBUG = true; // Set to false in production
function debugLog(message, data) {
if (DEBUG) {
console.log(`[Optimly Chat] ${message}`, data);
}
}
// Use throughout your code
debugLog('Sending message', { chatId, message });
debugLog('Received response', data);
Support
Need help with your integration?
- Technical Support: contact@optimly.io
- Developer Documentation: docs.optimly.io
- Community Discord: discord.gg/cqpQ4QPhfr
Examples & Templates
Check out our repository of integration examples: