ServiceNow CTI Integration
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
Environment: ServiceNow Yokohama version
I’ve embedded my custom CTI Phone app as the OpenFrame softphone, and I’m attempting to programmatically “open/show” the phone by sending an event from the CTI app itself. The message exchange between the CTI app and ServiceNow UI Scripts is working correctly. I’m able to send and receive messages successfully.
However, when I try to open/show or hide/close the OpenFrame, it doesn’t respond as expected. I’m currently using the following System UI → UI Script and the corresponding HTML script from the CTI app side to send, receive, and control the OpenFrame.
I’m not sure what I might be missing — any expert advice or suggestions would be greatly appreciated.
System UI -> UI Scripts
================================
(function() {
console.log('UI Script initialized — listening for messages from iframe');
function fnLog() {
console.log('fnLog :');
};
function handleIncomingMessage(event) {
try {
var msg = event.data;
if (!msg || typeof msg !== "object") return;
console.log('Message received from Tryvium app:', msg);
console.log('window.top.NOW.CustomEvent ', window.top.NOW);
// Ensure we are running in top-level workspace shell
if (!window.top.NOW || !window.top.NOW.CustomEvent) {
console.warn("⚠️ NOW.CustomEvent not available yet. Retrying...");
setTimeout(function() {
handleIncomingMessage(event)
}, 1000);
return;
}
window.top.NOW.CustomEvent.observe(msg.eventName, fnLog());
switch (msg.eventName) {
// 🧲 Expand (show) the phone
case "openframe_open":
case "openframe_expand":
case "openframe_shown":
console.log("📞 Showing the CTI phone...");
window.top.NOW.CustomEvent.fireAll("openframe_shown");
break;
// 🧲 Collapse (hide) the phone
case "openframe_close":
case "openframe_collapse":
case "openframe_hidden":
console.log("📴 Closing the CTI phone...");
// var hiddenPayload = {
// eventName:"openframe_hidden",
// type:"NOW.PostMessage"
// };
window.top.NOW.CustomEvent.fireAll("openframe_hidden");
break;
// 🧾 Open an Incident in Agent Workspace
case "open_incident":
console.log("📄 Opening Incident:", msg.data);
const table = msg.data?.table || "incident";
const sysId = msg.data?.sys_id;
if (window.top.NOW.workspaceNavigator) {
window.top.NOW.workspaceNavigator.openRecord({
table: table,
sysId: sysId
});
} else {
console.warn("⚠️ workspaceNavigator not found");
}
break;
default:
console.log("ℹ️ Unhandled message type:", msg.eventName);
}
} catch (error) {
console.error('Error processing incoming message:', error);
}
}
// Listen at the top window level
if (window.top) {
window.top.addEventListener('message', handleIncomingMessage, true);
} else {
window.addEventListener('message', handleIncomingMessage, true);
}
})();
CTI Phone APP
===================
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CTI App - Yokohama Demo</title>
<script>
function sendToServiceNow(action) {
const allOrigins = "*";
const sourceOrigin = '<source origin>';
const targetOrigin = '<target origin>';
// Always use window.top to reach the outer ServiceNow frame
if (!window.top) {
throw new Error('Window.top is not accessible');
}
if (action === "open_cti_phone") {
const payload = {
type: "cti_to_snow",
eventName: "openframe_open",
data: {
caller: "John Doe",
phone: "<phone>",
incidentId: "INC0012345"
}
};
console.log("📤 Sending message to ServiceNow:", payload);
window.top.postMessage(payload, allOrigins);
} else if (action === "close_cti_phone") {
const payload = {
type: "cti_to_snow",
eventName: "openframe_hidden",
data: {
caller: "John Doe",
phone: "<phone>",
incidentId: "INC0012345"
}
};
console.log("📤 Sending message to ServiceNow:", payload);
window.top.postMessage(payload, allOrigins);
} else if (action === "open_incident_tab") {
const incidentPayload = {
type: "cti_to_snow",
eventName: "open_incident",
data: {
table: "incident",
sys_id: "654b17c23b0ea6100dc35c0864e45a9d"
}
};
console.log("📤 Sending message to ServiceNow:", incidentPayload);
window.top.postMessage(incidentPayload, allOrigins);
}
}
// Listen for messages back from ServiceNow or target
window.addEventListener("message", (event) => {
console.log("📩 CTI received:", event.origin, event.data);
});
</script>
</head>
<body style="font-family:sans-serif">
<h3>CTI App (OpenFrame)</h3>
<button onclick="sendToServiceNow('open_cti_phone')">Open CTI Phone</button>
<button onclick="sendToServiceNow('close_cti_phone')">Close CTI Phone</button>
<button onclick="sendToServiceNow('open_incident_tab')">Open Incident</button>
</body>
</html>
