Node Js Heroku Canvas Integration

Introduction

In this blog, I am going to explain Heroku and node js canvas integration. Canvas allows you to integrate web applications with Salesforce in the different places of salesforce like Chatter Tab, Visualforce Page, Lightning Component, Publisher, Chatter Feed, Console, Open CTI, Mobile Navigation, Layouts, and Mobile Cards. In this post, I am going to show the simple table that contains the product master data which is a simple HTML table.

Prerequisites

  1. Git installed on your local machine
  2. Heroku account
  3. Heroku toolbelt installed.
  4. Node.js installed on your local machine

Creating Connected App

In order to integrate the salesforce with Heroku application, you need to create the configure the salesforce connected app as shown.

  • Setup -> Create -> Apps -> Connected Apps-> New
  • Fill  Connected App NameAPI Name, and Contact Email as shown in the image 
  • Check the Enable OAuth Settings in the API (Enable OAuth Settings) section
    • Callback URL: add as https://localhost.com/_callback. Later after deploying node js app to Heroku, we need to change this.
    • Selected OAuth Scopes: select the scopes you want for the NodeJS app access token to grant.  Select as ” Full Access ” for this testing app.
  • In the section, Canvas App Settings type Check Force.com Canvas
  • Canvas App URL: https://localhost.com/canvas/callback.Later after deploying the apps Heroku, we are going to change this URL.
  • Access Method: Signed Request (POST)
  • Locations: choose Chatter Tab and publisher as of now. but you can select one or more based on the where you want to show this the canvas on salesforce.
    Now finally connected App is looking as shown below.

Now you need to enable the app for the profiles or users. To do this,

  • Click on the Manage on the connected App which you created in above .click edit policies
  • In the OAuth policies select Admin approved users are pre-authorized for the Permitted Users field and save it
  • In the Profiles related list add the profiles or permission set which you wanted to grant access

Building Your App on Node Js

Let’s set up the basic app structure. We will use Express to set up a basic Node application. Here is the below package.json file which we will use to build the node js application. The application folder structure is shown below.

package.json

{
    "name": "canvasquickaction",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "dependencies": {
        "body-parser": "^1.15.0",
        "crypto-js": "^3.1.6",
        "express": "^4.13.4"
    },
    "devDependencies": {},
    "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC"
}
  • Once you have created your file structure, set up a Git repo in this directory by running from command. $ git init your command line within this directory.
  • Inside of the public > views > index.html file, add the following code
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        https://code.jquery.com/jquery.js
        <style>
            * {
                margin: 0;
                padding: 0;
                font-family: Lato;
            }
            
            body {
                padding: 0px;
                background: #f6f3f7;
            }
            
            h1 {
                display: block;
                width: 100%;
                background: #64e0ef;
                height: 55px;
                padding-left: 10px;
                color: #fff;
                font-size: 20px;
                line-height: 55px;
                text-shadow: 1px 1px 1px rgba(0, 0, 0, .3);
                box-sizing: border-box;
                text-align: center;
            }
            
            table {
                width: 100%;
                min-width: 500px;
                border-collapse: collapse;
                font-weight: bold;
                color: #6b6b6b;
            }
            
            thead {
                background-color: rgba(29, 150, 178, 1);
                border: 1px solid rgba(29, 150, 178, 1);
                font-weight: normal;
                text-align: center;
                color: white;
            }
            
            tr {
                height: 50px;
                text-align: center;
            }
            
            td {
                box-sizing: border-box;
                text-align: center;
            }
        </style>
    </head>
    
    <body>
        <div>
            <h1>Product Manangement Node Js Heroku Integration </h1>
            <table>
                <thead>
                    <tr>
                        <th>Item Name </th>
                        <th>Master Price </th>
                        <th>Discount </th>
                        <th>Product Description </th>
                        <th>Discount Approval </th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                      
                        <td>Product ACT 100</td>
                        <td>$279.00</td>
                        <td>$29.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 200</td>
                        <td>$279.00</td>
                        <td>$29.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 300</td>
                        <td>$279.00</td>
                        <td>$10.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 400</td>
                        <td>$279.00</td>
                        <td>$39.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 500</td>
                        <td>$279.00</td>
                        <td>$21.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>Yes</td>
                    </tr>
                    <tr>
                        
                        <td>Product ACT 600</td>
                        <td>$279.00</td>
                        <td>$19.00</td>
                        <td>Affordable and easy to use, Act!</td>
                        <td>No</td>
                    </tr>
                </tbody>
            </table>
        </div>
    
    </html>

     

  • From the command line in the main app directory initialize your Node app by running -.npm install which will load all the node modules from the package.json

In the index.js file add the following code:

var express  = require('express'),
  bodyParser = require('body-parser'),
  path       = require('path'),
  CryptoJS   = require("crypto-js");

app        = express(),
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'bower_components')));

app.use(bodyParser.json()); // create application/json parser
app.use(bodyParser.urlencoded({ entended: true })); //create application/x-www-urlencoded parser

var views = path.join(__dirname, 'public/views');
 var   consumerSecret = process.env.CONSUMER_SECRET;

app.get('/', function (req, res) {
  res.sendFile(path.join(views, 'index.html'));
});

app.post('/', function (req, res) {
  // Desk secret key	
  var shared = consumerSecret;
  // Grab signed request
  var signed_req = req.body.signed_request;
  // split request at '.'
  var hashedContext = signed_req.split('.')[0];
  var context = signed_req.split('.')[1];
  // Sign hash with secret
  var hash = CryptoJS.HmacSHA256(context, shared); 
  // encrypt signed hash to base64
  var b64Hash = CryptoJS.enc.Base64.stringify(hash);
  if (hashedContext === b64Hash) {
    res.sendFile(path.join(views, 'index.html'));
  } else {
    res.send("authentication failed");
  };  		
})

var port = process.env.PORT || 9000;
app.listen(port);
console.log('Listening on port ' + port);

Run the following from the command line within your main app directory to push your changes to Heroku.

  1. heroku create
  2. git add .
  3. git commit -m "pushing to heroku"
  4. git push heroku master
  5. heroku open
    Open the URL which looks like as a random string like https://limitless-retreat-55750.herokuapp.com/

Now go to the Connected app which you created in earlier, update the callback URL and Canvas App URL with the Heroku app URL  example https://limitless-retreat-55750.herokuapp.com/

Now We have to add the Environmental variable Consumer secret from the connected app to Heroku by runs the following command.

heroku config:set CONSUMER_SECRET=xxxx

Now you can see the Canvas app on the chatter tab as shown below.

Github URL for complete code: https://github.com/rajamohanvakati/Canvas-App-Quick-Action

 

 

 

IBM Watson Salesforce Visual Recognition

In this Blog, I am going to explain how to Integrate Salesforce and IBM Watson Image Recognition.  Visual Recognition allows users to understand the contents of an image or video frame, answering the question: “What is in this image?” and “Are there similar images?” etc. The IBM Watson Visual Recognition service uses deep learning algorithms to analyze images for scenes, objects, faces, and other content. The response includes keywords that provide information about the content.A set of built-in classes provides highly accurate results without training. You can train custom classifiers to create specialized classes. You can also create custom collections of your own images, and then upload an image to search the collection for similar images. In this blog, we are going to use default classifiers to classify an image and then detect faces in an image. You can also preview a live version of this application. Some of the major highlights include

Object determination — Classification of things in the image
Face detection — Detect human faces, including estimation of age & gender
Text extraction — Extract text contained in the image
Celebrity identifier — Identity of the person if your image includes a public figure

1. Setup API Key for IBM Watson Visual Recognition

  1. Register for IBM Bluemix with US South or your preferred region.
  2. Log in to the IBM Bluemix.
  3. Select Create app, to start with the new applet
  4. Find Watson on Services tab
  5. On Watson services, select Visual Recognition API
  6. Click on Create to get started.
  7. On Service credentials, select on credential-1 and copy the API-key
    Once you get the API key you are completed with Bluemix console setup now we will turn to Salesforce.

2. Salesforce Setup

I am considering the case is having an image which we will use for Image Recognition. So let’s set up two new fields on the case as shown below. Upload_Image_URL__c – URL(255)
Image__c  formula   HYPERLINK( Upload_Image_URL__c ,IMAGE( Upload_Image_URL__c , “Case Image”))

3. Train a Custom Classifier

So not too much worried at this stage on the  Custom Classifier and trying to emphasize the out of the box default classifier with IBM Waston. You can consider to implement the custom classifier based on the business logic and wanted to implement your own image classification that fits your model like a product catalog.

4.Remote Site Settings

Add the Image Recognition services under Remote Site settings.

5.Recognition Image

Here is the simple visualforce page that shows how we can classify the images as shown below. You will get the result of each image with a prediction score and Classification. You can now use the class with the highest score in your application to label your image.

6. Code Walkthrough

Here is the code walkthrough for the apex controller. The below code is shown the simple way to build the endpoint URL of image Recognition services.

 public String buildImageRecognizationURL(String imageURL ,String API_KEY ){
        String baseURL = 'https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classify?api_key='+API_KEY+'&url='+imageURL+'&version=2016-05-20';
        return baseURL ;
    }

the below code is making an API call to Watson services along with the image URL

 HttpRequest req = new HttpRequest();
        String baseURL = buildImageRecognizationURL(c.Upload_Image_URL__c, '9c1be84069f7af00896771d0dfd8b1bb4c822d5b');
        req.setEndpoint(baseURL);
        req.setMethod('POST');
        Http http = new Http();
        HTTPResponse res = http.send(req);

Below Code is used to for parsing the JSON response data to show it the page

 public list<Classification> parseJson(String jsonRes){
        list<Classification> classif = new list<Classification>() ;
        Map<String, Object> m =(Map<String, Object>)JSON.deserializeUntyped(jsonRes);
        List<Object> a = (List<Object>)m.get('images');
        Map<String, Object> a2 =(Map<String, Object>)a[0];
        List<Object> a33 = (List<Object> )a2.get('classifiers') ; 
        Map<String, Object> a444 =(Map<String, Object>)a33[0];
        List<Object> a555= (List<Object>)a444.get('classes');
        for(Object o :a555){
            Map<String, Object> classiObj =(Map<String, Object>)o;
            Classification cNew = new Classification(); 
            for(String ss : classiObj.keySet()){
                if(ss=='class'){
                    cNew.classificaions = (String)classiObj.get(ss) ;
                }
                if(ss=='score'){
                    cNew.percentage = (Decimal)classiObj.get(ss) ;
                }
            }
            classif.add(cNew);
        }
        return classif;
    }
    
    public class Classification {
        public String classificaions {get;set;}
        public Decimal percentage {get;set;}
    }

Here is corresponding visualforce page code

 <div class="slds-scope">
        <table class="slds-table slds-table_bordered slds-table_cell-buffer">
            <thead>
                <tr class="slds-text-title_caps" style="padding: 0.5rem; color: rgb(51, 135, 133);">
                    <th scope="col">
                        <div class="slds-truncate" title="Classification"><b>Classification</b></div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="prediction %"><b>prediction %</b></div>
                    </th>
                </tr> </thead>
            <tbody>
                <apex:repeat value="{!fetchClassifications}" var="cls">
                    
                    <tr>
                        <th scope="row" data-label="Classification">
                            <div class="slds-truncate" > {!cls.classificaions}</div>
                        </th>
                        <td data-label="prediction %">
                            <div class="slds-truncate">
                                {!cls.percentage}%
                            </div>
                        </td>
                        
                        
                    </tr>
                    
                </apex:repeat>
            </tbody>
        </table>

Github Repo is here below

https://github.com/rajamohanvakati/Watson-Image-Recognition

Customer Tone Analyze from Live Agent Chat

In this blog, I am going to explain how to understand the customer tone from the live agent chat and this post is an extended version of my post about customer tone. IBM Watson has different tone analyzer services like from the text, email, and customer engagement.
You can use live agent transcript for tone analysis. simple live agent chat is looking as shown below

the result of the analysis will look as shown below.

The code is here for the same is shown here below.

public class IBMWatsonToneChatAnalyzer {
    
    Private String caseId {get;set;}
    public Case c{get;set;}
    public String jsonData{get;set;}
    public ToneAnalysis tones {get;set;}
    public IBMWatsonToneChatAnalyzer(ApexPages.StandardController con){
        caseId = con.getId() ; 
        c =[Select Id , Subject,Description from Case where id=:caseId] ;
        callWatsonToneAnalyser(c);
    }
    
    public  void callWatsonToneAnalyser(Case c) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:Bluemix_Tone_Analyser/v3/tone_chat?version=2016-05-18');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(stringToJSON(c));
        Http http = new Http();
        HTTPResponse res = http.send(req);
        jsonData = res.getBody();
        tones =  (ToneAnalysis) JSON.deserialize(res.getBody(), ToneAnalysis.class);
        
    }
    
    private static String stringToJSON(Case c) {
        LiveChatTranscript trans = [Select Id , Body from LiveChatTranscript where CaseId =:c.Id ];
        String body =trans.Body;
        return     buildJson(body);
    }
    
    public static String buildJson(String body){
        List<String> strSplite = body.Split('<p align="center">') ;
        String againSpl = strSplite[3];
        String spl2 = againSpl.Split('</p>')[0];
        String agentName = spl2.Split('Agent')[1] ; 
        String toMakeJson = strSplite[3].replace('Agent','') ;
        String temp = strSplite[3].replace('Agent','');
        List<String> spliteBodsy = temp.Split(agentName) ; 
        //System.debug('spliteBodsy'+spliteBodsy);     
        JSONGenerator gen = JSON.createGenerator(true);
        gen.writeStartObject();
        gen.writeFieldName('utterances');
        gen.writeStartArray();
        for (integer i = 0; i <spliteBodsy.size(); i++){
            String res = spliteBodsy[i]; 
            List<String> restem =res.Split('Visitor') ; 
            If(restem.size()>1){
                gen.writeStartObject();
                gen.writeStringField('text', res.Split('Visitor')[1]);
                gen.writeStringField('user', 'customer');
                gen.writeEndObject();
                gen.writeStartObject();
                gen.writeStringField('text', res.Split('Visitor')[0]);
                gen.writeStringField('user', 'agent');
                gen.writeEndObject();
                
            }
        }
        gen.writeEndArray();
        gen.writeEndObject();
        
        String pretty = gen.getAsString();
        System.debug('pretty'+pretty);
        return pretty ;
        
    } 
    
    public class Tones {
        public Double score{get;set;}
        public String tone_id{get;set;}
        public String tone_name{get;set;}
    }
    
    public class ToneAnalysis {
        public List<Utterances_tone> utterances_tone{get;set;}
    }
    
    public class Utterances_tone {
        public Integer utterance_id{get;set;}
        public String utterance_text{get;set;}
        public List<Tones> tones{get;set;}
    }
    
    public class Tones_Z {
    }
    
    
    public static ToneAnalysis parse(String json) {
        return (ToneAnalysis) System.JSON.deserialize(json, ToneAnalysis.class);
    }
    
}

The below is the visualforce page for the same.

<apex:page standardController="Case" extensions="IBMWatsonToneChatAnalyzer" showHeader="false"  standardStylesheets="false" sidebar="false" applyHtmlTag="false" applyBodyTag="false" docType="html-5.0">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en">
        <head>
            <meta charset="utf-8" />
            <meta http-equiv="x-ua-compatible" content="ie=edge" />
            <title>Image Recognization with Watson </title>
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <apex:slds />
            
        </head>
        <body>
            
            <div class="slds-scope">
                <div class="demo-only" style="padding: 0.5rem; background: rgb(51, 135, 133);">
                    <div class="slds-text-color_inverse-weak slds-text-heading_large slds-text-align_center"> Case Tone Analyzer </div>
                </div>
            </div>
            <div class="slds-scope">
                <div class="slds-grid">
                    <apex:repeat value="{!tones.utterances_tone}" var="cls">
                        <div class="slds-col">
                            <apex:repeat value="{!cls.tones}" var="cls1">
                                <div class="slds-page-header color-background-error-dark">
                                    <div class="slds-media__body">
                                        <p class="slds-text-body_small slds-line-height_reset">{!cls1.tone_name}</p>
                                        <p class="slds-text-body_small slds-line-height_reset">
                                            {!cls1.score}  
                                        </p>
                                    </div>
                                </div>
                            </apex:repeat>
                        </div>
                        
                    </apex:repeat>
                    
                </div>
            </div>
        </body>
    </html>
</apex:page>

 

 

 

 

 

 

Understand Customer Feeling from Case With IBM Watson

In this post, we are going to see how to use IBM Watson tone analyzer services understand the customer emotional, social, and language tones from the case descriptions. You can use IBM Waston services in many ways like understand the customer tone from Analyzing text marketing campaigns, Understanding the lead interested level, understand customer happiness from the case is few use cases. Let’s assume the case is coming from the web to lead with case subject and Description about the case . This post we are going to Predict whether they are happy, sad, confident, and more from the description an the subject.

What is Watson Tone Analyzer?

The IBM Watson Tone Analyzer service uses linguistic analysis to detect emotional, social, and language tones in written text. The service can analyze tone at both the document and sentence levels. You can use the service to understand how your written communications are perceived and then to improve the tone of your communications. Businesses can use the service to learn the tone of their customers’ communications and to respond to each customer appropriately or to understand and improve their customer conversations in general.You submit JSON, plain text, or HTML input that contains your written content to the service. The service returns JSON results that report the tone of your input. You can use these results to improve the perception and effectiveness of your communications, ensuring that your writing conveys the tone and style that you want for your intended audience. The following diagram shows the basic flow of calls to the service.

Submit content to the Tone Analyzer service and use the results to improve your communications.

1. Create Waston Service

To get started, one can just create an IBM login at https://console.ng.bluemix.net and create a service called “Tone Analyzer” as shown below.

Select the Service click on create a service to receive your credentials which are required to make an API call from the salesforce.

 

2. Create Named Credential in Salesforce

Create a named credential in Salesforce with the Tone Analyzer service credentials which you got them from the first step and you can use those in call out to IBM Watson services.

3. Simple Visualforce page.

That’s all. Here is the below Sample visualforce page that displays the customer emotions based on the case subject and description. The page shows the complete custom tone in different areas of the Emotions and Language styles and Social Tendencies.

4.Code Walkthrough

Here is the below piece of code that prepares the Json file to send the HTTP request to Watson services.

    JSONGenerator generator = JSON.createGenerator(true);
        generator.writeStartObject();
        generator.writeStringField('text', c.Subject+''+c.Description);
        generator.writeEndObject();

Below piece of code shows how to make the Http Call to IBM Watson tone services. We are using the Named Credentials with call out.

 HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:Bluemix_Tone_Analyser/v3/tone?version=2016-05-18');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(stringToJSON(c));
        Http http = new Http();
        HTTPResponse res = http.send(req);
        jsonData = res.getBody();

 

Below Piece of code is for the JSON parsing.

public Class ToneAnalysis {
        public DocumentTone document_tone {get; set;} 
    }
    
    public Class DocumentTone {
        public  List<ToneCategory> tone_categories {get; set;}
    }
    
    public Class ToneCategory {
        public  List<Tone> tones {get; set;}
        public  String category_id {get; set;}
        public  String category_name {get; set;}
    }
    
    public Class Tone {
        public  Double  score {get; set;}
        public  String tone_id {get; set;}
        public  String tone_name {get; set;}
    }

Here is the visual force page the show the result.

<div class="slds-scope">
                <div class="demo-only" style="padding: 0.5rem; background: rgb(51, 135, 133);">
                    <div class="slds-text-color_inverse-weak slds-text-heading_large slds-text-align_center"> Case Tone Analyzer </div>
                </div>
            </div>
            <div class="slds-scope">
                <div class="slds-grid">
                    <div class="slds-col">
                        <div class="slds-page-header">
                            <div class="slds-media__body">
                                <h1 class="slds-page-header__title slds-truncate slds-align-middle">Emotion</h1>
                                <p class="slds-text-body_small slds-line-height_reset">
                                    &lt; .5 = not likely present <br/> &gt; .5 = likely present <br/> &gt; .75 = very likely present <br/>
                                </p>
                            </div>
                        </div>
                    </div>
                    <div class="slds-col">
                        <div class="slds-page-header">
                            <div class="slds-media__body">
                                <h1 class="slds-page-header__title slds-truncate slds-align-middle">Language Style</h1>
                                <p class="slds-text-body_small slds-line-height_reset">
                                    &lt; .5 = not likely present <br/> &gt; .5 = likely present <br/> &gt; .75 = very likely present <br/>
                                </p>
                            </div>
                        </div>
                    </div>
                    <div class="slds-col">
                        <div class="slds-page-header">
                            <div class="slds-media__body">
                                <h1 class="slds-page-header__title slds-truncate slds-align-middle">Social Tendencies</h1>
                                <p class="slds-text-body_small slds-line-height_reset">
                                    &lt; .5 = not likely present <br/> &gt; .5 = likely present <br/> &gt; .75 = very likely present <br/>
                                </p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="slds-scope">
                <div class="slds-grid">
                    
                    <apex:repeat value="{!tones.document_tone.tone_categories}" var="cls">
                        <div class="slds-col">
                            <apex:repeat value="{!cls.tones}" var="cls1">
                                <div class="slds-page-header color-background-error-dark">
                                    <div class="slds-media__body">
                                        <p class="slds-text-body_small slds-line-height_reset">{!cls1.tone_name}</p>
                                        <p class="slds-text-body_small slds-line-height_reset">
                                            {!cls1.score}  
                                        </p>
                                    </div>
                                </div>
                            </apex:repeat>
                        </div>
                        
                    </apex:repeat>
                    
                </div>
            </div>

Here is the complete code

https://github.com/rajamohanvakati/Watson-Tone-Analyzer-

5.Conclusion

If you’d like help identifying how your customers are feeling, IBM Watson tone analyzer will help you to understand.