Microsoft Social Engagement Content Blocked in Form

Hi everyone,

This time I’m gonna share my experience with Microsoft Social Engagement in Dynamics 365. So, I have my MSE analytics grid embedded in my D365 deployment. It’s been working fine until one day I saw this error on the grid.

I was so sure that I didn’t make any changes either to the form or the MSE config itself. So, I checked everything and found that MSE was not set up correctly. I needed to add the Dynamics address to MSE allowed domain to display it properly.

This is the result after I fixed the issue.

Hope this helps.

Add Custom Web Resource into Schedule Board and Where to Find It

No, it’s not a part of Harry Potter stories nor in its universe. This is about Dynamics 365 and it’s universe. 🙂

So, I came across the new Resource Scheduling in Dynamics 365 for Field Service and Project Service Automation. And I was asked to test out how to embed Google map into Schedule Board because we saw that it can hold custom web resource.

So, I edited the tab and added a web resource containing Google map into it. After saving, I look carefully to see where the changes take place but oddly it seems like nothing’s changed!

After a while, I tried to re-examine the dashboard carefully and expanded every layer, one by one and voila, it’s hiding inside the “Details” tab!

So, in conclusion, when you add a custom web resource into the schedule board, it will be displayed as a new tab in the “Details” tab.

Cheers!

Adding Intent Detection to Case in Dynamics 365

This is the second post of a series of works I do in integrating Azure AI capabilities with Dynamics 365. This is to proof that integration concept of LUIS into D365 is doable.

Intent Detection is derived from language understanding (LUIS) in Microsoft Azure. We usually see LUIS being implemented in chatbots, but this time I want to show you how it can be implemented in other area as well, especially in Dynamics 365. In my work, what I did was detecting description in case entity and understand the intent using LUIS. It’s like Text Analytics in my previous post, working in the same mechanism but it’s utilizing different Azure API though.

Pre-requisites

To build this, you must have:

  • An instance of Dynamics 365 for Customer Service (Online)
  • Your own active LUIS project.
  • A custom field to store the repsonse from the API.

Setting Up

  1. After signing up for Azure LUIS, login to https://www.luis.ai/home to create and train your own LUIS project. Don’t forget to keep the subscription key string and endpoint and store it somewhere for later use.

  2. For my research purpose, I saved this info in a custom entity.

  3. You can build your own LUIS or, to ease complexity, you can use the pre-loaded intent provided and add more intents as you require. For more details pertaining LUIS project development, you can follow this link below.

    https://docs.microsoft.com/en-us/azure/cognitive-services/LUIS/luis-get-started-create-app

  4. Now, let’s do something in case entity. I created a custom field and put it in the form. This field is to display the intent returned by LUIS.
  5. Time to write some js to call the API of published LUIS project. The web service can be called thru multiple ways. I just love js because I can see the result immediately.
function callIntentDetectionAPI(){
    var text = Xrm.Page.getAttribute("description").getValue();
    if (text != null){
        var xhr = new XMLHttpRequest();
        var URL = retrieveConfig("LUIS API");
        var subscriptionKey = retrieveConfig("LUIS Subscription Key");
        var URL = URL + encodeURIComponent(text);
        xhr.addEventListener("readystatechange", function () {
         if (this.readyState === 4) {
            var resp = JSON.parse(this.responseText);
            Xrm.Page.getAttribute("new_intentiontxt").setValue(resp.topScoringIntent.intent);
         }
        });
        xhr.open("GET", URL);
        xhr.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
        xhr.send();
    }
}

function retrieveConfig(configName){
    var new_value;
    var req = new XMLHttpRequest();

    req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/new_configurationsettings?$filter=new_name eq '" + configName + "'", false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
    req.onreadystatechange = function() {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
                for (var i = 0; i < results.value.length; i++) {
                    new_value = results.value[i]["new_value"];
                }
            } else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send();
    return new_value;
}

6. Register your js file in your case form. In my case, I registered the js in OnChange event of description field, so we can extract the intent promptly.

7. Once all set, publish your customization and test.

Hope this post will be useful. Happy CRM-ing!

Analyze Case Sentiment in Dynamics 365 for Customer Service

Hi folks!

In this very first post I would like to show you the capability of Dynamics 365 to utilize Azure AI Text Analytics to extract the sentiment of a case. For some of you who are not familiar with Text Analytics API, it is part of Cognitive Services provided by Microsoft Azure. This API is a cloud-based service that provides advanced natural language processing over raw text, and includes three main functions: sentiment analysis, key phrase extraction, and language detection. For more details, you can check it out here.

Alright, moving on to the main objective of this post, I want to show you how I cultivated Text Analytics API functionalities and embedded it into Dynamics 365. As an example, I have a case whom customers sent complaint in description. The system analyzes the description and extract the sentiment score, key phrases and detect the language of the customer.

result_first

Pre-requisites

To build this, you will need:

  • An instance of Dynamics 365 for Customer Service (Online)
  • Active subscription key to Text Analytics API provided by Azure.
  • Some custom fields to store the extractions from the API.
  • Some emoticons (nice to have).

Setting Up

The first thing you need to do is to subscribe to Microsoft Azure. If you happened to not have Text Analytics API subscription you can follow steps below or refer to this link for a comprehensive one.

Once you logged in to Azure portal, create new resource and choose AI + Cognitive ServicesText Analytics API.

azure_1

Choose the pricing tier, in my case I opted for the free one.

azure_2

Once you’re done, you might want to save the endpoint address and the subscription key. Click on manage keys to get the subscription key.

azure_3

For my research purpose, I saved this info in a custom entity.

custom_config

Now, let’s do something in case entity. I created some custom fields and display them in the form.

custom_form

Then, write a js to call the Text Analytics API and retrieve the result. In this example, I extract the sentiment of description field by sending it over to API. The complete guide to call API is available in this article.

function callTextAnalyticsAPI(type, description) {
       debugger;   

       var params = {
             // Request parameters
       };          

       var body = JSON.stringify({
         "documents": [
             {
               "language": "",
               "id": "1",
               "text": description
             }
             ]
       });

       var xhr = new XMLHttpRequest();
       xhr.addEventListener("readystatechange", function () {
         if (this.readyState === 4) {
             // alert(this.responseText);
             var resp = JSON.parse(this.responseText);            

             if (type == "language"){
                    var languageDetected = resp.documents[0].detectedLanguages[0].name.toString();
                    Xrm.Page.getAttribute("new_language").setValue(languageDetected);
             } else if (type == "keyphrase"){
                    var keyPhrases = resp.documents[0].keyPhrases.toString();
                    Xrm.Page.getAttribute("new_keyphrases").setValue(keyPhrases);
             } else {
                    var score  =  resp.documents[0].score.toFixed(2);
                    var sentiment  = classifySentimentScore(score);
                    Xrm.Page.getAttribute("new_sentimentscore").setValue(score);
                    Xrm.Page.getAttribute("new_sentiment").setValue(sentiment);
                    setSentimentEmoticon();
             }
         }
       });
    
       var URL = retrieveConfig("Text Analytics API");
       var subscriptionKey = retrieveConfig("Text Analytics Subscription Key");
          
       if (type == "language"){
             URL = URL + "/languages";       
       } else if (type == "keyphrase"){
             URL = URL + "/keyPhrases";      
       } else {
             URL = URL + "/sentiment";       
       }

       xhr.open("POST", URL);
       xhr.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
       xhr.setRequestHeader("Content-Type", "application/json");
       xhr.setRequestHeader("Accept", "application/json");
       xhr.send(body);
}

Next step is to add a nice-to-have feature of emoticon in the form. Here, I added three emoticons (happy, sad and neutral emotions) to be displayed. Save these emoticons as web resources and extract the URL so that we can set it dynamically in js.

web_resource

function setSentimentEmoticon(){
       var sentiment = Xrm.Page.getAttribute("new_sentiment").getValue();
       var url = Xrm.Page.context.getClientUrl();
       var iFrame = Xrm.Page.getControl('IFRAME_Sentiment');

       if (sentiment != null){
             if (sentiment == "Very High" || sentiment == "High"){
                    iFrame.setSrc(url + "/%7B636541873040000127%7D/WebResources/new_happy.png");
             } else if (sentiment == "Low" || sentiment == "Very Low"){              
                    iFrame.setSrc(url + "/%7B636541873040000127%7D/WebResources/new_sad.png");
             } else {
                    iFrame.setSrc(url + "/%7B636541873040000127%7D/WebResources/new_neutral.png");
             }
       }
}

Register your js file in your case form. In my case, I registered the js in OnSave event, so we can extract the sentiment on saving the case.

Once all set, publish your customization and test.

result_final

Hope this post will be useful. Happy CRM-ing!

 

P.S. This post was influenced by this post which utilizes Text Analytics in USD.