Architecting Video Waiting Room Experiences with Dynamic Content and Queue Position Updates
What This Guide Covers
This guide details the architectural pattern for implementing a dynamic, real-time video waiting room in Genesys Cloud CX that pushes live queue position updates and contextual content to the customer browser without requiring page reloads. The end result is a low-latency experience where the customer sees their exact position in line, estimated wait time, and relevant self-service options that update automatically as the queue state changes.
Prerequisites, Roles & Licensing
- Licensing: CX 2 or CX 3 license for agents; CX 1 license for customers is insufficient for video media. You require the Video Messaging or Video Conferencing add-on depending on whether you are using 1:1 video calls or multi-party video rooms. For this specific pattern (1:1 video call with a waiting room UI), the standard Video Calling feature set within CX 2/3 is required.
- Permissions:
Architect > Flow > EditTelephony > Trunk > Edit(for WebRTC/SIP trunking if using hybrid media)Video > Video Rooms > EditIntegrations > Web Messaging > EditData > Data Connector > Edit(for custom events)
- OAuth Scopes:
architect:flow:writevideo:video-room:readtelephony:trunk:read
- External Dependencies:
- A Genesys Cloud Hosted WebRTC Trunk (or SIP trunk with WebRTC capability).
- A frontend framework capable of handling Genesys Cloud Client SDK v2 or v3.
- A backend middleware service (Node.js, Python, etc.) to act as the bridge between Genesys Cloud Webhooks and the customer browser via WebSocket or Server-Sent Events (SSE). Genesys Cloud does not push real-time queue updates directly to the browser; you must engineer this bridge.
The Implementation Deep-Dive
1. Designing the Hybrid Media Flow in Genesys Cloud Architect
The core architectural challenge in video waiting rooms is that Genesys Cloud’s native video waiting room (the default “waiting” screen in the video SDK) is static. It does not expose dynamic queue position data to the client-side SDK in a structured, real-time manner. To solve this, we must decouple the media session from the information session.
We will use a Video Call Flow that routes to a standard Queue, but we will intercept the queue metrics via Webhooks to drive a separate WebSocket channel to the customer’s browser.
Step 1.1: Configure the Video Queue
Create a new Queue in Genesys Cloud.
- Name:
Video Support Queue - Media Type:
Video - Wrap-Up Code: Enable if required for compliance.
- Skill Requirements: Assign the specific skill (e.g.,
video-support) that your agents possess.
The Trap: Do not enable “Allow customers to chat while waiting” in the Queue settings if you intend to drive a custom UI. The native chat widget conflicts with custom WebSocket implementations for position updates. Keep the queue settings minimal.
Step 1.2: Build the Video Call Flow
Create a new Flow with Media Type set to Video.
-
Start Node: Connect to a Get Queue node. Select the
Video Support Queuecreated above. -
Set Variable: Before the queue node, use a Set Variable node to capture the
Call IDandQueue ID. Store these in flow variables:${call.id}and${queue.id}. -
Queue Node: Configure the Queue node to “Enqueue Call”.
- Timeout: Set to a reasonable value (e.g., 600 seconds) to prevent infinite hanging.
- Abandonment: Configure an abandonment action (e.g., hang up or transfer to voicemail).
-
Webhook Trigger (Critical Step): You need to know when the customer enters the queue and their position. Genesys Cloud does not expose “Position in Queue” directly in the standard IVR variables. You must use the Queue Statistics API or Webhooks.
Instead of relying on the Flow to calculate position, we will use a Webhook to notify your middleware when a call enters the queue.
Add a Webhook node immediately after the Queue node’s “Enqueue” outcome.
- Method:
POST - URL:
https://your-middleware.com/api/genesys/queue-entry - Body:
{ "callId": "${call.id}", "queueId": "${queue.id}", "timestamp": "${system.current-time}" }
- Method:
Architectural Reasoning: We are not calculating the position in the Flow because the Flow is stateless regarding other calls in the queue. The middleware holds the state of all active sessions. By pushing the callId to the middleware, the middleware can then poll the Genesys Cloud Queue Statistics API to determine the position.
2. Engineering the Middleware Bridge
The middleware is the brain of this operation. It maintains a WebSocket connection with the customer’s browser and polls Genesys Cloud for queue metrics.
Step 2.1: The Queue Position Logic
When the middleware receives the POST from the Architect Webhook:
- It establishes a WebSocket connection with the customer’s browser (identified by
callId). - It initiates a polling loop against the Genesys Cloud Queue Statistics API.
API Endpoint:
GET /api/v2/queues/{queueId}/stats?metric=waiters
The Trap: Polling frequency. Polling every 1 second causes rate limiting. Polling every 10 seconds creates a stale UI. The optimal pattern is adaptive polling. Start at 2 seconds. If the position does not change for 3 consecutive polls, increase the interval to 5 seconds. If the position changes, reset to 2 seconds.
Step 2.2: Calculating Estimated Wait Time
The Queue Stats API returns waiters (number of people ahead) and average-handle-time (AHT).
Formula:
Estimated Wait = (Position in Queue * Average Handle Time) / Number of Available Agents
You must also fetch availableAgents from:
GET /api/v2/queues/{queueId}/stats?metric=availableAgents
The Trap: Division by zero. If no agents are available, the wait time is infinite. Your middleware must handle this case by returning a message like “No agents currently available. Please try again later.” rather than crashing the UI.
3. Frontend Implementation with Genesys Cloud Client SDK
The customer’s browser loads a custom HTML/JS page. This page uses the Genesys Cloud Client SDK to handle the video media stream and a separate WebSocket client to handle the queue data.
Step 3.1: Initialize the Video Call
Use the Video module from the SDK.
import { Client, Video } from '@genesyscloud/purecloud-client-sdk-v2';
const client = new Client({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET', // Or use JWT flow for user context
basePath: 'https://api.mypurecloud.com'
});
// Authenticate
await client.auth.login({
grant_type: 'client_credentials',
scope: ['video:video-room:read', 'telephony:call:read']
});
// Start the video call session
// Note: The actual dialing is triggered by the backend or via a Deep Link
// Here we assume the user is already in the call context or we initiate it via REST
Architectural Reasoning: Do not use the Video Room SDK for 1:1 support calls. Use the Telephony and Video modules that support direct 1:1 calls. Video Rooms are for multi-party conferencing and have higher latency and different licensing.
Step 3.2: Integrate WebSocket for Dynamic Content
Create a WebSocket connection to your middleware.
const ws = new WebSocket(`wss://your-middleware.com/ws/${callId}`);
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
// Update UI
document.getElementById('position').innerText = data.position;
document.getElementById('waitTime').innerText = formatTime(data.estimatedWait);
// Dynamic Content: Show relevant articles based on wait time
if (data.estimatedWait > 120) {
document.getElementById('selfService').style.display = 'block';
}
};
4. Dynamic Content Injection
The goal is to reduce abandonments by providing value while the customer waits.
Step 4.1: Context-Aware Content
Your middleware should not just send numbers. It should send content IDs.
In your Architect Flow, before the queue, use a Get Knowledge Article node or a Webhook to fetch relevant articles based on the customer’s initial intent (captured via IVR or URL parameters).
Store these article IDs in the middleware session associated with the callId.
Step 4.2: The “Take a Number” Pattern
If the wait time exceeds a threshold (e.g., 3 minutes), the middleware sends a callback_offer event.
{
"event": "callback_offer",
"message": "Your wait time is 5 minutes. Would you like to be called back?",
"action": "accept_callback"
}
When the user clicks “Accept”, the middleware triggers a Genesys Cloud API call to Transfer the Call to a Callback Queue or Hangup and schedule a callback via the Callback API.
The Trap: Do not hang up the call immediately upon callback acceptance. You must first ensure the callback is scheduled. If you hang up first, you lose the call context. Use the Transfer to Callback node in Architect, triggered by a REST API call from your middleware.
Validation, Edge Cases & Troubleshooting
Edge Case 1: WebSocket Disconnect During Video Session
The Failure Condition: The customer’s internet connection drops briefly. The WebSocket closes. The video media stream (SRTP) may also drop, but often it reconnects automatically via WebRTC ICE negotiation. The UI, however, stops updating. The customer sees “Position: 5” forever, even if they are now Position 1.
The Root Cause: The WebSocket is not resilient to transient network failures. The Genesys Cloud Video SDK handles media reconnection, but your custom data channel does not.
The Solution: Implement Heartbeat and Reconnection Logic in the frontend WebSocket client.
- Send a ping every 30 seconds.
- If no pong is received, attempt to reconnect.
- Upon reconnection, send a
GETrequest to your middleware to fetch the current position, not just listen for deltas. This ensures the UI is never stale.
Edge Case 2: Queue Position Skew Due to Agent Availability
The Failure Condition: The UI shows “Position 1”, but the customer waits for 2 minutes. They abandon the call.
The Root Cause: The calculation Position * AHT / Available Agents is an estimate. It does not account for:
- Agents wrapping up from previous calls.
- Agents going on break.
- Priority queues (if other queues share the same agents).
The Solution: Display a Range, not a precise number.
Instead of “Wait: 2 minutes”, display “Wait: 1-3 minutes”.
In your middleware, calculate the min and max based on the standard deviation of recent AHT. This manages expectations and reduces perceived wait time frustration.
Edge Case 3: Media Session Timeout vs. Queue Timeout
The Failure Condition: The customer is in the queue. The Architect Flow has a 10-minute timeout. The Genesys Cloud WebRTC session has a default 30-minute timeout. The customer waits 11 minutes. The Flow hangs up the call, but the WebRTC session in the browser remains active, showing a black screen with “Call Ended” but no audio.
The Root Cause: The media session and the signaling session are not always perfectly synchronized in custom SDK implementations. When the Flow ends the call, it sends a SIP BYE. The SDK must interpret this and clean up the local media tracks.
The Solution: In the Genesys Cloud Client SDK, listen for the callEnd or mediaEnd events.
videoCall.on('callEnd', () => {
// Force cleanup of UI and WebSocket
ws.close();
alert('Your call has ended.');
window.location.reload(); // Or redirect to a thank you page
});
Ensure your Architect Flow’s “Hangup” action is configured to send a proper SIP BYE with a reason code (e.g., 487 Request Terminated). This helps the SDK distinguish between a normal hangup and a network failure.