This demo showcases a simulation of call center where callers queue up to talk to available agents using OpenTok.
These are the OpenTok features used in this demo:
Install NodeJS v8.0+
Install dependencies with
$ npm install
Get OpenTok API keys and set them as environment variables:
$ export OPENTOK_API_KEY="opentok-api-key-here" $ export OPENTOK_API_SECRET="opentok-api-secret-here"
Register session monitoring callback in your TokBox account for the path
/ot_callback. For example, if this application is hosted at
https://example.com, register this URL:
Build assets for the app, run:
$ npm run app-build
$ npm start
This will start the application on port
8080. To change port, set the
PORT environment variable. For example, to start the application on port
3000, do this:
$ PORT=3000 npm start
To start secure server, set the
SECURE environment variable to some value. For example, this will start the application on HTTPS port 3000:
$ SECURE=1 PORT=3000 npm start
For development use, you can compile assets in development mode and launch server by running:
$ npm run dev
This application builds a simple queue where callers can wait for agents to talk to them. It uses NodeJS as the backend and VueJS in the frontend.
Note: The server stores all data in-memory for the purpose of this demo. A real-world application should use some database instead.
Backend logic for this demo is present in server.js. These are what the server does:
Callerconstructor used to represent a caller and provide methods to perform actions on each caller.
Agentconstructor used to represent an agent and provide methods to perform actions on each agent.
The frotend is a simple single-page application (SPA) built on VueJS with vue-router to route between agent and caller screens. It uses UIKit for drawing the UI. The demo intentionally keeps things simple without breaking down code into further components or customizing much of the UI elements.
These are the relevant files:
app.js: Bootstrapping script that loads vue and vue-router and mounts routes from the components.
components/: Directory where all vue components are stored
components/home.vue: Template for the homepage of the demo
components/caller.vue: Component used for the caller screen. This sets up the caller's initial form and then manages the whole lifecycle of the caller.
components/agent.vue: Component used for the agent screen. This manages entire lifecycle of the agent.
components/ot-subscriber.vueprovide reusable components for OpenTok publisher and subscriber objects.
The agent screen has all the magic in this demo. Here is how agent screen handles callers in the frotnend:
So, the agent keeps on switching between OpenTok sessions - connecting to them and disconnecting as required. This whole process takes a reasonably short time. At each stage, the application sends out signals for each event so that the client UI can adjust accordingly.
A core part of this demo is managing caller queue and assigning callers to agents. All of this happens on the server side in
server.js. It uses OpenTok's session monitoring to reliably determine when a caller has connected or disconnected.
Call queue management is composed of six main pieces:
callers: List of current callers. This is a
Mapthat uses caller ID as key and its corresponding
Callerinstance as the value.
agents: List of active agents. This is another
Mapthat uses agent ID as key and its corresponding
Agentinstance as the value.
pendingQueue: An array that stores callers (instances of
Caller) who are yet to be assigned to any agent.
assignCaller(caller): A function that takes a
Callerinstance as argument and assigns it to an agent. If no agent is connected, this function adds the given caller to
agent.assignPending(limit = 1): A method on
Agentthat assigns a number of callers from
pendingQueueto given agent in FIFO mode - callers who were in the queue earlier are assigned first.
removeCaller(callerID): A function that removes a caller from list of active callers and also from
Here is a step-by-step description of how the call queue logic is handled:
Callerconstructor by calling
new Caller()based on the caller's supplied details - name, reason and whether the call is audio-only
handleConnectionCreated()handler to match the connection data with the caller ID and marks the caller as ready.
agent.assignPending(1)if the agent has less than 3 callers assigned at that point.
GET /call/:id/delete. This calls
removeCaller(callerID)internally. The frontend can call this HTTP endpoint when any of these events happen:
pendingQueue. That way, other agents can pick up those callers.