If statement to only open AWS soft phone while in Service Operations Workspace

rstoker
Tera Contributor

Hi. I'm the customer and don't have much coding experience. We recently turned on an integration with AWS Connect. It works great, but interferes when viewing anything outside the Service Operations Workspace. The solution we came up with is to add an if-statement to the javascript that controls the soft phone. Unfortunately, everything we have tried has failed.

 

I think we want to put it somewhere in the OpenFrame Initialization portion of the code. Possibly to skip the entire thing, but I think the if-statement we are using is the problem.

 

We've tried:

if (window.location.href.indexOf("service-now.com/now/sow/"){

if(window.location.contains("service-now.com/now/sow/")){

if (window.location.href.indexOf("sow") > -1{

if window.location.toString().includes("sow")

if (window.location.href.indexOf('sow') !== -1) {

 

etc...

 

 

Someone in our organization recently suggested:  "window.location.href is used on the client side of browser where SNOW uses gs.action.getGlideURI() on the server side to obtain the portion of the URL that you are looking for. "

 

Is that heading down the correct path or are we totally going at this the wrong way?

 

1 ACCEPTED SOLUTION

You can try something like this - just replace those log statements with an alert and return.

 

 

function initCallback(snConfig) {
  if (window.parent.location.href.indexOf("/now/sow/") !== -1) {
    alert("{YOUR MESSAGE}");
    return;
  }
  var openFrameConfig = snConfig;
  if (openFrameConfig.configuration)
    showRecordOnIncomingBehavior = JSON.parse(openFrameConfig.configuration);
  //register for communication event from TopFrame
  openFrameAPI.subscribe('openframe_awa_agent_presence', handleOpenFrameAwaEvent);
  //register event for click to call
  openFrameAPI.subscribe('openframe_communication', handleClickToCall);
  //register for work item accepted event
  openFrameAPI.subscribe('openframe_awa_workitem_accepted', handleWorkItemAccepted);
}

 

 

Good luck!

 

View solution in original post

8 REPLIES 8

Sheldon  Swift
ServiceNow Employee
ServiceNow Employee

What file are you modifying?

 

On the client side, you would use something like this:

if (window.location.href.indexOf("/now/sow/") !== -1) {
  // Do something
}

If that's not working, you can double-check the value of window.location.href:

console.log(window.location.href);

I attached the full code. This code opens an AWS Softphone, which then causes a pop-up while in the Service Operations Workspace. Unfortunately it also causes a popup every time a new ServiceNow page loads, but outside of the Workspace these pop-ups just redirect to the Interaction ticket. This means if someone tries to open out knowledgebase it redirects them away from it. We would like the pop-ups (and soft phone in general) to only work while in the Workspace.

rstoker
Tera Contributor

It removed the file I attached. I'll try to post it here

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
 <g:evaluate var="jvar_user_sysid" jelly="true">
var userSysId = gs.getUserID();
userSysId;
 </g:evaluate>
 <g:evaluate var="jvar_ccphost" jelly="true">
var id = RP.getParameterValue('id');
var ccpHost = '';
var gr = new GlideRecord('sn_cti_connect_instance');
if (gr.get(id)) {
var instanceParams = gr.getValue('instance_params');
var instanceARN = gr.getValue('aws_arn');
var providerAppId = gr.provider_application.toString();
try {
instanceParams = JSON.parse(instanceParams);
ccpHost = instanceParams ? instanceParams.ccpHost : null;
} catch(ipe) {
gs.error("Couldn't parse instance params"+ipe.message);
}
if(gs.nil(ccpHost)) {
ccpHost = gr.getValue('name') + ".awsapps.com";
}
}
ccpHost;
 </g:evaluate>
 <g:evaluate var="jvar_instance_arn" jelly="true">
instanceARN;
 </g:evaluate>
 <g:evaluate var="jvar_provider_app_id" jelly="true">
providerAppId;
 </g:evaluate>
 <g:evaluate var="jvar_ccpregion" jelly="true">
var ccpRegion = RP.getParameterValue('region');
if(!ccpRegion) {
ccpRegion = instanceParams ${AND} instanceParams.ccpRegion ? instanceParams.ccpRegion : null;
if(ccpRegion == null)
                ccpRegion = instanceARN ? instanceARN.split(':')[3] : null;
}
ccpRegion;
 </g:evaluate>
 <g:evaluate var="jvar_ccpversion" jelly="true">
var ccpVersion = RP.getParameterValue('version');
if(!ccpVersion) {
ccpVersion = instanceParams ${AND} instanceParams.ccpVersion ? instanceParams.ccpVersion : gs.getProperty('sn_cti_amzn_cct.default_ccp_version_suffix', 'ccp-v2');
}
ccpVersion;
 </g:evaluate>
 <g:evaluate var="jvar_session_token" jelly="true">
var g_ck = gs.getSession().getSessionToken();
g_ck;
 </g:evaluate>
 <g:evaluate var="jvar_cfg" jelly="true">
var ccpHost = jelly.jvar_ccphost;
var ccpRegion = jelly.jvar_ccpregion;
var ccpVersion = jelly.jvar_ccpversion;
var ccpUrl = instanceParams ${AND} instanceParams.ccpUrl ? instanceParams.ccpUrl : null;
var audioRecordingUrlPrefix = instanceParams ${AND} instanceParams.audioRecordingUrlPrefix ? instanceParams.audioRecordingUrlPrefix : null;
 
//Backward support - Instances with previous domain
if(gs.nil(ccpUrl))
ccpUrl = ccpHost ? 'https://' + ccpHost + '/connect/' + ccpVersion + '/' : null;
 
//Backward support - Instances with previous domain
if(gs.nil(audioRecordingUrlPrefix))
audioRecordingUrlPrefix = 'https://' + ccpHost + '/connect/get-recording?format=wav&amp;callLegId=';
 
var cfg = {
ccpHost: ccpHost,
ccpUrl: ccpUrl,
loginPopup: true,
audioRecordingUrlPrefix: audioRecordingUrlPrefix,
softphone: {
allowFramedSoftphone: true
}
};
if(ccpRegion) {
cfg.region = ccpRegion;
}
// If we have a url then create valid config
if(cfg.ccpUrl) {
cfg = JSON.stringify(cfg);
} else {
cfg = null;
}
cfg;
 </g:evaluate>
 <html>
<head>
<!--
This is key if you don't include this then you will get an error from aws saying
Refused to display 'https://nowdemo1.awsapps.com/connect/ccp#/' in a frame because it set 'X-Frame-Options' to 'sameorigin'
Unfortunately you still need to be logged in outside for it to load as if you are not you will get
Refused to display 'https://snclgs.awsapps.com/connect/login?landat=%2Fconnect%2Fccp#/changeStatus' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
-->
<meta name="referrer" content="origin" />
<style>
html {
}
body {
  margin: 0px;
  padding: 0px;
  border: 0px;
  min-width: max-content;
  min-height: max-content;
  width: 99%;
}
#containerDiv {
  margin: 0px;
  padding: 0px;
  border: 0px;
  height: 517px;
}
</style>
</head>
 <body>
<j:choose>
<j:when test="${jvar_cfg != 'null'}">
<textarea id="cfg" rows="20" cols="60" style="display: none">${HTML:jvar_cfg}</textarea>
 
<div id="containerDiv"/>
</j:when>
<j:otherwise>
<div>${gs.getMessage('Invalid Configuration')}</div>
</j:otherwise>
</j:choose>
 </body>
 </html>
 <j:if test="${jvar_cfg != 'null'}">
<script src="/scripts/amazon-connect-streams.min.js?sysparm_substitute=false"/>
<script src="/scripts/openframe/latest/openFrameAPI.min.js"/>
<script type="text/javascript">
// WORKAROUND: Clear out localstorage on start so login popup can occur
window.localStorage.removeItem('connectPopupManager::connect::loginPopup');
 
var cfg = JSON.parse(document.getElementById('cfg').textContent);
try{
connect.core.initCCP(containerDiv, cfg);
}
catch(err){
console.error("Error Initializing CCP: ", err)
}
 
//Subscribing to "EventType.TERMINATED", which is published when agent manually log out of the ccp. 
const eventBus = connect.core.getEventBus();
eventBus.subscribe(connect.EventType.TERMINATED, () => {
sendSoftPhoneAwsAgentMappingEvent("agent_logout");
});
 
/*********************************
* OpenFrame Initialization
*********************************/
var currentEntityRecord = {
entity: null,
sysId: null
};
var callExceptions = {
invalidPhoneNumber: 'BadEndpointException'
}
var currentAgent = null;
var config = {
height: 522,
width: 400
};
var showRecordOnIncomingBehavior = {};
var outboundInteractionId = '';
function handleClickToCall(context) {
var actor = 'agent';
var event = 'calling_customer';
context['inbound_id'] = '${jvar_instance_arn}';
try {
var debug = {
source: 'click_to_call',
actor: actor,
event: event,
payload: context
};
console.log(debug);
// update the interaction with click to call context
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/sn_cti_core/cti_api/softphone/sources/click_to_call/actor/' + actor + '/events/' + event);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader('X-UserToken', '${jvar_session_token}');
xhr.send(JSON.stringify(context));
} catch(se) {
console.error(se);
}
xhr.onreadystatechange = function() {
try {
if(xhr.readyState === XMLHttpRequest.DONE) {
// extract the interactionSysId from the click to call payload
var interacionEntity = context.data.data.filter( data => data.entity === 'interaction' );
// Ignore screen popup if interaction is not created (could happen when sn_openframe.create_interaction property is false)
if(interacionEntity.length > 0) {
var query = interacionEntity[0].query;
// store the outbound interaction ID in the session to update contact Id in the connect callback
outboundInteractionId = query.replace("sys_id=", '');
}
// Make an outbound call via amazon connect
var phoneNumber = context.data.metaData.phoneNumber;
var response = JSON.parse(xhr.response);
var formattedPhoneNumber = response ? response.result.SoftPhoneEventSink4ClickToCall.formattedPhoneNumber : phoneNumber;
var agentUtil = new lily.Agent();
agentUtil.connect(connect.Endpoint.byPhoneNumber(formattedPhoneNumber),{
  failure:function(error){
console.log("click to call error occured : " + error);
var exception = JSON.parse(error);
// Open the interaction in case of an error so that the agent is aware that an interaction was created
openInteraction(outboundInteractionId);
 
// handle invalid phone number scenario
if(exception ${AND} callExceptions.invalidPhoneNumber === exception.type) {
var payload = {};
payload.type = 'error';
payload.exception = exception;
payload.interactionId = outboundInteractionId;
payload.phoneNumber = formattedPhoneNumber;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/sn_cti_core/cti_api/softphone/sources/click_to_call/actor/' + actor + '/events/' + event);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader('X-UserToken', '${jvar_session_token}');
xhr.send(JSON.stringify(payload));
}
  }
});
}
} catch(se) {
console.log(se);
}
}
}
 
function updateInteractionContactId(contact) {
var payload = {};
var contactNode = {};
var interaction = {};
var contactId = contact.getContactId();
 
// Prepare the outbound call attributes
interaction.name = 'interactionId';
interaction.value = outboundInteractionId;
 
contactNode.contactId = contactId;
contactNode.type = contact.getType();
contactNode.direction = 'outbound';
contactNode.attributes = contact.getAttributes();
contactNode.attributes.interactionId = interaction;
payload.contact = contactNode;
 
// Send softphone event sync to update the contact Id
sendSoftPhoneEvent('contact', 'click_to_call', payload);
 
// Reset the outbound interaction Id
    outboundInteractionId = '';
return payload;
}
 
function openInteraction(interactionSysId) {
// Setup record so we can popup the interaction record
currentEntityRecord.entity = 'interaction';
currentEntityRecord.query = 'sys_id='+interactionSysId;
openFrameAPI.openServiceNowForm(currentEntityRecord);
}
 
function handleOpenFrameAwaEvent(context) {
if(currentAgent) {
if(context) {
var result = context.result;
if(result) {
var presence = result.presence;
if(presence) {
var presenceName = presence.name;
var agentState = currentAgent.getState().name;
if(agentState != presenceName) {
var states = currentAgent.getAgentStates();
var stateToSet = null;
for(var sti in states) {
var stateToCheck = states[sti];
if(stateToCheck.name == presenceName) {
console.info('handleOpenFrameAwaEvent: Setting agent state', stateToCheck);
currentAgent.setState(stateToCheck);
return;
}
}
console.warn('handleOpenFrameAwaEvent: Unable to find matching aws connect state for: ' + presenceName);
} else {
console.info('handleOpenFrameAwaEvent: No state change needed');
}
}
}
}
}
}
 
// XMLHttpRequest wrapper using callbacks
let request = obj => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open((obj.method || "GET"), obj.url);
if (obj.headers) {
Object.keys(obj.headers).forEach(key => {
xhr.setRequestHeader(key, obj.headers[key]);
});
}
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(xhr.statusText);
}
};
xhr.onerror = () => reject(xhr.statusText);
xhr.send(obj.body);
});
};
 
function handleWorkItemAccepted(payload) {
var document_sys_id, table;
var region = '${jvar_ccpregion}';
if (payload ${AND} payload.result ${AND} payload.result.workItem){
table = payload.result.workItem.document.table;
document_sys_id = payload.result.workItem.document.sys_id;
}
// Process work item only for interactions
if (table === 'interaction' ${AND} document_sys_id){
// Get interaction details from work item document sys_id
var tableUrl = '/api/now/table/interaction?sysparm_fields=sys_id&amp;sysparm_query=sys_id%3D'+ document_sys_id +'%5Eccc_source%3Damazon_connect%5Etype%3Dphone';
request({url: tableUrl, headers: {'X-UserToken': '${jvar_session_token}'}})
.then(data => {
var interaction = JSON.parse(data).result[0];
if (interaction.sys_id !== null){
var agentUserName = currentAgent.getConfiguration().username;
// Call extension point to update DynamoDB table with agentName who accepted the work item request
var actor = 'caller';
var event = 'work_item_accepted';
var payload = {region, interactionId: document_sys_id, agentUserName};
var debug = {
source: 'handleWorkItemAccepted',
actor: actor,
event: event,
payload: payload
};
console.log(debug);
var updateAgentUrl = '/api/sn_cti_core/cti_api/softphone/sources/aws_ccp/actor/'+actor+'/events/'+event;
var headers = {'X-UserToken': '${jvar_session_token}', 'Content-Type': 'application/json', 'Accept': 'application/json'};
request({method: 'POST', url: updateAgentUrl, headers:headers, body: JSON.stringify(payload)})
.then(data => {console.log("Update agentName response: ", data);})
.catch(error => {console.error("Error updating agentName: ", error);})
} else console.error("Cannot handle work item: interaction with type=phone and ccc_source=amazon_connect not found");
})
.catch(error => {
console.error("Error fetching interaction details: ", error);
});
}
}
 
function initCallback(snConfig) {
console.log("openframe configuration",snConfig);
var openFrameConfig = snConfig;
if(openFrameConfig.configuration)
showRecordOnIncomingBehavior = JSON.parse(openFrameConfig.configuration);
//register for communication event from TopFrame
openFrameAPI.subscribe('openframe_awa_agent_presence', handleOpenFrameAwaEvent);
//register event for click to call
openFrameAPI.subscribe('openframe_communication', handleClickToCall);
//register for work item accepted event
openFrameAPI.subscribe('openframe_awa_workitem_accepted', handleWorkItemAccepted);
}
 
openFrameAPI.init(config, initCallback, initCallback);
 
/*********************************
* AWS Connect Streams API Configuration
*********************************/
connect.contact(function(contact) {
// Open the openFrame popup
openFrameAPI.setFrameMode("expand");
openFrameAPI.show();
var outboundInteractionIdForPreview = '';
 
// Update the outgoing interaction with the AWS contact ID
// This is called once when a new contact is created in AWS Connect. It is not called again for the lifecycle of a call.
    // We want to do this before any event is triggered as the very first thing in the connect.contact callback so that the link between interaction and contact ID is persisted
// even if the customer never picks the call or the call drops for other reasons
// Ignore the update logic if no interaction is created(could happen if sn_openframe.create_interaction property is false
if(outboundInteractionId.length > 0  ${AND} !contact.isInbound()) {
var outboundAttributes = updateInteractionContactId(contact);
outboundInteractionIdForPreview = outboundAttributes.contact.attributes.interactionId.value;
} else if (!outboundInteractionId ${AND} contact ${AND} !contact.isInbound()) {
if(document.hasFocus() === true)
sendOutgoingCallToContactSoftPhoneEvent(contact);
}
 
// Pop the interaction if it is an outbound call or if the showRecord behavior is onIncoming
if(!contact.isInbound() || 'onIncoming' === showRecordOnIncomingBehavior.showRecord) {
var attributes = contact.getAttributes();
// Check if we have an interaction id since it may not have been set
if((attributes ${AND} attributes.interactionId ${AND} attributes.interactionId.value) || outboundInteractionIdForPreview) {
var interactionsysId = attributes.interactionId ? attributes.interactionId.value : outboundInteractionIdForPreview;
if(interactionsysId) {
// Screen pop the related tasks of the interaction
openInteraction(interactionsysId);
}
}
}
for(var methodKey in contact) {
if(methodKey.startsWith('on')) {
console.log('Adding Listener: contact.' + methodKey);
var toCall = function(contact) {
sendSoftPhoneContactEvent(contact);
};
contact[methodKey](toCall);
}
}
});
connect.agent(function(agent) {
currentAgent = agent;
for(var methodKey in agent) {
if(methodKey.startsWith('on')) {
console.log('Adding Listener: agent.' + methodKey);
var toCall = function(contact) {
sendSoftPhoneAgentEvent(agent);
};
agent[methodKey](toCall);
}
}
sendSoftPhoneAwsAgentMappingEvent("agent_login");
});
/*********************************
* AWS to CTI Softphone Event bindings
*********************************/
var sendSoftPhoneEvent = function(actor, event, payload) {
try {
var actualPayload = payload ? payload : {};
actualPayload['window'] = {
location: {
href: window.location.href,
search: window.location.search
}
};
actualPayload['aws'] = {
connect: {
config: cfg
}
};
var debug = {
source: 'sendSoftPhoneEvent',
actor: actor,
event: event,
payload: actualPayload
};
console.log(debug);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/sn_cti_core/cti_api/softphone/sources/aws_ccp/actor/' + actor + '/events/' + event);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader('X-UserToken', '${jvar_session_token}');
xhr.send(JSON.stringify(actualPayload));
} catch(se) {
console.error(se);
}
};
var currentAgentState = '';
var setOpenFrameAgentPresence = function(agent) {
var status = agent.getStatus();
var presence = {
displayName: status.name,
color: 'grey',
sysId: '9cd83267575313005baaaa65ef94f98b',
available: false
};
// See: connect.AgentStateType and connect.AgentAvailStates
if('routable' === status.type) {
presence.available = true;
presence.color = 'green';
presence.sysId = '0b10223c57a313005baaaa65ef94f970';
} else if('offline' === status.type) {
presence.available = false;
presence.color = 'red';
presence.sysId = '9cd83267575313005baaaa65ef94f98b';
} else if('not_routable' === status.type) {
presence.available = false;
presence.color = 'grey';
presence.sysId = '41f9b8dfb31313005baa6e5f26a8dcac';
}
var debug = {
source: 'openFrameAPI',
event: status.name,
status: status,
presence: presence
};
console.log(debug);
// The API below doesn't do anything useful with the backend it just sets the icon
// We are required to make sure the backend is in sync
openFrameAPI.setPresenceIndicator(presence.displayName, presence.color);
};
var sendSoftPhoneAgentEvent = function(agent) {
try {
if(agent) {
var status = agent.getStatus();
if(status) {
// Use status.name NOT status.type and ignore event since it is mapped to the event handler on the agent which is the status.type
var event = status.name;
var agentSysId = '${jvar_user_sysid}';
var payload = {
agent: {
sys_id:  agentSysId,
status: status
}
};
// Avoid spamming endpoint with useless events
if(currentAgentState !== event) {
currentAgentState = event;
sendSoftPhoneEvent('agent', event, payload);
setOpenFrameAgentPresence(agent);
}
}
}
} catch(ae) {
console.error(ae);
}
};
var sendSoftPhoneAwsAgentMappingEvent = function(event) {
var agentSysId = '${jvar_user_sysid}';
var providerAppId = '${jvar_provider_app_id}';
if(currentAgent){
var agentConfig = currentAgent.getConfiguration();
if(agentConfig){
var awsAgentUserName = agentConfig.username;
var actor = 'agent';
var payload = {agentSysId, awsAgentUserName, providerAppId};
var debug = {
source: 'aws_ccp',
actor: actor,
event: event,
payload: payload
};
console.log(debug);
 
var eventSyncUrl = '/api/sn_cti_core/cti_api/softphone/sources/aws_ccp/actor/'+actor+'/events/'+event;
var headers = {'Accept': 'application/json', 'Content-Type': 'application/json', 'X-UserToken': '${jvar_session_token}'};
request({method: 'POST', url: eventSyncUrl, headers:headers, body: JSON.stringify(payload)})
.catch(error => { console.error("Exception:sendSoftPhoneAwsAgentMappingEvent: " + error); })
}
};
 
var currentContactState = '';
var sendSoftPhoneContactEvent = function(contact) {
try {
if(contact) {
var status = contact.getStatus();
if(status) {
// Use status.type
var event = status.type;
// Avoid spamming endpoint with useless events since we only care about state changes
if(currentContactState !== event) {
currentContactState = event;
var attributes = contact.getAttributes();
// Check if we have an interaction id since may not have been set
if(attributes.interactionId) {
if('connected' === event) {
// Pop the screen onAccepted if no explicit showRecord behavior is maintained or if onAccepted is showRecord behavior maintained
if( 0 === Object.keys(showRecordOnIncomingBehavior).length || 'onAccepted' === showRecordOnIncomingBehavior.showRecord) {
// Screen pop the related tasks of the interaction
openInteraction(attributes.interactionId.value);
}
}
} else {
// TODO: Backfill the interaction record with whatever information we can get
}
var payload = {};
var contactNode = {};
payload.contact = contactNode;
var contactId = contact.getContactId();
contactNode.contactId = contactId;
contactNode.type = contact.getType();
contactNode.status = status;
contactNode.attributes = attributes;
contactNode.queueInfo = contact.getQueue();
sendSoftPhoneEvent('contact', event, payload);
}
}
}
} catch(ce) {
console.error(ce);
}
};
 
        var sendOutgoingCallToContactSoftPhoneEvent = function(contact) {
if(contact ${AND} contact.contactId ${AND} contact.contactId !== "") {
var actor = 'agent';
var event = 'outgoing_call_to_customer';
try {
var payload = {};
var contactNode = {};
payload.contact = contactNode;
contactNode.contactId = contact.contactId;
contactNode.agentSysId = '${jvar_user_sysid}';
payload.phoneNumber = '';
if (contact ${AND} contact.getActiveInitialConnection ${AND} contact.getActiveInitialConnection().getEndpoint)
payload.phoneNumber = contact.getActiveInitialConnection().getEndpoint().phoneNumber;
 
var debug = {
source: 'aws_ccp',
actor: actor,
event: event,
payload: payload,
method: "sendOutgoingCallToContactSoftPhoneEvent"
};
console.log(debug);
var finalPayload = payload ? payload : {};
finalPayload['window'] = {
location: {
href: window.location.href,
search: window.location.search
}
};
finalPayload['aws'] = {
connect: {
config: cfg
}
};
 
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/sn_cti_core/cti_api/softphone/sources/aws_ccp/actor/' + actor + '/events/' + event);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader('X-UserToken', '${jvar_session_token}');
xhr.send(JSON.stringify(finalPayload));
xhr.onreadystatechange = function() {
try {
if(xhr.readyState === XMLHttpRequest.DONE) {
var response = JSON.parse(xhr.response);
var interaction_id = response ? response.result.AwsConnectSoftPhoneEventSink4Interaction.interactionId : null;
if (interaction_id)
openInteraction(interaction_id);
}
} catch(ex) {
console.error("Exception:sendOutgoingCallToContactSoftPhoneEvent: " + ex.message);
}
}
} catch(se) {
console.error("Exception:sendOutgoingCallToContactSoftPhoneEvent: " + se.message);
}
}
};
</script>
 </j:if>
</j:jelly>

Do you know how to check your browser console? If yes, try adding the log statement here:

 

      function initCallback(snConfig) {
        console.log("openframe configuration", snConfig);
        console.log("Page location is: " + window.location.href); // **** TESTING *****
        var openFrameConfig = snConfig;
        if (openFrameConfig.configuration)
          showRecordOnIncomingBehavior = JSON.parse(openFrameConfig.configuration);
        //register for communication event from TopFrame
        openFrameAPI.subscribe('openframe_awa_agent_presence', handleOpenFrameAwaEvent);
        //register event for click to call
        openFrameAPI.subscribe('openframe_communication', handleClickToCall);
        //register for work item accepted event
        openFrameAPI.subscribe('openframe_awa_workitem_accepted', handleWorkItemAccepted);
      }