Context-Aware Chat
This guide shows you how to make your ept AI chatbot context-aware by providing user and page context with each message, and displaying relevant prompt questions based on what the user is currently viewing.
Overview
Context-aware chat enhances the user experience by:
- Providing Relevant Context: The AI knows what page the user is on, their role, and other contextual information
- Dynamic Prompt Questions: Show different suggested questions based on the current page or user state
- Personalized Responses: The AI can provide more targeted and relevant answers
- Better User Experience: Users get more relevant help without having to explain their context
Prerequisites
Before implementing context-aware features, ensure you have:
- Basic Integration Complete: Your chatbot must be properly integrated (see Integrating the Chatbot)
- Access Token Setup: Either using
eptClientId
for automatic token management or manualaccessToken
- User Context Data: Access to relevant user and page information in your application
Quick Setup
Here's a minimal example showing both context metadata and dynamic prompts:
<script>
window.eptAIConfig = {
// Authentication - choose one option
eptClientId: 'YOUR_PUBLIC_CLIENT_ID', // Option A: Automatic token management
// accessToken: 'your-jwt-token', // Option B: Manual token management
// Bot customization
botName: 'Product Expert',
botImage: 'https://example.com/bot.png',
loadingText: 'Thinking…',
// Context sent with each message
eptMetaData: {
page: location.pathname,
url: location.href,
locale: document.documentElement.lang || 'en',
// Add any relevant context for your application
section: 'documentation',
userRole: 'developer'
},
// Dynamic prompt questions
defaultQuestions: [
'What can you help me do here?',
'Show me the top use cases.'
],
};
</script>
<!-- Load the chatbot -->
<script src="https://assets.ept.ai/chat/v1/ept_chat_loader_bundle.js?v=1.0.0" async></script>
Providing Context Metadata
How It Works
When you send a message, the chatbot automatically includes window.eptAIConfig.eptMetaData
in the payload. The AI uses this context to provide more relevant and targeted responses. You can update eptMetaData
at any time, and the new values will be used with the next message.
Recommended Context Fields
Keep context information useful but privacy-safe:
Navigation Context:
page
: Current page pathurl
: Full current URLsection
: High-level section (docs, pricing, dashboard, etc.)locale
: User's language preference
Application State:
productId
: Current product being viewedversion
: Application or product versionfeatureFlags
: Active features for this userselectedSku
: Currently selected product variant
User Identity (Coarse-Grained):
accountId
: Account identifier (avoid if privacy-sensitive)userRole
: User's role (admin, developer, viewer, etc.)plan
: Subscription plan levelpermissions
: Available features or capabilities
⚠️ Privacy Note: Avoid including personally identifiable information (PII) unless explicitly disclosed to users.
Implementation Examples
- Static Sites
- Single Page Apps
- React Integration
For traditional multi-page websites, set context on each page:
<script>
// Update context per page
window.eptAIConfig.eptMetaData = {
page: location.pathname,
url: location.href,
section: location.pathname.startsWith('/docs') ? 'docs'
: location.pathname.startsWith('/pricing') ? 'pricing'
: location.pathname.startsWith('/support') ? 'support'
: 'site',
locale: document.documentElement.lang || 'en'
};
</script>
For SPAs, update context when routes change:
function computeMetadata() {
return {
page: location.pathname,
url: location.href,
section: location.pathname.startsWith('/docs') ? 'docs'
: location.pathname.startsWith('/pricing') ? 'pricing'
: location.pathname.startsWith('/dashboard') ? 'dashboard'
: 'site',
// Application context
accountId: window.APP?.account?.id ?? null,
userRole: window.APP?.user?.role ?? null,
plan: window.APP?.account?.plan ?? null,
featureFlags: window.APP?.featureFlags ?? [],
locale: window.APP?.user?.locale ?? 'en'
};
}
function refreshChatContext() {
// Next message will include the updated metadata
window.eptAIConfig.eptMetaData = computeMetadata();
console.log('Chat context updated:', window.eptAIConfig.eptMetaData);
}
// Update context on route changes
window.addEventListener('popstate', refreshChatContext);
// For React Router, Vue Router, etc.
// React: useEffect(() => refreshChatContext(), [location]);
// Vue: watch(() => route.path, refreshChatContext);
For React applications with React Router:
import { useEffect, useLocation } from 'react';
function ChatContextProvider({ children }) {
const location = useLocation();
const user = useUser(); // Your user context hook
const account = useAccount(); // Your account context hook
useEffect(() => {
const updateChatContext = () => {
window.eptAIConfig = {
...window.eptAIConfig,
eptMetaData: {
page: location.pathname,
url: window.location.href,
section: getSection(location.pathname),
accountId: account?.id,
userRole: user?.role,
plan: account?.plan,
locale: user?.locale || 'en'
}
};
};
updateChatContext();
}, [location, user, account]);
return children;
}
function getSection(pathname) {
if (pathname.startsWith('/docs')) return 'docs';
if (pathname.startsWith('/pricing')) return 'pricing';
if (pathname.startsWith('/dashboard')) return 'dashboard';
return 'site';
}
Dynamic Prompt Questions
How It Works
On first connect, the chatbot displays a list of suggested question buttons from window.eptAIConfig.defaultQuestions
. When users click a suggestion, it fills the input field and sends the message automatically. This provides an excellent way to guide users toward the most relevant questions for their current context.
Benefits of Dynamic Prompts
- Reduced Friction: Users don't need to think about what to ask
- Better Engagement: Relevant suggestions increase interaction rates
- Contextual Guidance: Show different prompts based on page/section
- Discoverability: Help users discover chatbot capabilities
Static Implementation (Multi-Page Sites)
For traditional websites, set different defaultQuestions
on each page:
- Documentation Page
- Pricing Page
- Support Page
<script>
window.eptAIConfig = {
...window.eptAIConfig,
defaultQuestions: [
'Show me a code example for this feature',
'How do I troubleshoot common errors?',
'What are the API rate limits?',
'Find integration guides for my platform'
],
eptMetaData: {
...window.eptAIConfig?.eptMetaData,
section: 'docs',
page: location.pathname
}
};
</script>
<script>
window.eptAIConfig = {
...window.eptAIConfig,
defaultQuestions: [
'Compare Pro vs Enterprise for 50 users',
'Calculate pricing for 200 seats with SSO',
'What features are included in each plan?',
'Do you offer volume discounts?'
],
eptMetaData: {
...window.eptAIConfig?.eptMetaData,
section: 'pricing',
page: location.pathname
}
};
</script>
<script>
window.eptAIConfig = {
...window.eptAIConfig,
defaultQuestions: [
'Help me troubleshoot a login issue',
'How do I reset my account password?',
'Contact information for enterprise support',
'Check the status of my support ticket'
],
eptMetaData: {
...window.eptAIConfig?.eptMetaData,
section: 'support',
page: location.pathname
}
};
</script>
Dynamic Implementation (Single Page Apps)
For SPAs, the default prompt list renders only once. To show different prompts when routes change, you need to manually update the DOM. Here's a complete implementation:
// Map routes to relevant prompt questions
function getPromptsForPath(path) {
if (path.startsWith('/docs')) {
return [
'Show me code examples for this feature',
'Help me troubleshoot integration errors',
'What are the API authentication requirements?',
'Find related documentation topics'
];
}
if (path.startsWith('/pricing')) {
return [
'Compare Pro vs Enterprise for 100 users',
'Calculate total cost of ownership',
'What discounts are available?',
'Explain billing and payment options'
];
}
if (path.startsWith('/dashboard')) {
return [
'How do I configure this setting?',
'Help me understand these metrics',
'Show me how to export data',
'What permissions do I need for this action?'
];
}
// Default prompts for other pages
return [
'What can you help me with here?',
'Show me the most relevant features',
'How do I get started?',
'Find integrations for my use case'
];
}
function renderPromptQuestions(prompts) {
const chatBox = document.getElementById('eptai-chat-box');
if (!chatBox) {
console.warn('Chat box not found, retrying...');
setTimeout(() => renderPromptQuestions(prompts), 500);
return;
}
// Find or create the prompt container
let container = chatBox.querySelector('.displayMessageContainer');
if (!container) {
container = document.createElement('div');
container.className = 'displayMessageContainer';
container.appendChild(document.createElement('ul'));
chatBox.appendChild(container);
}
const ul = container.querySelector('ul');
ul.innerHTML = '';
// Create prompt buttons
prompts.forEach(question => {
const li = document.createElement('li');
li.className = 'eptai-default-question';
li.textContent = question;
li.style.cursor = 'pointer';
li.addEventListener('click', () => {
// Fill input and send message (mimics built-in behavior)
const input = document.getElementById('eptai-chat-input');
const sendBtn = document.getElementById('eptai-send-btn');
if (input && sendBtn) {
input.value = question;
setTimeout(() => sendBtn.click(), 100);
container.remove(); // Remove prompts after use
}
});
ul.appendChild(li);
});
}
function updatePromptsForCurrentRoute() {
const prompts = getPromptsForPath(location.pathname);
renderPromptQuestions(prompts);
// Also update context metadata
window.eptAIConfig.eptMetaData = {
...window.eptAIConfig.eptMetaData,
page: location.pathname,
url: location.href,
timestamp: new Date().toISOString()
};
}
// Initialize prompts when chat loads
document.addEventListener('DOMContentLoaded', () => {
// Wait for chat to initialize
setTimeout(updatePromptsForCurrentRoute, 1000);
});
// Update prompts on route changes (adjust event based on your router)
window.addEventListener('popstate', updatePromptsForCurrentRoute);
// For frameworks, call updatePromptsForCurrentRoute() when routes change
// React: useEffect(() => updatePromptsForCurrentRoute(), [location])
// Vue: watch(() => route.path, updatePromptsForCurrentRoute)
Advanced Features
User-Specific Context
You can provide user-specific context to make responses even more personalized:
// Example: E-commerce site context
window.eptAIConfig.eptMetaData = {
page: location.pathname,
section: 'product-page',
productId: 'SKU-12345',
productCategory: 'electronics',
userSegment: 'enterprise',
viewingHistory: ['product-A', 'product-B'],
cartItems: 3,
isLoggedIn: true,
userRole: 'buyer'
};
Conditional Prompts
Show different prompts based on user state or permissions:
function getContextualPrompts() {
const user = getCurrentUser();
const path = location.pathname;
if (path.startsWith('/admin') && user.role === 'admin') {
return [
'How do I manage user permissions?',
'Show me system health metrics',
'Help with configuration settings'
];
}
if (path.startsWith('/dashboard') && !user.isSubscribed) {
return [
'What features are available in paid plans?',
'How do I upgrade my account?',
'Compare pricing options'
];
}
// Standard prompts for regular users
return [
'How do I get started?',
'Show me popular features',
'Help me with my account'
];
}
Real-Time Context Updates
Update context based on user actions in real-time:
// Example: Update context when user selects a product
function onProductSelected(productId) {
window.eptAIConfig.eptMetaData = {
...window.eptAIConfig.eptMetaData,
selectedProduct: productId,
timestamp: new Date().toISOString()
};
}
// Example: Update context when filters change
function onFiltersChanged(filters) {
window.eptAIConfig.eptMetaData = {
...window.eptAIConfig.eptMetaData,
activeFilters: filters,
resultCount: getFilteredResultCount(filters)
};
}
Best Practices
Context Management
- Keep Context Relevant: Only include information that helps the AI provide better responses
- Update Frequently: Refresh context when user state or page content changes significantly
- Privacy First: Never include sensitive personal information unless explicitly consented
- Performance Aware: Avoid sending large objects; keep metadata lightweight
Prompt Design
- Be Specific: Write prompts that are clear and actionable
- Use User Language: Match the terminology your users understand
- Limit Options: Show 3-5 prompts maximum to avoid overwhelming users
- Test Effectiveness: Monitor which prompts are clicked most often
Implementation Tips
- Graceful Degradation: Ensure the chatbot works even if context updates fail
- Error Handling: Add try-catch blocks around context update functions
- Performance: Debounce rapid context updates to avoid overwhelming the system
- Testing: Test context updates across different routes and user states
Troubleshooting
Common Issues
Prompts Not Updating
- Ensure you're using the DOM manipulation approach for SPAs
- Check that the chat widget has fully loaded before updating prompts
- Verify that event listeners are properly attached to route changes
Context Not Being Sent
- Confirm
eptMetaData
is properly structured as a plain object - Check browser console for any JavaScript errors
- Verify that context updates happen before sending messages
Performance Issues
- Avoid updating context on every scroll or mouse movement
- Use debouncing for rapid state changes
- Keep metadata objects small and focused
Debugging Context
Add logging to verify context is working correctly:
function debugContext() {
console.log('Current chat context:', window.eptAIConfig.eptMetaData);
}
// Call after context updates
window.addEventListener('ept-context-updated', debugContext);
Next Steps
After implementing context-aware chat:
- Monitor Performance - Track how context affects response quality
- Advanced Integrations - Connect with CRM and support systems
- Design Customization - Style prompts to match your brand
Related Documentation
- Integrating the Chatbot - Basic integration setup
- Configuring Design - Customize appearance and styling
- Continuous Improvement - Monitor and optimize performance