Live Chat Widget Module
The Live Chat Widget module provides an embeddable chat widget that enables real-time customer engagement directly on your website. Connect with visitors instantly, route conversations to human agents or AI bots, and manage all conversations from a unified dashboard.
Overview
Key Features:
- Embeddable Widget: Easy-to-install JavaScript widget for any website
- Real-time Messaging: Instant communication with website visitors
- Agent Dashboard: Manage conversations, assign agents, track metrics
- AI Bot Integration: Route to AI bots for automated responses
- Customizable Appearance: Match your brand colors and style
- Business Hours: Configure online/offline behavior
- Pre-chat Forms: Collect visitor information before chat starts
Quick Start
1. Enable the Module
- Go to Integrations > Modules
- Find Live Chat Widget in the Channels category
- Click Enable
2. Create a Widget
- Navigate to Live Chat > Widgets
- Click Create Widget
- Configure appearance and behavior
- Save the widget
3. Install on Your Website
Copy the embed code and add it to your website:
<script src="https://your-domain.com/api/widget/{token}/script.js" async></script>
The widget will automatically appear on your pages.
Widget Configuration
Basic Settings
| Setting | Description | Default |
|---|---|---|
| Name | Internal name for the widget | Required |
| Handler Type | Who handles chats: agent, ai_bot, or workflow |
agent |
| Active | Enable/disable the widget | true |
Appearance
| Setting | Description | Default |
|---|---|---|
| Primary Color | Main widget color (hex) | #000000 |
| Text Color | Text color on primary background | #ffffff |
| Position | Widget placement: bottom-right, bottom-left, top-right, top-left |
bottom-right |
| Border Radius | Roundness of corners (px) | 12 |
| Launcher Size | Size of the chat button (px) | 60 |
| Logo URL | Custom logo image URL | None |
Messages
| Setting | Description | Default |
|---|---|---|
| Welcome Title | Header text in chat window | "Hi there!" |
| Welcome Message | Greeting message to visitors | "How can we help you today?" |
| Input Placeholder | Placeholder in message input | "Type a message..." |
| Offline Message | Message when agents are offline | Custom message |
Behavior
| Setting | Description | Default |
|---|---|---|
| Collect Name | Ask for visitor's name before chat | true |
| Collect Email | Ask for visitor's email before chat | true |
| Sound Enabled | Play notification sounds | true |
| Show Branding | Display "Powered by AutoCom" | true |
| Allowed Domains | Restrict widget to specific domains | All domains |
Business Hours
Configure when your team is available:
{
"timezone": "Asia/Kolkata",
"monday": { "enabled": true, "start": "09:00", "end": "18:00" },
"tuesday": { "enabled": true, "start": "09:00", "end": "18:00" },
"wednesday": { "enabled": true, "start": "09:00", "end": "18:00" },
"thursday": { "enabled": true, "start": "09:00", "end": "18:00" },
"friday": { "enabled": true, "start": "09:00", "end": "17:00" },
"saturday": { "enabled": false },
"sunday": { "enabled": false }
}
Agent Management
Setting Up Agents
Agents are team members who can respond to live chat conversations.
- Go to Live Chat > Agents
- Click Add Agent
- Select a team member from the dropdown
- Set their maximum concurrent chats
- Click Save
Agent Status
| Status | Description |
|---|---|
| Online | Available to receive new chats |
| Away | Temporarily unavailable |
| Busy | Handling maximum chats |
| Offline | Not accepting new chats |
Automatic Assignment
When a new conversation starts:
- System finds available online agents
- Considers agent workload (current chat count vs max)
- Assigns to agent with lowest workload
- If no agents available, chat stays in queue
Conversation Management
Conversation States
pending → active → resolved/closed
↓
waiting (agent awaiting response)
| Status | Description |
|---|---|
| Pending | New conversation, not yet assigned |
| Active | Agent actively chatting |
| Waiting | Waiting for visitor response |
| Resolved | Issue solved, awaiting confirmation |
| Closed | Conversation ended |
Working with Conversations
From the Live Chat > Conversations page:
- View all conversations with status filters
- Search by visitor name, email, or message content
- Assign/reassign to different agents
- Set priority (low, normal, high, urgent)
- Add internal notes (not visible to visitor)
- Rate and provide feedback after resolution
Quick Actions
| Action | Description |
|---|---|
| Resolve | Mark issue as solved |
| Close | End the conversation |
| Reopen | Resume a closed conversation |
| Transfer | Assign to another agent |
Dashboard & Analytics
Dashboard Overview
The Live Chat dashboard shows:
- Active Chats: Currently ongoing conversations
- Pending Chats: Waiting for agent assignment
- Today's Stats: Conversations started, resolved today
- Average Response Time: Time to first agent response
- Online Agents: Currently available team members
Key Metrics
| Metric | Description |
|---|---|
| Response Time | Average time to first response |
| Resolution Time | Average time to resolve |
| Customer Satisfaction | Average rating (1-5 stars) |
| Chat Volume | Number of conversations over time |
| Agent Performance | Chats handled, ratings per agent |
API Reference
Dashboard
GET /api/v1/live-chat/dashboard
Returns stats, recent conversations, and active widgets.
Widgets
GET /api/v1/live-chat/widgets
POST /api/v1/live-chat/widgets
GET /api/v1/live-chat/widgets/{id}
PUT /api/v1/live-chat/widgets/{id}
DELETE /api/v1/live-chat/widgets/{id}
POST /api/v1/live-chat/widgets/{id}/toggle-active
POST /api/v1/live-chat/widgets/{id}/regenerate-token
GET /api/v1/live-chat/widgets/{id}/embed-code
Conversations
GET /api/v1/live-chat/conversations
GET /api/v1/live-chat/conversations/{id}
GET /api/v1/live-chat/conversations/{id}/messages
POST /api/v1/live-chat/conversations/{id}/messages
POST /api/v1/live-chat/conversations/{id}/assign
POST /api/v1/live-chat/conversations/{id}/resolve
POST /api/v1/live-chat/conversations/{id}/close
POST /api/v1/live-chat/conversations/{id}/reopen
PUT /api/v1/live-chat/conversations/{id}/priority
Agents
GET /api/v1/live-chat/agents
POST /api/v1/live-chat/agents
GET /api/v1/live-chat/agents/{id}
PUT /api/v1/live-chat/agents/{id}
DELETE /api/v1/live-chat/agents/{id}
GET /api/v1/live-chat/agents/me
PUT /api/v1/live-chat/agents/me/status
Public Widget Endpoints
These endpoints don't require authentication and are used by the embedded widget:
GET /api/widget/{token}/script.js
GET /api/widget/{token}/config
POST /api/widget/{token}/session
POST /api/widget/{token}/conversations
GET /api/widget/{token}/conversations/{id}/messages
POST /api/widget/{token}/conversations/{id}/messages
POST /api/widget/{token}/conversations/{id}/rate
Data Model
Widget
id: integer
name: string
token: string (unique, 32 chars)
is_active: boolean
primary_color: string (hex)
text_color: string (hex)
position: string
border_radius: integer
launcher_size: integer
launcher_icon: string
logo_url: string (nullable)
welcome_title: string
welcome_message: text
input_placeholder: string
offline_message: text
handler_type: 'agent' | 'ai_bot' | 'workflow'
handler_id: integer (nullable)
collect_email: boolean
collect_name: boolean
show_branding: boolean
sound_enabled: boolean
allowed_domains: array
business_hours: object
Visitor
id: integer
session_id: string (unique)
name: string (nullable)
email: string (nullable)
phone: string (nullable)
ip_address: string
user_agent: string
referrer: string (nullable)
current_page: string (nullable)
first_seen_at: timestamp
last_seen_at: timestamp
Conversation
id: integer
widget_id: integer
visitor_id: integer
agent_id: integer (nullable)
status: 'pending' | 'active' | 'waiting' | 'resolved' | 'closed'
priority: 'low' | 'normal' | 'high' | 'urgent'
source_url: string (nullable)
source_page_title: string (nullable)
last_message: text (nullable)
last_message_at: timestamp (nullable)
first_response_at: timestamp (nullable)
resolved_at: timestamp (nullable)
closed_at: timestamp (nullable)
rating: integer (1-5, nullable)
feedback: text (nullable)
Message
id: integer
conversation_id: integer
sender_type: 'visitor' | 'agent' | 'bot' | 'system'
sender_id: integer (nullable)
content: text
metadata: object (nullable)
is_read: boolean
read_at: timestamp (nullable)
Agent
id: integer
user_id: integer
status: 'online' | 'away' | 'busy' | 'offline'
max_concurrent_chats: integer (default: 5)
current_chats_count: integer
total_chats_count: integer
total_rating: integer
ratings_count: integer
last_active_at: timestamp (nullable)
Integration with AI
AI Bot Handler
When a widget uses handler_type: 'ai_bot':
- Visitor message is sent to configured AI service
- AI generates response based on context
- Response is sent back to visitor
- If AI can't handle, escalates to human agent
Workflow Handler
When a widget uses handler_type: 'workflow':
- Visitor is guided through predefined flow
- Collects structured information
- Routes to appropriate department/agent
- Creates support ticket if needed
Best Practices
Widget Placement
- Place widget on all customer-facing pages
- Avoid placing on checkout pages (distracting)
- Use different widgets for different sections (sales vs support)
Response Time
- Aim for < 1 minute first response during business hours
- Set clear offline expectations
- Use quick replies for common questions
Agent Training
- Train agents on product knowledge
- Use canned responses for FAQs
- Escalation procedures for complex issues
Visitor Experience
- Don't require too much info upfront
- Be proactive with greeting messages
- Follow up on unresolved conversations
Troubleshooting
Widget Not Appearing
- Verify embed code is correct
- Check browser console for JavaScript errors
- Ensure widget is active
- Check allowed domains configuration
Messages Not Sending
- Check network connectivity
- Verify API URL is accessible
- Check browser console for CORS errors
- Ensure widget token is valid
Agents Not Receiving Chats
- Verify agent status is "online"
- Check max concurrent chats limit
- Ensure agent is assigned to widget's scope
- Check conversation assignment settings
Real-Time Broadcast Architecture
Live chat messages and conversation updates are delivered in real-time via Laravel Reverb (WebSocket). Both the web admin panel and the mobile agent app subscribe to these events for instant updates without polling.
Broadcast Channels
Two channels are used per event:
| Channel | Type | Used By | Purpose |
|---|---|---|---|
private-tenant.{tenantId}.live-chat |
Private (auth required) | Admin panel + Mobile app | Agent-side real-time updates |
chat.conversation.{id} |
Public | Embedded widget | Visitor-side real-time updates |
Events broadcast:
chat.message.sent— fires on every new message (visitor, agent, bot, or system)chat.conversation.updated— fires on status changes, assignment, resolution, transfer
Tenant Resolution in Public Routes
The visitor-facing /api/widget/{token}/* routes run outside tenant middleware (they're public), so tenant() returns null inside the controller. To ensure broadcasts reach the correct tenant channel, each widget stores a tenant_id column that's set automatically when the widget is created.
The ChatMessageSent and ChatConversationUpdated events override broadcastTenantId():
protected function broadcastTenantId(): ?string
{
if (function_exists('tenant') && tenant()) {
return tenant('id');
}
return $this->conversation->widget?->tenant_id;
}
This means messages broadcast to private-tenant.{tenantId}.live-chat correctly regardless of whether the request originated from an authenticated agent route or a public widget endpoint.
Broadcast Payload
{
"conversation_id": 42,
"message": {
"id": 150,
"content": "Hello, I need help",
"sender_type": "visitor",
"sender_id": 10,
"sender_name": "Jane Doe",
"type": "text",
"created_at": "2026-04-12T08:30:00.000000Z"
},
"agent_name": "Albin Varghese",
"visitor_id": 10,
"widget_id": 1,
"handler_type": "agent",
"_tenant_id": "acme",
"_timestamp": "2026-04-12T08:30:00+00:00"
}
Push Notifications for Agents
When a visitor sends a message to a conversation assigned to a human agent, the system automatically sends a push notification to that agent via the notification system:
- Works whether the app is foreground, background, or closed
- Delivered via FCM/APNs on mobile
- Single notification per message (no duplicates between WebSocket and push)
- Suppressed automatically when the agent is viewing that specific chat screen
- Skipped for AI-bot-handled conversations (no human needs alerting)
Urgent incoming chat notification — when a chat is transferred or assigned to a specific agent, a high-priority notification fires with long vibration pattern (10 seconds, Android chat_urgent channel) to make sure the agent doesn't miss it.
Mobile App Integration
The mobile app maintains a singleton Echo instance shared between the notifications context and live chat — preventing multiple competing WebSocket connections. The live chat channel subscription happens globally in NotificationsContext so events arrive regardless of the active screen.
Event flow on mobile:
Visitor sends message (public widget)
│
▼
Backend: ChatConversation::addMessage()
│
├─► Broadcasts ChatMessageSent to private-tenant.{id}.live-chat
│ │
│ ▼
│ Mobile app (global NotificationsContext)
│ │
│ ├─► Calls onChatMessage() listeners
│ │ (chat detail screen updates if open)
│ │
│ └─► No local notification (handled by push)
│
└─► NotifyAgentOnVisitorMessage listener
│
▼
NotificationService::send()
│
├─► DB row in `notifications` table
│
└─► NotificationCreated broadcast to private-user.{id}
│
▼
Mobile app push notification
(tap → /(app)/m/chat/{id})
Troubleshooting Real-Time
Messages slow or delayed:
- Confirm the WebSocket is connected — check app logs for
[Echo] ✓ WebSocket CONNECTED - Verify the broadcast channel matches what the app subscribes to: both should contain the correct
tenant_id - If only polling fallback is delivering messages (15–30s delay), the WebSocket is failing silently — check private channel auth endpoint
Notifications not arriving:
- Check the conversation has an
assigned_agent_id(no notifications for unassigned chats) - Verify the widget's
handler_type— AI bot widgets skip notifications unless a human is assigned - Check Horizon is running and the
defaultqueue is being processed
Channel mismatch errors:
- If
tenant()returnsnullduring a widget request, thetenant_idcolumn onchat_widgetsmust be set. Run:UPDATE chat_widgets SET tenant_id = 'your-tenant-id' WHERE tenant_id IS NULL;
Next Steps
- Modules Overview - Understanding the module system
- Notifications - Push notification system
- Team Management - Managing users and permissions