Skip to main content

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 = `
<div class="chat-container" style="position: fixed; bottom: 20px; right: 20px; width: 350px; height: 500px; border: 1px solid #ccc; border-radius: 10px; background: white; display: flex; flex-direction: column;">
<div class="chat-header" style="background: #007bff; color: white; padding: 15px; border-radius: 10px 10px 0 0;">
<h4 style="margin: 0;">Chat with us</h4>
</div>
<div class="chat-messages" id="chat-messages" style="flex: 1; padding: 15px; overflow-y: auto;">
<div class="bot-message">Hi! How can I help you today?</div>
</div>
<div class="chat-input" style="padding: 15px; border-top: 1px solid #eee;">
<input type="text" id="message-input" placeholder="Type your message..." style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 5px;" />
<button onclick="sendMessage()" style="width: 100%; margin-top: 10px; padding: 10px; background: #007bff; color: white; border: none; border-radius: 5px;">Send</button>
</div>
</div>
`;
}

// 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 identifier
  • YOUR_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:

  1. 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?


Examples & Templates

Check out our repository of integration examples: