Custom Extensions for the RingCentral Embeddable Voice Web Widget

John Wang
RingCentral Developers
4 min readJul 17, 2018
RingCentral Embeddable Voice Custom Extensions

At last year’s Dreamforce and Connect Central conferences, we introduced the Embeddable Voice web widget, a UI SDK that allows you to easily embed RingCentral into any web app, or even desktop apps using captive browsers. With the first release, we allowed you to:

  1. embed the RingCentral communications experience in your web app
  2. configure two-way communication between RingCentral and your app for click-to-dial, inbound screen-pop and call logging
  3. customize the look and feel of the widget for your own colors
  4. access the React components to customize and extend the widget

Now we’ve gone one step further and allowed you to extend the widget itself more easily by building in hooks for popular use cases, specifically:

  1. contacts integration so you can view your contacts and have their names associated with call records without loading them into RingCentral
  2. custom conference call invites so you can create invites using your solution of choice. We now have an example implementation for Office 365 Calendar
  3. call logging integration which allows you to launch a 3rd-party app to log calls with the click of a button

These are available in the core Embeddable Voice SDK:

Here are some examples to get you started.

Custom Conference Call Invites

Add a custom conferenceInvite with a custom name. The RingCentral for Google integration has built-in conference invites for Google Calendar. For this example, we will create an integration with Office 365 Calendar.

Embeddable Voice with Custom Office 365 Conference Invite

First, register your service with the text you would like to appear on the button, “Invite with Office 365 Calendar”.

// Register your service
function registerService() {
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
type: 'rc-adapter-register-third-party-service',
service: {
name: 'Game of Thrones',
conferenceInvitePath: '/conference/invite',
conferenceInviteTitle: 'Invite with Office 365 Calendar'
}
}, '*');
}

Add a listener for the /conference/invite data.path to your custom code, e.g. inviteConference.

// Add message event to response to the widget
window.addEventListener('message', function (e) {
var data = e.data;
if (data && data.type === 'rc-post-message-request') {
if (data.path === '/conference/invite') {
inviteConference(data);
}
}
});

Then create the inviteConference and supporting functions:

function inviteConference(request) {
var calendarUrl = buildO365CalendarUrl({
'subject':'New Conference',
'body': request.body.conference.inviteText});
window.open(calendarUrl);
responseMessage(request, { data: 'ok' });
}
function buildO365CalendarUrl(params={}) {
var calendarUrl = 'https://outlook.office.com/owa/?path=/calendar/action/compose';
var encoded = [];
if ('subject' in params) {
encoded.push('subject=' + encodeURIComponent(params['subject']));
}
if ('body' in params) {
encoded.push('body=' + encodeURIComponent(params['body']));
}
if (encoded.length > 0) {
calendarUrl = calendarUrl + '&' + encoded.join('&');
}
return calendarUrl;
}

Contacts Integration

Contacts integration allows you to do three things:

  • have custom contact names appear next to calls in Call History
  • have custom contact names appear in your directory for calling
Embeddable Voice with Custom Contacts

Register your service. You can use the same registerService function as above.

// Register your service
function registerService() {
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
type: 'rc-adapter-register-third-party-service',
service: {
name: 'Game of Thrones',
conferenceInvitePath: '/conference/invite',
conferenceInviteTitle: 'Invite with Office 365 Calendar'
contactsPath: '/contacts',
contactSearchPath: '/contacts/search',
contactMatchPath: '/contacts/match'
}
}, '*');
}

Add a listener for the /contacts/* data.path to your custom code as shown below.

// Add message event to response to the widget
window.addEventListener('message', function (e) {
var data = e.data;
if (data && data.type === 'rc-post-message-request') {
if (data.path === '/conference/invite') {
inviteConference(data);
}
if (data.path === '/contacts') {
getContacts(data);
}
if (data.path === '/contacts/search') {
searchContacts(data);
}
if (data.path === '/contacts/match') {
matchContacts(data);
}
}
});

For getContacts return a JSON array as follows:

function getContacts(request) {
responseMessage(request, {
data: [
{
"id":"+14235550143",
"name":"Eddard \"Ned\" Stark",
"type":"Game of Thrones",
"phoneNumbers":[
{
"phoneNumber":"+14235550143",
"phoneType":"directPhone"
}
]
}
]
}
}

To implement searchContacts and matchContacts, see the Embeddable Voice documentation: Third-Party Service in Widget.

Call Logging Integration

You can also launch a third-party app to log any call in your Call History. A log button will appear next to each call log entry to initiate a 3rd-party call log action.

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
type: 'rc-adapter-register-third-party-service',
service: {
name: 'Game of Thrones',
callLoggerPath: '/callLogger',
callLoggerTitle: 'Log to CRM'
}
}, '*');

Here is an example posting the message which your code can hook into.

window.addEventListener('message', function (e) {
var data = e.data;
if (data && data.type === 'rc-post-message-request') {
if (data.path === '/callLogger') {
// add your codes here to log call to your service
console.log(data);
// response to widget
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
type: 'rc-post-message-response',
responseId: data.requestId,
response: { data: 'ok' },
}, '*');
}
}
});

Try it out

You can try it out by following the instructions in the Embeddable Voice repo. Reach out to us on GitHub issues, Developer Community, or Stack Overflow if you have any questions.

--

--

John Wang
RingCentral Developers

AVP Platform Products for @RingCentral with a focus on improving life through innovative products and software