The Microsoft Dynamics 365 Contact Center is transforming customer engagement through Generative AI technology across various communication channels. It serves as an Copilot-first contact center as a service (CCaaS) solution compatible with preferred CRMs or third-party (3P) software. This add-on enables customers to leverage Dynamics 365 Contact Center along with AI functionalities within their preferred CRM system.
Built upon the Microsoft Azure, Power Platform, and core Dynamics 365 infrastructure, Dynamics 365 Contact Center extends its capabilities by seamlessly integrating CCaaS and AI features with existing 3P solutions. Agents have the flexibility to utilize the add-on in either Embedded mode, where the 3P CRM serves as the primary user experience (UX) with CCaaS/AI functionalities embedded, or Standalone mode, where Dynamics 365 Contact Center plus AI capabilities take precedence while maintaining connectivity with 3P CRM data.
- Set up D365 Contact Center embedded experience
- Install Node latest version
- git clone
https://github.com/microsoft/dynamics-365-contact-center.git
Recommended versions for compiling custom CTI drivers:
- Node: 22.x LTS (minimum supported: 16.20.x)
- npm: >=8 (minimum: >=7 for lockfile v2; use
npm cinotnpm install) - TypeScript: 5.5.x–5.9.x (minimum: 4.9.5; earlier versions fail with loader/types)
- webpack: 5.x (must produce a single bundled JS file that registers
window.CCaaS.CTIDriver) - ts-loader: 9.x
- tsconfig key settings:
module: commonjs,target: es6(If you change either, rebuild and test in the embedded environment to ensure the driver still loads.)
Disclaimer: Earlier Node (>=16.1.x) and TypeScript (>=4.9.5) versions may build, but only the listed minimums and recommendations are validated for deterministic single-file bundles and reliable runtime loading.
The CTI driver serves as a bridge between the Microsoft Omnichannel Add-on and Salesforce CRM, allowing for the integration of telephony features into the CRM environment.
IMPORTANT NOTICE: The external URL method for loading CTI drivers (Approach 2) is deprecated and will be removed on September 19, 2025. Please use the Web Resource approach (Approach 1) for all new implementations and migrate existing implementations immediately.
Before proceeding with platform-specific setup, understand the approaches available for configuring custom CTI drivers using the useCustomCTI flag:
This is the preferred and secure method for loading custom CTI drivers.
a. Upload Custom CTI Driver to Web Resource:
-
Search for web resource under Default solutions in Dynamics 365
-
Search for:
msdyn_CustomCTIDriver.js -
Display name: "CustomCTIDriver.js"
-
Click on
msdyn_CustomCTIDriver.jsto modify the JS file -
Replace the content with your compiled CTI driver file content (e.g.,
dist/SFExampleCTIDriver.jsordist/SNExampleCTIDriver.js) and save and publish.
b. Use the CCaaS URL with Web Resource:
https://<example-ccaas-domain>/widget/index.html?dynamicsUrl=https://<dynamics-environment>.crm.dynamics.com&useCustomCTI=1Note: To verify web resource loading, check browser console for the element:
document.getElementById("InlineCustomCTIDriver")This method is deprecated and will be removed in the 8.3 train release. Please migrate to the Web Resource approach (Approach 1) immediately.
a. Configure App Setting in Dynamics 365:
- Set msdyn_enableCustomCTIFromWebresource to "No" in Setting definitions
b. Host the compiled file externally:
-
Host your compiled CTI driver file on a CDN or any publicly accessible URL
-
Use the CCaaS URL with external CTI driver:
https://<example-ccaas-domain>/widget/index.html?dynamicsUrl=https://<dynamics-environment>.crm.dynamics.com&useCustomCTI=1&ctiDriverUrl=<CDN-url>
Use the built-in default CTI driver without any custom implementation:
-
Set
useCustomCTI=0in the query parameter -
Use the following URL format:
https://ccaas-embed-test.azureedge.net/widget/index.html?dynamicsUrl=https://example.crm10.dynamics.com/&useCustomCTI=0
-
The system will automatically load the default CTI driver based on the environment
Note: Default CTI driver ignores any ctiDriverUrl parameter when useCustomCTI=0
** Key Point:** To use ANY custom CTI driver (either web resource or external URL), you MUST include useCustomCTI=1 in the URL.
When useCustomCTI parameter is missing from URL:
- The system defaults to
useCustomCTI=0behavior - System attempts to load default CTI driver for the environment
- Both
ctiDriverUrlparameter and web resource are ignored
| useCustomCTI Parameter | App Setting | Expected Output | Example URL |
|---|---|---|---|
useCustomCTI=1 |
TRUE | Gets script from web resource (recommended) | https://ccaas-embed-test.azureedge.net/widget/index.html?dynamicsUrl=https://example.crm10.dynamics.com/&useCustomCTI=1 |
useCustomCTI=1 (deprecated) |
FALSE | Gets script from ctiDriverUrl parameter | https://ccaas-embed-test.azureedge.net/widget/index.html?dynamicsUrl=https://example.crm10.dynamics.com/&useCustomCTI=1&ctiDriverUrl=https://your-cdn-url.com/js/YourCTIDriver.js |
useCustomCTI=0 |
Ignored | Uses default CTI driver (ignores ctiDriverUrl and web resource) | https://ccaas-embed-test.azureedge.net/widget/index.html?dynamicsUrl=https://example.crm10.dynamics.com/&useCustomCTI=0 |
example-ccaas-domain: https://ccaas-embed-prod.azureedge.net
-
Navigate to
/samples/SFExampleCTIDriver -
Run command
npm install -
Open the file
/samples/SFExampleCTIDriver/src/SFExampleCTIDriver.ts -
Implement your desired functionality within any of the methods provided by the ICTIDriver interface. Refer to the Salesforce OpenCTI Methods Documentation for available methods and their usage.
-
Run command
npm run build, dist/SFExampleCTIDriver.js file will get generated inside /SFExampleCTIDriver folder -
Configure Custom CTI Driver: Follow the web resource approach (Approach 1) described in the Common CTI Driver Configuration section above. Upload the
dist/SFExampleCTIDriver.jsfile to the web resource. -
Update the Salesforce Call center definition file (imported in prerequisite) by replacing the URL with the one generated in Step 6 based on your chosen approach.
-
Your Salesforce Extension integration is now complete and ready to use.
-
Navigate to
/samples/SNExampleCTIDriver -
Run command
npm install -
Open the file
/samples/SNExampleCTIDriver/src/SNExampleCTIDriver.ts -
Implement your desired functionality within any of the methods provided by the ICTIDriver interface. Refer to the ServiceNow OpenFrame Methods Documentation for available methods and their usage.
-
Run command
npm run build, dist/SNExampleCTIDriver.js file will get generated inside /SNExampleCTIDriver folder -
Configure Custom CTI Driver: Follow the web resource approach (Approach 1) described in the Common CTI Driver Configuration section above. Upload the
dist/SNExampleCTIDriver.jsfile to the web resource. -
Add the URL generated in Step 6 (based on your chosen approach) to the respective OpenFrame Configuration as shown in the screenshot below:
Url to the list of OpenFrame Configuration:
https://<ServiceNow-domain>/now/nav/ui/classic/params/target/sn_openframe_configuration_list.do -
Your ServiceNow Extension integration is now complete and ready to use.
-
Navigate to
samples/GenericExampleCTIDriver. -
Run
npm installto install the project dependencies. -
Navigate to
GenericExampleCTIDriver/src/GenericExampleCTIDriver.ts. -
Implement the methods defined in
ICTIInterfaceaccording to your CRM requirements. -
Run
npm run buildto compile the project. -
Configure Custom CTI Driver:
-
Recommended: Follow the web resource approach (Approach 1) described in the Common CTI Driver Configuration section above. Upload the compiled
dist/GenericExampleCTIDriver.jsfile to the web resource. -
Legacy (Deprecated): Host the compiled file on a CDN and include the CDN URL as a query parameter in the CCaaS URL:
https://<example-ccaas-domain>/widget/index.html?dynamicsUrl=https://<dynamics-environment>.crm.dynamics.com&ctiDriverUrl=<CDN-url>Note: This method will be removed on September 19, 2025. Please migrate to the web resource approach.
example-ccaas-domain:
https://ccaas-embed-prod.azureedge.net -
-
Incorporate this URL into the phone/softphone settings of your CRM.
- Use
window.postMessageto communicate from CTIDriver to Generic CRM.
embedSDK.conversation.onConversationLoaded((conversationData: IConversationLoadedEventData) => {
console.log("Embed SDK Conversation Loaded", conversationData);
window.parent.postMessage(conversationData, "*");
presenceAPIs(embedSDK);
getFocusedConversationId(embedSDK);
});- Use
document.getElementById("iframeId").contentWindow.postMessageto communicate from Generic CRM to CTIDriver.
// code required to send message on Generic CRM side
document.getElementById("iframeId").contentWindow.postMessage(JSON.stringify({messageType:"clickToDial", messageData: {number: 8208654321}}),"*");
// code required to listen for message event on CTIDriver side
window.addEventListener("message", (event) => {
const {messageType, messageData} = JSON.parse(event.data);
if (messageType && messageType === "clickToDial") {
const clickDialPayload = {
number: messageData.number
};
callbackFunction(clickDialPayload);
}
})Refer to the CCaaS SDK README for details on available APIs and how to integrate them.



