We've had about a month of tinkering since rollout to figure out how to keep our team on top of incoming chats (we're using the LiveAgent snap-ins with Omni Channel routing, but this will work for either.
At a minimum, we've found that our users need to have their chat console open in a non-minimized window with no other tabs - or even open in another browser by itself (some use Chrome, but have chat open in Firefox). This prevents suppression of the alert sound from the browser ignoring hidden tabs.
There appear to be some periodically reappearing known issues with the 'status update on push timeout' not working in some orgs. This means that you can't get a user to move to busy/offline when they do miss a chat. This is only really a problem when a single agent is logged in - the visitor chat gets stuck in a waiting state, with no agent to roll over to - and no way for the agent to accept the orphaned chat. So we've recommended that three or more people are logged in at all times.
Additionally, we've created a hidden custom console component for the utility bar that will play a continuous alert sound until the chat is accepted, declined, cancelled, or the agent status has changed. This uses static resources with jquery and an mp3 alert sound (currently the standard LiveAgent sound) - but you could rework it to remove dependence on both. I've removed code for another purpose that needs jquery.
I've also left in a few other commented out events that will be useful in non-Omni Channel implementations.
<apex:page standardStylesheets="false" showHeader="false" sidebar="false" applyHtmlTag="true" applyBodyTag="true" docType="html-5.0">
<html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<head>
<title>ChatAlert</title>
<apex:slds />
<apex:includeScript value="/support/console/40.0/integration.js"/>
<apex:includeScript value="{!URLFOR($Resource.jquery, '/jquery/jquery-3.2.1.min.js')}"/>
</head>
<body>
<audio id="alertsound" src="{!URLFOR($Resource.alertsounds, '/alertsounds/request.mp3')}" autostart="false"></audio>
<script type="text/javascript">
var $j = jQuery.noConflict();
var init = function () {
sforce.console.chat.onChatCanceled(function (result) {
console.log('Chat Canceled: ', result);
endAlertRepeat();
});
// sforce.console.chat.onChatRequested(function (result) {
// });
// sforce.console.chat.onChatStarted(function (result) {
// });
// sforce.console.chat.onChatEnded(function (result) {
// });
// sforce.console.chat.onChatDeclined(function (result) {
// });
// sforce.console.chat.onChatTransferredOut(function (result) {
// });
sforce.console.addEventListener(
sforce.console.ConsoleEvent.PRESENCE.WORK_ASSIGNED,
function (result) {
console.log('Work Assigned: ', result);
startAlertRepeat();
});
sforce.console.addEventListener(
sforce.console.ConsoleEvent.PRESENCE.WORK_ACCEPTED,
function (result) {
console.log('Work Accepted: ', result);
endAlertRepeat();
});
sforce.console.addEventListener(
sforce.console.ConsoleEvent.PRESENCE.WORK_DECLINED,
function (result) {
console.log('Work Declined: ', result);
endAlertRepeat();
});
sforce.console.addEventListener(
sforce.console.ConsoleEvent.PRESENCE.STATUS_CHANGED,
function (result) {
console.log('Presence Status changed: ', result);
endAlertRepeat();
});
sforce.console.addEventListener(
sforce.console.ConsoleEvent.PRESENCE.LOGOUT,
function () {
console.log('Logged Out');
endAlertRepeat();
});
// sforce.console.addEventListener(
// sforce.console.ConsoleEvent.PRESENCE.WORK_CLOSED,
// function (result) {
// });
// sforce.console.addEventListener(
// sforce.console.ConsoleEvent.PRESENCE.WORKLOAD_CHANGED,
// function (result) {
// });
},
alertTimerId = null,
delayTimerId = null,
alertCounter = 0,
playAlertSound = function() {
var sound = document.getElementById("alertsound");
sound.play();
},
startAlertRepeat = function() {
if(delayTimerId === null && alertTimerId === null) {
delayTimerId = window.setTimeout(delayedAlertRepeat, 5500);
}
},
delayedAlertRepeat = function() {
alertCounter += 1;
if(alertTimerId === null) {
alertTimerId = window.setInterval(playAlertSound, 5000);
delayTimerId = null;
}
},
endAlertRepeat = function() {
alertCounter = (alertCounter > 0)? alertCounter - 1 : 0;
if(alertTimerId !== null && alertCounter <= 0) {
window.clearInterval(alertTimerId);
alertTimerId = null;
}
if(delayTimerId !== null) {
window.clearTimeout(delayTimerId);
delayTimerId = null;
}
};
$j(document).ready(function() {
init();
});
</script>
</body>
</html>
</apex:page>
Hope this helps! We've dropped our missed chats to less than a tenth of what they were on roll out.