ECE chatStatus V2 - Legacy Version
Legacy Versions
Note - this is also a legacy version - but is ideal for demos - as can be placed directly on the ECE Web server without any additional 3rd party software or configuration.
Latest Versions
Summary
Version 2.0
The chatStatus API can be directly placed onto the ECE Web Server, e.g. D:\ECE\eService\templates\chat\businessHours\chatStatus.asp
- The ECE Web server must have https access to the CCE Admin server - so it can access the Business Hours API
- The client browser does not access CCE server directly - only allow access to the CCE API from the DMZ ECE Web server and NOT from the internet
- Code is provided with an MIT license, free of charge to use, copy, modify etc. and without any warranty of any kind.
- The chatStatus returns the current status of the Chat line based on real time data from a specific Business Hours ID (CCE API) and two ECE chat APIs.
- The response is in JSON or JSONP format (JSONP will be returned if the callback variable is set, but this functionality can be disabled).
- If using JSONP format (supported), you do not need CORS to be configured.
Next steps - would be to make this API cacheable - so the backends APIs are already requested every 10 seconds no matter how many clients where using the API. I will be using memcached (and I might also try redis) for this caching capability
Features
- Business Hours - open / close your Web Chat via CCE Business Hours GUI
- Web Chat can dynamically go 'busy' based on real time values retrieved via the ECE APIs and compared with min / max variables configured - these desired max/min values are set via Business Hours Name - in CCE.
- Min Agent Availability
- Max Queue Depth
- Max Wait Time
- Simple Proactive Chat - enable / disable & configurable timer
Business Hour Reasons can also be used to auto change the message for different closed reasons.
The chatStatus API returns 3 core variables which can be used on your webpage to change the status of your chat.
- chatStatus - this variable is set to open, closed or busy based on real time data from the relevant APIs.
- chatStatusReason (the value of the reason is retrieved via CCE BusinessHours API (or set to “out of service” - if unable to do so)
- ChatTimer (the time in ms to wait before showing the proactive chat)
Example JSON output
{ "debugLevel":"1", "errorcode":"0", "errorstring":"", "chatStatus":"busy", "chatStatusReason":"myMinAgentCount", "chatTimer":"0" }
Steps to enable Demo Web site to work with your ECE Web server
- Download demo website code - https://github.com/gerardorourke/startbootstrap-landing-page/
- Edit the index.html and jsonp-example.html files by doing a find and replace of “ucce-ece-db-12.lab2.purplepi.ie” with your ECE FQDN address
- Download chatStatus.asp
- Host on your ECE Web server: D:\ECE\eService\templates\chat\businessHours\chatStatus.asp
- Note - if your locate the file in a different folder on the ECE Webserver - update the relevant chatStatus.asp URLs in the index.html / ece-undocked.html files
- Update the following variables in the chatStatus.asp file with your relevant details (see chatStatus.asp for more info)
- ccehostname
- ecehostname
- cceuser
- ccepass
- Configuring CORS on the IIS webserver. i.e. add the domain name where the chat website is hosted.
Sample Chat Demo Located here: http://purplepi.ie/web/doku.php?id=chat
chatStatus.asp
Place this file on your ECE Web server - so it is accessible from the client Web Browser.
Example location: D:\ECE\eService\templates\chat\businessHours\chatStatus.asp
Example Web URL: http://my-ece-webserver.example.com/system/templates/chat/businessHours/chatStatus.asp?businessHoursId=5001&chatEntryId=1001
- chatStatus.asp
<%@language = JScript %> <% /* Author: Gerry O'Rourke - Purplepi.ie Date: 22 September 2019 Version 2.0 /* /* MIT License Copyright (c) 2019 Gerard O'Rourke - purplepi.ie Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Example Location of File on ECE Web Server: D:\ECE\eService\templates\chat\businessHours\ Example JSON format URL: http://ucce-ece-db-12.lab2.purplepi.ie/system/templates/chat/businessHours/chatStatus.asp?businessHoursId=5001&chatEntryId=1001 Example JSONP format URL: http://ucce-ece-db-12.lab2.purplepi.ie/system/templates/chat/businessHours/chatStatus.asp?businessHoursId=5001&chatEntryId=1001&callback=parseResponse */ /* --- Overview --- The relevant businessHourId and chatEntryId (case sensative) must be passed into this script otherwise a chatStatus of 'closed' and chatStatusReason of 'out of service' will be returned. The response is in JSON format, unless a query variable 'callback' is set in the URL. If the variable callback is set, the response will use in JSONP with the function name set to value of the callback variable. This key variables chatStatus API that are returned via JSON format are:. chatStatus chatStatusReason myProactiveChatTimer --- chatStatus --- This Variable chatStatus should return one of 3 possible values 'open' 'closed' 'busy' --- chatStatusReason --- This Variable should return the reasonText from the BusinessHours API. In the Web Demo, the reasonText of "Emergency" and "Holiday" are used and were created in CCE admin Business Hours section. This enabled a differnet closed message if the day was a holiday or was forced closed and Reason set to 'Emergency' --- myProactiveChatTimer --- This is the timer for a Proactive Chat in Milliseconds. The time in SECONDS is set as part of the Business Hour Name e.g. a Business Hours Name of "Sales.Chat_A_B_C_D" where A = proactive timer set in seconds, e.g. for 10 seconds before a proactive chat is given set to '10' - Note setting to '0' disabled proactive chat) B = Minimum Number of Chat Agents required - before giving back chatStatus of 'busy' - e.g. set to '0' to allow queuing, set to '1' to require at least 1 agent available before giving busy. C = Max Queue Depth - e.g. set to 5 to give back a busy if there are 5 or more chats in the current chat queue D = Max Expected Wait Time in seconds, e.g. set to '120' to give back a busy if the expected wait time is more than 120 seconds. Example Business Hours Name: "Sales.Chat_10_0_5_120" Example JSON Output: { "debugLevel":"1", "errorcode":"0", "errorstring":"", "chatStatus":"busy", "chatStatusReason":"myMinAgentCount", "chatTimer":"0" } For more info check out: http://orourke.tv/web/doku.php?id=vendors:cisco:uc:ece:apiexample For chat Demo Check out: http://purplepi.ie/web/doku.php?id=chat For Sample HTML + JavaScript Code using this chatStatus API to create a dyanmically updating webpage: https://github.com/gerardorourke/startbootstrap-landing-page */ try { //start of Global Try // ******************************************************************************************** // // *************************** Review and change the BELOW variables ************************* // // ******************************************************************************************** // // Variables CCE & ECE Server Details var ccehostname = 'ucce-hds-a.lab2.purplepi.ie'; var ecehostname = 'ucce-ece-db-12.lab2.purplepi.ie'; var cceuser = '[email protected]'; //create a PCCE User Administrator dedicated for this role. var ccepass = 'myPa$$w0rd!'; // HTTPS Connection Timemout and TLS setttings var SXH_OPTION_2_VALUE = 13056; // SXH_OPTION_IGNORE_SERVER_SSL_CERT_ERROR_FLAGS -> 'SXH_OPTION_2_VALUE = 13056;' to ignore all SSL errors var resolveTimeout = 3000; // DNS Resolve Timeout (ms) var connectTimeout = 3000; // Value (ms) is applied to establishing a communication socket with the target server var sendTimeout = 3000; // The value applies to sending an individual packet of request data (if any) on the communication socket to the target server. (ms) var receiveTimeout = 3000; // The value applies to receiving a packet of response data from the target server (ms) // Default Values if unable to read valid values from BusinessHours Name var defaultProactiveChatTimer = '0'; // value here in seconds, e.g. '10' for a 10 second delay for Proactive Chat (note this value is converted to ms when presented to Client Browser) var defaultMinAgentCount = '0'; var defaultMaxQueueDepth = '0'; var defaultMaxWaitTime = '900'; var debuglevel = 1; // 0 = disabled, 1 = minimum (use on client to output JSON to Console, 2 = basic debugging, 3 = all. Set to 0 in production unless you have an issue to troubleshoot the script. var JSONP_allow = true; // ******************************************************************************************** // // **************************** Review and change the ABOVE variables ************************ // // ******************************************************************************************** // // Initial JS variable values var chatStatus = 'closed'; //Defaults value until overwritten var chatStatusReason = 'out of service'; //Defaults value until overwritten var errorcode = '0'; var errorstring = ''; // Query String - Retrieve dyanmic values for the Business Hours and ECE API IDs. var myQuerySring = Request.QueryString; var myChatEntryId = Request.QueryString("chatEntryId"); var myBusinessHoursId = Request.QueryString("businessHoursId"); var myCallback = Request.QueryString("callback"); var responseFormat = 'json'; var outputfilestarted = false; // CCE & ECE URLs var businessHoursUrl = 'https://' + ccehostname + '/unifiedconfig/config/businesshour/' + myBusinessHoursId; var liveSessionStatusUrl = 'http://' + ecehostname + '/system/egain/chat/entrypoint/liveSessionStatus/' + myChatEntryId; var capacityUrl = 'http://' + ecehostname + '/system/egain/chat/entrypoint/capacity/' + myChatEntryId; // Declare Global Variables used in both businessHours and ECE APIs var myProactiveChatTimer = '0'; //Defaults value until overwritten var myMaxQueueDepth var myMaxWaitTime var myMinAgentCount if (isNaN(myChatEntryId)) { errorcode = '501'; errorstring = 'ChatEntryId not a number,'; } if (isNaN(myBusinessHoursId)) { errorcode = '501'; errorstring = errorstring + 'businessHoursId not a number,'; } if ((Request.QueryString("callback").count > 0) && (JSONP_allow == true)) { if (/\s/.test(myCallback)) { errorcode = '501'; errorstring = 'callback variable contains spaces'; } else{ responseFormat = 'jsonp'; } } // ***** Start of Output File ***** if (responseFormat == 'jsonp') { Response.ContentType = "application/javascript"; // Set Content Type to JavaScript Response.Write(myCallback + '('); } else { Response.ContentType = "application/json"; // Set Content Type to JSON } Response.Write('{'); // Start of JSON Output File outputfilestarted = true; if (errorcode == '0') { chatStatus = businessHoursAPI() // BusinessHours API - returns 'open' or 'closed' } if ((chatStatus == 'open') && (errorcode == '0')) { chatStatus = liveSessionStatusAPI() // ECE liveSessionStatus API - returns 'open' or 'busy' or if unable to read - 'closed' with chatStatusReason 'out of service' } if ((chatStatus == 'open') && (myMinAgentCount > 0) && (errorcode == '0')) { chatStatus = capacityAPI() // ECE Capacity API - returns 'open' or 'busy' or if unable to read - 'closed' with chatStatusReason 'out of service' } if (debuglevel > 1) { Response.Write('\n"QueryString":"' + Request.QueryString + '",'); } Response.Write('\n"debugLevel":"' + debuglevel + '",'); Response.Write('\n"errorcode":"' + errorcode + '",'); Response.Write('\n"errorstring":"' + errorstring + '",'); Response.Write('\n"chatStatus":"' + chatStatus + '",'); Response.Write('\n"chatStatusReason":"' + chatStatusReason + '",'); Response.Write('\n"chatTimer":"' + myProactiveChatTimer + '"'); Response.Write('\n}'); if (responseFormat == 'jsonp') { Response.Write(');'); } // ******************************************************************************************** // // ******************************** Functions ************************************************* // // ******************************************************************************************** // function businessHoursAPI() { try { var srvXmlHttp srvXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0"); srvXmlHttp.setOption(2, SXH_OPTION_2_VALUE); //Ignore SSL Certs srvXmlHttp.setTimeouts(resolveTimeout, connectTimeout, sendTimeout, receiveTimeout); srvXmlHttp.open("GET", businessHoursUrl, false, cceuser, ccepass); srvXmlHttp.send(); var httpstatus = srvXmlHttp.status; if (debuglevel > 1) { Response.Write('\n"businessHoursApiHttpStatus":"' + httpstatus + '",'); } if (httpstatus != 200) { chatStatus = 'closed'; chatStatusReason = 'out of service'; myProactiveChatTimer = '0'; errorcode = httpstatus; errorstring = 'businessHour API http error'; return chatStatus; } var businessHours = srvXmlHttp.responseXML; var businessHoursName = businessHours.selectSingleNode("//businessHour/name"); var runTimeStatus = businessHours.selectSingleNode("//businessHour/runTimeStatus"); var runTimeStatusReason = businessHours.selectSingleNode("//businessHour/runTimeStatusReason"); chatStatusReason = runTimeStatusReason.text; //Parse Business Hours Name to retrieve the Proactive Chat Timer, Min Agent Count, Max Queue Depth & Max Wait Timeouts var businessHoursNameArray = businessHoursName.text.split("_"); var myBusinessHoursName = businessHoursNameArray[0]; myProactiveChatTimer = businessHoursNameArray[1]; myMinAgentCount = businessHoursNameArray[2]; myMaxQueueDepth = businessHoursNameArray[3]; myMaxWaitTime = businessHoursNameArray[4]; myProactiveChatTimer = myProactiveChatTimer * 1000; //Converts ChatTimer from seconds to milliseconds // Check if Valid Values from BusinessHour - if not - overwrite with the default values. if (isNaN(myProactiveChatTimer)) { myProactiveChatTimer = defaultProactiveChatTimer * 1000; //note - converts to milliseconds } if (isNaN(myMinAgentCount)) { myMinAgentCount = defaultMinAgentCount; } if (isNaN(myMaxQueueDepth)) { myMaxQueueDepth = defaultMaxQueueDepth; } if (isNaN(myMaxWaitTime)) { myMaxWaitTime = defaultMaxWaitTime; } if (runTimeStatus.text == 1 || runTimeStatus.text == 3) { chatStatus = 'open'; } else { chatStatus = 'closed'; // Not actually needed as already set to 'closed' as the initial value but ... myProactiveChatTimer = '0'; } if (debuglevel > 2) { Response.Write('\n"fullBusinessHoursName":"' + businessHoursName.text + '",'); Response.Write('\n"runTimeStatusReason":"' + runTimeStatusReason.text + '",'); Response.Write('\n"myBusinessHoursName":"' + myBusinessHoursName + '",'); Response.Write('\n"myProactiveChatTimer":"' + myProactiveChatTimer + '",'); Response.Write('\n"myMinAgentCount":"' + myMinAgentCount + '",'); Response.Write('\n"myMaxQueueDepth":"' + myMaxQueueDepth + '",'); Response.Write('\n"myMaxWaitTime":"' + myMaxWaitTime + '",'); Response.Write('\n"runTimeStatus":"' + runTimeStatus.text + '",'); } return chatStatus; } //Try catch (err) { chatStatus = 'closed'; chatStatusReason = 'out of service'; myProactiveChatTimer = '0'; errorcode = '500'; errorstring = 'businessHours API Error'; return chatStatus; } //end of catch } //end of function function liveSessionStatusAPI() { try { var srvXmlHttp srvXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0"); srvXmlHttp.setOption(2, SXH_OPTION_2_VALUE); //Ignore SSL Certs srvXmlHttp.open("GET", liveSessionStatusUrl, false); srvXmlHttp.send(); var httpstatus = srvXmlHttp.status; if (debuglevel > 1) { Response.Write('\n"liveSessionApiHttpStatus":"' + httpstatus + '",'); } if (httpstatus != 200) { chatStatus = 'closed'; chatStatusReason = 'out of service'; myProactiveChatTimer = '0'; errorcode = httpstatus; errorstring = 'liveSession API http error'; return chatStatus; } var liveSessionStatus = srvXmlHttp.responseXML; var waitTime = liveSessionStatus.selectSingleNode("//ns2:waitTime"); var queueDepth = liveSessionStatus.selectSingleNode("//ns2:queueDepth"); if (parseInt(queueDepth.text, 10) > myMaxQueueDepth) { chatStatus = 'busy'; chatStatusReason = 'MaxQueueDepth'; myProactiveChatTimer = '0'; } if (parseInt(waitTime.text, 10) > myMaxWaitTime) { chatStatus = 'busy'; chatStatusReason = 'MaxWaitTime'; myProactiveChatTimer = '0'; } if (debuglevel > 2) { Response.Write('\n"waitTime":"' + waitTime.text + '",'); Response.Write('\n"queueDepth":"' + queueDepth.text + '",'); } return chatStatus; } //end of try catch (err) { chatStatus = 'closed'; chatStatusReason = 'out of service'; myProactiveChatTimer = '0'; errorcode = '500'; errorstring = 'liveSession API Error'; return chatStatus; } //end of catch } //end of function function capacityAPI() { try { srvXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0"); srvXmlHttp.setOption(2, SXH_OPTION_2_VALUE); //Ignore SSL Certs srvXmlHttp.open("GET", capacityUrl, false); srvXmlHttp.send(); var httpstatus = srvXmlHttp.status; if (debuglevel > 1) { Response.Write('\n"capacityApiHttpStatus":"' + httpstatus + '",'); } if (httpstatus != 200) { chatStatus = 'closed'; chatStatusReason = 'out of service'; myProactiveChatTimer = '0'; errorcode = httpstatus; errorstring = 'capacity API http error'; return chatStatus; } var capacity = srvXmlHttp.responseXML; var count = capacity.selectSingleNode("//ns2:count"); if (parseInt(count.text, 10) < myMinAgentCount) { chatStatus = 'busy'; chatStatusReason = 'myMinAgentCount'; myProactiveChatTimer = '0'; } if (debuglevel > 2) { Response.Write('\n"agentCount":"' + count.text + '",'); } return chatStatus; } // Try catch (err) { chatStatus = 'closed'; chatStatusReason = 'out of service'; chatTimer = '0'; errorcode = '500'; errorstring = 'capacity API Error'; return chatStatus; } //Catch } //Function } //End of Global Try catch (err) { chatStatus = 'closed'; chatStatusReason = 'out of service'; chatTimer = '0'; errorcode = '500'; errorstring = 'Script Error'; if ((outputfilestarted == false) || (typeof outputfilestarted == 'undefined')){ if (responseFormat == 'jsonp') { Response.ContentType = "application/javascript"; // Set Content Type to JavaScript Response.Write(myCallback + '('); } else { Response.ContentType = "application/json"; // Set Content Type to JSON } Response.Write('{'); // Start of JSON Output File } Response.Write('\n"chatStatus":"' + chatStatus + '",'); Response.Write('\n"chatStatusReason":"' + chatStatusReason + '",'); Response.Write('\n"chatTimer":"' + chatTimer + '",'); Response.Write('\n"errorcode":"' + errorcode + '",'); Response.Write('\n"errorstring":"' + errorstring + '"'); Response.Write('\n}'); } %>
Example JavaScript using the chatStatus API on a webpage
Example code you would add to the bottom of your HTML page to call the chatStatus API
Update the relevant host names of your ECE Web server switch and your businessHour and ECE chat Entry IDs.
Note: along with this code - the standard ECE code snippets also need to be added (Check out the sample website code on Github)
<!-- JavaScript to Show or Hide the open / closed / busy Chat options based on 'chatStatus' and 'chatStatusReason' values from chatStatus custom API--> <script type="text/javascript"> // Initiate Variables var chatStatus = 'closed'; var chatStatusReason = 'out of service'; var chatTimer = '0'; var chatProactiveAttempts = '0' //Initialise to zero var chatStatusRefreshTimer = '10000'; // refresh timer set 10 seconds for testing - in production set to '60000' var chatProactiveRetryAttempts = '1'; var chatStatusUrl = "http://ucce-ece-db-12.lab2.purplepi.ie/system/templates/chat/businessHours/chatStatus.asp"; var mybusinessHourId = '5001'; var mychatEntryId = '1001'; getChatStatus(); //on load of page run the (Ajax) Script function getChatStatus() { //Note - the JSON Response gets auto parsed by jQuery. $.ajax({ url: chatStatusUrl, data: {businessHoursId: mybusinessHourId, chatEntryId: mychatEntryId}, dataType: 'json', success: function(chatStatusAPI) { chatStatus = chatStatusAPI.chatStatus; chatStatusReason = chatStatusAPI.chatStatusReason; chatTimer = chatStatusAPI.chatTimer; if (chatStatusAPI.debugLevel > 0) { console.log("------ ChatStatus API Success Response ------"); console.log(chatStatusAPI); console.log("---------------------------------------------"); } setChatStatus(); //on success call this function to update the page } }) .fail(function() { chatStatus = 'closed'; chatStatusReason = 'out of service'; chatTimer = '0'; console.log("------ chatStatus: Ajax Call failed ------"); setChatStatus(); //on fail call this function to update the page }) }; function setChatStatus() { if (chatStatus == 'closed') { $('#mychatOff').show(); $('#mychatOn').hide(); $('#mychatBusy').hide(); $('#mychatPageLoad').hide(); if (chatStatusReason == 'Holiday') { //Case sensensitve = match exactly! $('#mychatclosed-holidaymessage').show(); $('#mychatclosed-standardmessage').hide(); $('#mychatclosed-emergencymessage').hide(); $('#mychatclosed-outofservicemessage').hide(); } if (chatStatusReason == 'Emergency') { //Case sensensitve = match exactly! $('#mychatclosed-emergencymessage').show(); $('#mychatclosed-holidaymessage').hide(); $('#mychatclosed-standardmessage').hide(); $('#mychatclosed-outofservicemessage').hide(); } if (chatStatusReason == 'out of service') { //Case sensensitve = match exactly! $('#mychatclosed-outofservicemessage').show(); $('#mychatclosed-holidaymessage').hide(); $('#mychatclosed-standardmessage').hide(); $('#mychatclosed-emergencymessage').hide(); } } if (chatStatus == 'busy') { $('#mychatBusy').show(); $('#mychatOff').hide(); $('#mychatOn').hide(); $('#mychatPageLoad').hide(); } if (chatStatus == 'open') { $('#mychatOn').show(); $('#mychatOff').hide(); $('#mychatBusy').hide(); $('#mychatPageLoad').hide(); //Proactive Chat if (chatProactiveRetryAttempts > chatProactiveAttempts){ setTimeout(function() { if ((chatTimer != 0) && (chatStatus == 'open') && (chatProactiveRetryAttempts > chatProactiveAttempts)) { //Since open state can change by the timer occurs - need to check again before showing chatProactiveAttempts++ $('#chatModal').modal(); } }, chatTimer); } } if (chatStatusReason != 'out of service'){ setTimeout(getChatStatus, chatStatusRefreshTimer); //call the getChatStatus function again in X seconds as long as chatStatusReason is NOT 'out of service' } } function disableProactiveChat() { window.chatTimer = 0; console.log('chatStatus chatTimer: 0'); } </script>
JSONP JavaScript Extract
The JSONP version of the JavaScript code is very similar to above JSON version, except ajax is configured with dataType jsonp format and the callback variable “ChatStatusParse” is set (you can set whatever funtion name you want). The ChatStatusParse function is then called on success. This chatStatusParse function is also included below. Check out jsonp-example.html on the github page for a full working example.
The advantage of JSONP is that CORS is not a requirement due to how browsers handle JSONP. Check out this wiki link for more info.
function getChatStatus() { //Note - the JSON Response gets auto parsed by jQuery. $.ajax({ url: chatStatusUrl, data: {businessHoursId: mybusinessHourId, chatEntryId: mychatEntryId}, dataType: 'jsonp', jsonp: 'callback', jsonpCallback: 'chatStatusParse', success: function(data) { //console.log(data); //formatted JSON data } }) .fail(function() { chatStatus = 'closed'; chatStatusReason = 'out of service'; chatTimer = '0'; console.log("chatStatus: Ajax Call failed"); setChatStatus(); //on fail call this function to update the page }) }; function chatStatusParse(chatStatusAPI){ chatStatus = chatStatusAPI.chatStatus; chatStatusReason = chatStatusAPI.chatStatusReason; chatTimer = chatStatusAPI.chatTimer; if (chatStatusAPI.debugLevel > 0) { console.log("------ ChatStatus API Response ------"); console.log(chatStatusAPI); console.log("-------------------------------------"); } setChatStatus(); //on success call this function to update the page }
HTML for Proactive Chat
Note - uses Bootstrap CSS Modal for Popup - Reference
<!-- Modal --> <div class="modal fade" id="chatModal" tabindex="-1" role="dialog" aria-labelledby="chatModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="chatModalLabel">Proactive Chat Demo</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <p>Hello, one of our assistents is available to assist you now. <p>Do you want to chat? </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary" onclick="$('#chatModal').modal('hide');egainChat.openHelp();">Chat Now!</button> </div> </div> </div> </div>
ECE & CCE APIs used to achieve this functionality
ECE - liveSessionStatus - Display chat option based on queue depth and wait time
http://ucce-ece-db-12.lab2.purplepi.ie/system/egain/chat/entrypoint/liveSessionStatus/1001
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <sessionStatus xmlns:ns5="http://jabber.org/protocol/httpbind" xmlns:ns2="http://bindings.egain.com/chat" xmlns:ns4="jabber:client" xmlns:ns3="urn:ietf:params:xml:ns:xmpp-stanzas"> <ns2:waitTime>60.0</ns2:waitTime> <ns2:queueDepth>0</ns2:queueDepth> <ns2:altEngmtTime>0</ns2:altEngmtTime> </sessionStatus>
ECE - Agent Capacity
http://ucce-ece-db-12.lab2.purplepi.ie/system/egain/chat/entrypoint/capacity/1001
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <availableSlots xmlns:ns5="http://jabber.org/protocol/httpbind" xmlns:ns2="http://bindings.egain.com/chat" xmlns:ns4="jabber:client" xmlns:ns3="urn:ietf:params:xml:ns:xmpp-stanzas"> <ns2:count>3</ns2:count> </availableSlots>
CCE - Business Hours
https://ucce-hds-a.lab2.purplepi.ie/unifiedconfig/config/businesshour/5001
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <businessHour> <department> <refURL>/unifiedconfig/config/department/5000</refURL> <name>Department1</name> </department> <refURL>/unifiedconfig/config/businesshour/5001</refURL> <changeStamp>86</changeStamp> <configuredStatus> <status>2</status> <statusReason> <refURL>/unifiedconfig/config/businesshourstatusreason/5006</refURL> <reasonText>Open Override</reasonText> </statusReason> </configuredStatus> <description> </description> <name>Sales.Chat_0_1_6_120</name> <runTimeStatus>3</runTimeStatus> <runTimeStatusReason>Open Override</runTimeStatusReason> <specialDaySchedules> <specialDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/specialdayschedule/5000</refURL> <changeStamp>0</changeStamp> <date>18-03-2019</date> <description>St Pat Bank Holiday</description> <status>0</status> <statusReason> <refURL>/unifiedconfig/config/businesshourstatusreason/5001</refURL> <reasonText>Week Day closed reason</reasonText> </statusReason> </specialDaySchedule> </specialDaySchedules> <timezone> <refURL>/unifiedconfig/config/timezone/v2/5038</refURL> <displayName>(UTC+00:00) Dublin, Edinburgh, Lisbon, London</displayName> </timezone> <type>1</type> <weekDaySchedules> <weekDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/weekdayschedule/5011</refURL> <changeStamp>0</changeStamp> <endTime>17:00</endTime> <startTime>09:00</startTime> <dayOfWeek>1</dayOfWeek> </weekDaySchedule> <weekDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/weekdayschedule/5012</refURL> <changeStamp>0</changeStamp> <endTime>17:00</endTime> <startTime>09:00</startTime> <dayOfWeek>2</dayOfWeek> </weekDaySchedule> <weekDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/weekdayschedule/5013</refURL> <changeStamp>0</changeStamp> <endTime>17:00</endTime> <startTime>09:00</startTime> <dayOfWeek>3</dayOfWeek> </weekDaySchedule> <weekDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/weekdayschedule/5014</refURL> <changeStamp>0</changeStamp> <endTime>17:00</endTime> <startTime>09:00</startTime> <dayOfWeek>4</dayOfWeek> </weekDaySchedule> <weekDaySchedule> <refURL>/unifiedconfig/config/businesshour/5001/weekdayschedule/5015</refURL> <changeStamp>0</changeStamp> <endTime>17:00</endTime> <startTime>09:00</startTime> <dayOfWeek>5</dayOfWeek> </weekDaySchedule> </weekDaySchedules> </businessHour>
CORS IIS Config
This IIS URL Rewrite example configuration enables CORS, i.e. Cross-Origin Resource Sharing for the purplepi.ie domain.
This rule matches against the origin header and if it is ends with purplepi.ie, it will reply back with a Access-Control-Allow-Origin set the original original value.
For Example - a http request with the following header:
Origin: http://www.purplepi.ie
Since this matches it will reply back with header set of
Access-Control-Allow-Origin: http://www.purplepi.ie
URL Rewrite sample Config for purplepi.ie domain and any subdomain
Update the C:\inetpub\wwwroot\web.config file or use the URL Rewrite GUI interface on IIS Management so that the server will respond correctly if the origin of the webchat server is from the 'correct' domain.
<system.webServer> <rewrite> <outboundRules> <rule name="AddCrossDomainHeader"> <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="true"> <add input="{HTTP_ORIGIN}" pattern="(http(s)?:\/\/((.+\.)?purplepi\.ie))" /> </conditions> <action type="Rewrite" value="{C:0}" /> </rule> </outboundRules> </rewrite> </system.webServer>
Disabling Chat Banner
Reference UCCE Chat User Admin - Page 111
Locate egainDockChat.UseCustomButton and egainDockChatIsChatLaunched and set the values to true and if you wish to allow the docked chat entry point to be initiated through a custom button or offer banner other than “Docked Chat”.

