Dynamics 365 Telephony Integration for Developers (Part 2): Building the Widget

This is Part 2 of our developer series on Dynamics 365 telephony integration. In Part 1 we covered the architecture: the Channel Integration Framework (CIF v2), channel providers, and widgets. Now it's time to actually build the widget itself.

What the Widget Actually Is

Your widget is nothing exotic. It's a plain web page, hosted anywhere that supports HTTPS, that Dynamics 365 loads inside an iframe docked to the side of the Unified Interface. Everything you build here is standard HTML, CSS, and JavaScript. The only special ingredient is a JavaScript library Microsoft provides called CIFramework.js, which gives your page the ability to talk to Dynamics 365 through the iframe boundary.

Loading the CIF Library

The first thing your widget's HTML page needs to do is reference the CIF script and call its initialize method. This establishes the communication channel between your widget and the host Dynamics 365 window.

<script src="https://.../CIFramework.js"></script>
<script>
  Microsoft.CIFramework.initialize()
    .then(function () {
      console.log("Widget successfully connected to Dynamics 365");
      setupEventHandlers();
    })
    .catch(function (error) {
      console.error("Initialization failed", error);
    });
</script>

Until this promise resolves, none of the other CIF methods will work reliably, so it's good practice to gate the rest of your widget's logic behind a successful initialization.

Structuring Your Code Around Events

Once initialized, most of your widget's job is reacting to events. Dynamics 365 can notify your widget when an agent clicks a phone number, and your widget can notify Dynamics 365 when a call starts, ends, or needs a record opened. A clean way to structure this is to keep three layers in your code: a UI layer for the dialer pad itself, a "bridge" layer that only talks to CIF methods and events, and a "provider" layer that talks to your actual telephony backend (like Twilio or a SIP service). Keeping these separated makes it much easier to swap telephony providers later without rewriting your CIF integration logic.

Registering Your Event Handlers

CIF v2 uses a simple handler registration pattern. For example, to prepare for handling an agent clicking a phone number (which we'll wire up fully in Part 3), you register a listener like this:

function setupEventHandlers() {
  Microsoft.CIFramework.addHandler("onclicktoact", function (event) {
    console.log("Click to act received", event.data);
  });
}

At this stage, simply logging the event to the console is enough to confirm your widget is correctly wired up and receiving data from Dynamics 365.

Keeping the Widget Lightweight

Because your widget lives in a fairly narrow docked panel, it's worth keeping its UI simple: a dial pad, an active call display, and maybe recent call history. Avoid pulling in heavy frontend frameworks unless you need them, since the widget needs to load quickly every time an agent opens their session.

What's Next

With initialization working and your event-handling structure in place, Part 3 of this series covers the two features agents notice immediately: click-to-dial and screen pop.