Month: November 2017

Live Agent Deployment API

Introduction

In this blog, I am going to explain how to use the live agent deployment API  to find and create records and how to customize chat buttons and chat window. Live agent deployment API has the number of options to customize the live agent like Logging and controlling the live agent online and offline behaviors and allow automatically creating records and suggest the knowledge article etc. Below is the code from where you will launch your live agent normally it might be your webpage or visual force page from sites etc.

<apex:page sidebar="false">
    <head>
        
        <style> body { margin: 25px 0 0 25px; } </style>
        
         
        
    </head>    
    <body>
        <!--Deployments-->
        <script type='text/javascript' src='https://c.la1-c1-iad.salesforceliveagent.com/content/g/js/41.0/deployment.js'></script>
        <!--Chat Buttons & Invitations -->
        <!--Customize Chat Buttons with the Deployment APIs-->
        
        <img id="liveagent_button_online_5736A000000gBrn" style="display: none; border: 0px none; cursor: pointer" 
             onclick="liveagent.startChat('5736A000000gBrn')" src="https://5dfg34-developer-edition.na50.force.com/resource/1505938566000/ttttteee__Chat_Agent_Online" />
        <img id="liveagent_button_offline_5736A000000gBrn" style="display: none; border: 0px none; " 
             src="https://5dfg34-developer-edition.na50.force.com/resource/1505938566000/ttttteee__Chat_Agent_Online" />
        <script type="text/javascript">
        if (!window._laq) { window._laq = []; }
        window._laq.push(function(){liveagent.showWhenOnline('5736A000000gBrn', document.getElementById('liveagent_button_online_5736A000000gBrn'));
                                    liveagent.showWhenOffline('5736A000000gBrn', document.getElementById('liveagent_button_offline_5736A000000gBrn'));
                                   });</script>
        
        <script type='text/javascript'>
        /* Adds a custom detail called Contact Email and sets it value to testuser@gmail.com */
        liveagent.addCustomDetail('Contact E-mail', 'testuser@gmail.com');
        
        /* Creates a custom detail called First Name and sets the value to test */
        liveagent.addCustomDetail('First Name', 'test');
        
        /* Creates a custom detail called Last Name and sets the value to user */
        liveagent.addCustomDetail('Last Name', 'user');
        
        /* Creates a custom detail called Phone Number and sets the value to 415-555-1212 */
        liveagent.addCustomDetail('Phone Number', '415-555-1212');
        
        /* An auto-query that searches Contacts whose Email field exactly matches 'testuser@gmail.com'. If no result is found, it will create a Contact record with the email, first name, last name, and phone number fields set to the custom detail values. */
        liveagent.findOrCreate('Contact').map('Email','Contact E-mail',true,true,true).map('FirstName','First Name',false,false,true).map('LastName','Last Name',false,false,true).map('Phone','Phone Number',false,false,true);
        
        /* The contact that's found or created will be saved or associated to the chat transcript. The contact will be opened for the agent in the Console and the case is linked to the contact record */
        liveagent.findOrCreate('Contact').saveToTranscript('ContactId').showOnCreate().linkToEntity('Case','ContactId');
        
        /* Creates a custom detail called Case Subject and sets the value to 'Refund policy for products' and will perform a knowledge search when the chat is accepted for the agent */
        liveagent.addCustomDetail('Case Subject','Refund policy for products').doKnowledgeSearch();
        
        /* Creates a custom detail called Case Status and sets the value to 'New' */
        liveagent.addCustomDetail('Case Status','New');
        
        /* This does a non-exact search on cases by the value of the 'Case Subject' custom detail If no results are found, it will create a case and set the case's subject and status.
The case that's found or created will be associated to the chat and the case will open in the Console for the agent when the chat is accepted */
        liveagent.findOrCreate('Case').map('Subject','Case Subject',true,false,true).map('Status','Case Status',false,false,true).saveToTranscript('CaseId').showOnCreate();
        
             liveagent.addCustomDetail('InquiryDetails', 'Suport').saveToTranscript('Inquiry_Details__c');

        /* For internal or technical details that don't concern the agent, set showToAgent to false to hide them from the display. */
        liveagent.addCustomDetail('VisitorHash', 'c6f440178d478e4326a1', false);
        
        /* Sets the display name of the visitor in the agent console when engaged in a chat */
        liveagent.setName('Test User');
        
        /* Sets the width of the chat window to 500px */
        liveagent.setChatWindowWidth(10);
        
        /* Sets the height of the chat window to 500px */
        liveagent.setChatWindowHeight(10);
        
        liveagent.init('https://d.la1-c1-iad.salesforceliveagent.com/chat', '5726A000000gPLj', '00D6A000000vnuz');
        liveagent.enableLogging();
        
        </script>
        
        
    </body>
    
    
</apex:page>

Understand the code

Live agent logging will be very useful if you wanted to troubleshoot the live agent. You can enable the Logging by simple liveagent.enableLogging(); the method which results in the debugging as shown below on browser console.

The below piece of code shown what to do when the agent is online or offline.The showWhenOnline or showWhenOffline method to specify customers see when a particular button is online or offline based on the agent status. the below code we specify the button id to show the status  liveagent_button_online_5736A000000gBrn , liveagent_button_offline_5736A000000gBrn  .

liveagent.showWhenOnline('5736A000000gBrn', document.getElementById('liveagent_button_online_5736A000000gBrn'));

liveagent.showWhenOffline('5736A000000gBrn', document.getElementById('liveagent_button_offline_5736A000000gBrn'));

The below code request a chat from a button in a new window when you click on chat button by calling liveagent.startChat method.

<img id="liveagent_button_online_5736A000000gBrn" style="display: none; border: 0px none; cursor: pointer" 
             onclick="liveagent.startChat('5736A000000gBrn')" src="https://5dfg34-developer-edition.na50.force.com/resource/1505938566000/ttttteee__Chat_Agent_Online" />

Find and Create Records
Use the Deployment API to search for or create Salesforce records like a case, contact, account, or lead automatically when an agent begins a chat with a customer.addCustomDetail methods as  Adds a new custom detail for the chat visitor.

   /* Adds a custom detail called Contact Email and sets it value to testuser@gmail.com */
        liveagent.addCustomDetail('Contact E-mail', 'testuser@gmail.com');
        
        /* Creates a custom detail called First Name and sets the value to test */
        liveagent.addCustomDetail('First Name', 'test');
        
        /* Creates a custom detail called Last Name and sets the value to user */
        liveagent.addCustomDetail('Last Name', 'user');
        
        /* Creates a custom detail called Phone Number and sets the value to 415-555-1212 */
        liveagent.addCustomDetail('Phone Number', '415-555-1212');

The Custom Detail is displayed to agents in the footer widget and in the Chat Details page in the Salesforce Console while the chat is active as shown below.

 

Use the findOrCreate method to find existing records or create new ones based on certain criteria. The findOrCreate method begins the API call that finds existing records or creates new records when an agent begins a
chat with a customer. The below code show to find and create records and store it to the live agent transcript and suggesting the knowledge articles.

  /* An auto-query that searches Contacts whose Email field exactly matches 'testuser@gmail.com'. If no result is found, it will create a Contact record with the email, first name, last name, and phone number fields set to the custom detail values. */
        liveagent.findOrCreate('Contact').map('Email','Contact E-mail',true,true,true).map('FirstName','First Name',false,false,true).map('LastName','Last Name',false,false,true).map('Phone','Phone Number',false,false,true);
        
        /* The contact that's found or created will be saved or associated to the chat transcript. The contact will be opened for the agent in the Console and the case is linked to the contact record */
        liveagent.findOrCreate('Contact').saveToTranscript('ContactId').showOnCreate().linkToEntity('Case','ContactId');
        
        /* Creates a custom detail called Case Subject and sets the value to 'Refund policy for products' and will perform a knowledge search when the chat is accepted for the agent */
        liveagent.addCustomDetail('Case Subject','Refund policy for products').doKnowledgeSearch();
        
        /* Creates a custom detail called Case Status and sets the value to 'New' */
        liveagent.addCustomDetail('Case Status','New');
        
        /* This does a non-exact search on cases by the value of the 'Case Subject' custom detail If no results are found, it will create a case and set the case's subject and status.
The case that's found or created will be associated to the chat and the case will open in the Console for the agent when the chat is accepted */
        liveagent.findOrCreate('Case').map('Subject','Case Subject',true,false,true).map('Status','Case Status',false,false,true).saveToTranscript('CaseId').showOnCreate();
        
        /* Saves the custom detail to a custom field on LiveChatTranscript at the end of a chat.  Assumes a custom field called Company__c was added to the Live Chat Transcript object */
        liveagent.addCustomDetail('InquiryDetails', 'Suport').saveToTranscript('Inquiry_Details__c');

In the above code, we are trying o find the contact and if not available the create a new contact also searches for records that contain customer data specified by the addCustomDetail Deployment API method.  findOrCreate.saveToTranscript method to save the record you find or create the chat transcript associated
with the chat. Use the findOrCreate.showOnCreate method to automatically open the record you create in a subtab in the Salesforce console.   findOrCreate.linkToEntity method to link the record you found or created to another record type. The below image shows the search results on the console chat

 

liveagent.addCustomDetail(‘Case Subject’,’Refund policy for products’).doKnowledgeSearch() method search for Knowledge articles as shown below when customer is chat with agent.

 

 

 

Live agent Pre-Chat Forms with Validations

Introduction

In this post, I am going to explain how to set Pre-Chat form to collect information from visitors and customers the pre-chat page as well.Pre-chat information can help direct chat requests more efficiently and reduce the time agents spend collecting the information themselves to resolve the cases.

Understand Pre Chat API 

Use the Pre-Chat API to search for or create customer records automatically when a customer completes a pre-chat form. Here is the list of methods that you can use in pre-chat API

findOrCreate.map
      Searches for or creates records that contain the customer data that’s specified in the pre-chat form that the customer completes. You can call the findOrCreate.map method as many times as necessary to find the appropriate records. You can list multiple fields and their corresponding details to map the detail values to the appropriate fields within the record as shown below .Here findOrCreate.map is maps the contact first name and last name with pre-chat form first name and last name.

 <input type="hidden" name="liveagent.prechat.findorcreate.map:Contact"
               value="FirstName,FirstName;LastName,LastName;Email,Email;Phone,Phone"
               />
        <input type="hidden" name="liveagent.prechat.findorcreate.map:Case"
               value="Subject,chatReason;Description,TopicDetails"
               />

 

findOrCreate.map.doFind

Use the findOrCreate.map.doFind method to specify which fields to search against existing customer records when a customer completes a pre-chat form.Here is the code that searches the contact based on the pre-chat form email.

   <input type="hidden" name="liveagent.prechat.findorcreate.map.doFind:Contact"
               value="Email,true" />

findOrCreate.map.isExactMatch

Specifies which fields in your findOrCreate.map method require an exact field value match when you search for existing records.

 <input type="hidden" name="liveagent.prechat.findorcreate.map.isExactMatch:Contact"
               value="Email,true" />

findOrCreate.map.doCreate

Use the findOrCreate.map.doCreate method to specify which fields in findOrCreate.map method to use to create a new record if an existing record isn’t found. Specifies which fields in your findOrCreate.map method to use to create a new record if an existing record isn’t found. You can specify one or more fields for creating new records.

<input type="hidden" name="liveagent.prechat.findorcreate.map.doCreate:Contact"
               value="FirstName,true;LastName,true;Email,true;Phone,true" />

findOrCreate.saveToTranscript

Use the findOrCreate.saveToTranscript method to find or create a record and save it to the chat transcript associated with the chatSaves the record that you found or created using the findOrCreate.map.doCreate or findOrCreate.map.doFind
Pre-Chat API methods to the chat transcript associated with the chat when the chat ends.

 <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Contact"
               value="ContactId" />
        <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Case"
               value="CaseId" />

 

findOrCreate.showOnCreate

Use the findOrCreate.showOnCreate method to find or create a record and automatically open it in a subtab in the Salesforce console.Opens the record you created using the findOrCreate.map.doCreate and findOrCreate.map.doFind Pre-Chat API methods automatically in a subtab in the to the Salesforce console.

 <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Contact" value="true"
               />
        <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Case" value="true"
               />

findOrCreate.linkToEntity

Links the record you’ve found or created using the findOrCreate.map.doFind and findOrCreate.map.doCreate methods to another record of a different record type that you created using a separate findOrCreate.map API call. For example,
you can link a case record you found within your organization to a contact record you create. The findOrCreate.linkToEntity method can’t be used to populate fields on records that you create by using the findOrCreate API call. Instead, use the findOrCreate.map method to update field values on records.

  <input type="hidden" name="liveagent.prechat.findorcreate.linkToEntity:Contact"
               value="Case,ContactId" />

Code 

Here is the complete visualforce page. Go to developer edition and create a new visualforce page with the below code.

<apex:page showHeader="false" standardStylesheets="false" sidebar="false" title="GoBank Customer Care" cache="false">
    
    <apex:stylesheet value="{!URLFOR($Resource.LiveAgentCustomResources,'/css/style.css')}"/>
    <apex:includescript value="{!URLFOR($Resource.LiveAgentCustomResources,'/js/jquery-1.6.2.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.jQuery, '/jQuery/script/jquery.validate.min.js')}"/>
    <style>
        input
        {
        background: none repeat scroll 0 0 #EAEEF0;
        border: medium none;
        border-radius: 5px 5px 5px 5px;
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
        color: #000000;
        font-family: Helvetica;
        font-size: 12px;
        height: 30px;
        line-height: 30px;
        padding: 0 5px;
        position: relative;
        text-align: left;
        width: 302px;
        }
        
        .error {
        color:red !important;
        }
        
        select {
        box-shadow: none;
        line-height: 31px;
        font-size: 13px;
        border: 1px solid #B0B0B0;
        border-radius: 5px 5px 5px 5px;
        height: 30px;
        padding: 4px 5px;
        width: 643px;
        background: url(../img/select-BG.png) repeat-x;
        }
        
        .input-area {
        margin-bottom: 10px;
        }
        
        .input-area li {
        display: inline;
        position:relative;
        margin-right:15px;
        }
        
        .input-area li.last-child 
        {
        margin-right: 0 !important;
        }
        
        
    </style>
    
    <script type="text/javascript">
    (function() { function handlePageLoad() {
        var endpointMatcher = new RegExp("[\\?\\&]endpoint=([^&#]*)");
        document.getElementById('prechatForm').setAttribute('action',
                                                            decodeURIComponent(endpointMatcher.exec(document.location.search)[1]));
    } if (window.addEventListener) {
        window.addEventListener('load', handlePageLoad, false);
    } else { window.attachEvent('onload', handlePageLoad, false);
           }})();
    
    
    function submitform()
    { 
        $('#prechatForm').submit();
    }   
    $.validator.addMethod("valueNotEquals", function(value, element, arg) {   
        if($('[id$="LastName"]').val() != '' && $('[id$="FirstName"]').val() != '' && $('[id$="TopicDetails"]').val() != '' && $('[id$="Email"]').val() != '' && $('[id$="Phone"]').val() != '') 
        {
            return arg != value; 
        }
        else
        {
            return true;
        }               
    }, " ");
    
    $(document).ready(function(){  
        $('select').change(function() {                                                     
            validateNextButton();
        });
        
        $('textarea').change(function() {              
            validateNextButton();
        });
        
        
        
        
        
        $('[id$="prechatForm"]').validate({
            
            errorClass : "error",
            errorPlacement : function(error, element) {
                error.appendTo(element.parent().parent());
            },
            onkeyup : false,
            ignore : ':hidden'
            
        });      
        
        $('input[id$="FirstName"]').rules("add", {
            required : true,
            minlength : 2,
            messages : {
                required : " First Name is Required "
            }
        });                  
        
        $('input[id$="LastName"]').rules("add", {
            required : true,
            minlength : 2,
            messages : {
                required : "Last Name is Required "
            }
        }); 
        
        $('input[id$="Email"]').rules("add", {
            required : true,
            messages : {
                required : " Please Enter email "
            }
        }); 
        $('input[id$="Phone"]').rules("add", {
            required : true,
            messages : {
                required : " Please Enter email"
            }
        }); 
        $('select[id$="Topics"]').rules("add", { 
            valueNotEquals: 'chat topic',   
            messages : {
                valueNotEquals : "Please select a topic."
            }
        });  
        
        $('textarea[id$="TopicDetails"]').rules("add", {
            required : true,
            minlength : 10,
            messages : {
                required : " Please enter the details about chat  "
            }
        });  
        
        
    });
    
    function validateNextButton()
    {  
        if ($('[id$="prechatForm"]').valid())
        {               
            $("#sendButton").removeAttr("disabled", "disabled").addClass("button-on").removeClass("button-off");
        }
        else $("#sendButton").attr("disabled", "disabled").addClass("button-off").removeClass("button-on");
        
    }       
    
    function detailsClick(e,elm){
        var remainingChar =  255 -(elm.value.length);
        if(remainingChar >= 0){
            document.getElementById('charCount').value = remainingChar;
        }else{
            elm.value = elm.value.substring(0,255);
            document.getElementById('charCount').value = 0;          
            return false;
        }    
        return true; 
    }      
    
    </script>
    
    <div id="outerDiv" style="overflow:auto;">
        
        <div class="inner-box">
            <ul class="inner-box-header">
                
                <li class="h3-container">
                    <h3>Pre chat Window</h3>
                </li>
                
                
            </ul>
            <form method='post' id='prechatForm'>
                <div class="inner-box-content">
                    <table class="input-area">
                        <tr>
                            <td>       
                                <ul class="input-area">
                                    <li>
                                        <input type="text" name="liveagent.prechat:Firstname"  id="FirstName" maxlength="35"  placeholder="First Name" />
                                    </li>          
                                </ul>
                            </td>
                            <td>  
                                <ul class="input-area">
                                    <li class="last-child">  
                                        <input type="text" name="liveagent.prechat:Lastname"  id="LastName" maxlength="35" placeholder="last name"/>
                                    </li>          
                                </ul>
                            </td>          
                        </tr>
                        <tr>
                            <td>       
                                <ul class="input-area">
                                    <li>
                                        <input type="email" name="liveagent.prechat:Email"  id="Email" maxlength="100" placeholder="Email"/>
                                    </li>          
                                </ul>
                            </td>
                            <td>  
                                <ul class="input-area">
                                    <li class="last-child">  
                                        <input type="phone" name="liveagent.prechat:Phone"  id="Phone" maxlength="12" placeholder="Phone"/>
                                    </li>          
                                </ul>
                            </td>          
                        </tr>
                        
                    </table>
                    <div>
                        <div class="requiredInput">
                            <select name="liveagent.prechat:ChatReason" title="Please select a Topic" class="req" id="chatReason">
                                <option value="chat topic">Support On Installation</option>
                                <option value="Join GoBank">Knowledge Article</option>
                                <option value="Debit Cards">Service Maintaince</option>
                                <option value="Debit Cards">Refund policy for products</option>
                                <option value="Features">Features</option>
                                <option value="Feedback">Feedback</option>
                            </select>
                        </div></div>
                    <div class="textarea topic-container">
                        <div class="requiredInput">
                            <textarea id="TopicDetails" class="req" cols="60" data-val="true" maxlength="500" minlength="10" 
                                      name="liveagent.prechat:InquiryDetails" rows="3" style="resize: none;"
                                      onmouseout="detailsClick(event, this);" onkeydown="detailsClick(event,this);"></textarea> 
                            <label class="infield topic-label" for="TopicDetails">details</label>
                        </div>
                        <p class="charsRemaining">Characters Remaining: <input type="text" readonly="readonly" id="charCount" style="width:50px" value="255"/></p>
                    </div>
                    <ul class="chat-buttons send-button">
                        <li class="submit-button"><a id="sendButton" href="javascript: submitform()" class="button-off anton" title="send">Send</a></li>
                    </ul>
                </div>
                
                
                <!-- Pre Chat infomration to agent -->
                
                <input type="hidden" name="liveagent.prechat.Firstname" id="FirstName" />
                <input type="hidden" name="liveagent.prechat.Lastname" id="LastName" />
                <input type="hidden" name="liveagent.prechat.Email" id="Email" />
                <input type="hidden" name="liveagent.prechat.Phone" id="Phone" />
                <input type="hidden" name="liveagent.precht.ChatReason" id="chatReason" />
                <input type="hidden" name="liveagent.prechat.InquiryDetails" id="TopicDetails" />
                
                 <input type="hidden" name="liveagent.prechat.findorcreate.map:Contact"
                       value="FirstName,FirstName;LastName,LastName;Email,Email;Phone,Phone"
                       />
                <input type="hidden" name="liveagent.prechat.findorcreate.map:Case"
                       value="Subject,chatReason;Description,TopicDetails"
                       />
                
                <input type="hidden" name="liveagent.prechat.findorcreate.map.doFind:Contact"
                       value="Email,true" />
                <input type="hidden" name="liveagent.prechat.findorcreate.map.isExactMatch:Contact"
                       value="Email,true" />
                <input type="hidden" name="liveagent.prechat.findorcreate.map.doCreate:Contact"
                       value="FirstName,true;LastName,true;Email,true;Phone,true" />
                
                
                <input type="hidden" name="liveagent.prechat.findorcreate.linkToEntity:Contact"
                       value="Case,ContactId" />
 
                <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Contact" value="true"
                       />
                <input type="hidden" name="liveagent.prechat.findorcreate.showOnCreate:Case" value="true"
                       />
 
                <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Contact"
                       value="ContactId" />
                <input type="hidden" name="liveagent.prechat.findorcreate.saveToTranscript:Case"
                       value="CaseId" />
              
                <input type="hidden" name="liveagent.prechat.knowledgeSearch:CaseSubject" value="true" />
                
                
                
            </form>
        </div>
         
    </div>
    
</apex:page>

Update Chat Buttons and Automated Invitations

Update the live agent chat buttons with the visualforce page that you created above as shown below.

Now if you launch the chat from the site you can able to pre-chat form that will pop up before starting the chat.

Here is result agent can see before accepting the chat.

Based on your the above pre-chat form configuration once the agent is accepting the chat salesforce is going to do the bunch of operations like searching the contacts and opening a new record creating the page and suggest the knowledge article and save it to chat transactions and etc.

 

Salesforce Live Agent Custom Chat Window

This is simple live agent custom chat window using the visualforce. Create a new visualforce page with below code.

<apex:page showHeader="false" standardStylesheets="false" cache="false">
    <!-- Add custom CSS here -->
    <apex:includescript value="{!URLFOR($Resource.LiveAgentCustomResources,'/js/jquery-1.6.2.min.js')}" />
    <meta id="pageViewport" name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width"/> 
    <style type="text/css">
        .clear {
        clear: both;
        }
        
        .inner-box {
        background-color: #FFFFFF;
        border-radius: 10px 10px 10px 10px;
        box-shadow: 0 2px 1px #C9C9C9;
        display: block;
        padding: 0;
        width: 684px;
        margin: 0 auto 80px auto;
        overflow: visible;
        z-index: 1;
        padding: 0 20px 20px;
        position: relative;
        height: 600px;
        
        }
        
        .chat-buttons{
        list-style:none !important;
        }
        
        .inner-box-header h3 {
        font-family: DINMedium;
        font-size: 2.5em;
        color: #44Af51;
        font-weight: normal;
        margin:0;
        line-height:40px;
        text-align:center;
        }
        
        .button-on {
        background: #00bbce url(../img/button-BG.png) repeat-x;
        border: 1px solid #7B8589;
        border-radius: 5px;
        color: #FFFFFF !important;
        cursor: pointer;
        float: right;
        font-family: DINBold, helvetica, arial;
        font-size: 14px;
        letter-spacing: 0.01em;
        margin-top: 8px;
        min-width: 5px;
        overflow: hidden;
        padding: 5px 22px 7px 22px;
        position: relative;
        text-decoration: none;
        text-shadow: 0 -1px #838889;
        text-transform: uppercase;
        width: auto;
        }
        
        .button-off {
        background: #CCCCCC url(../img/button-grey-BG.png) repeat-x;
        border: 1px solid #CCCCCC;
        border-radius: 5px;
        color: #FFFFFF !important;
        pointer-events: none;
        cursor: default;
        float: right;
        font-family: DINBold, helvetica, arial;
        font-size: 14px;
        letter-spacing: 0.01em;
        margin-top: 8px;
        min-width: 5px;
        overflow: hidden;
        padding: 5px 22px 7px 22px;
        position: relative;
        text-decoration: none;
        text-shadow: 0 -1px #CCCCCC;
        text-transform: uppercase;
        width: auto;
        }
        
        
        input
        {
        background: none repeat scroll 0 0 #EAEEF0;
        border: medium none;
        border-radius: 5px 5px 5px 5px;
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
        color: #000000;
        font-family: Helvetica;
        font-size: 12px;
        height: 30px;
        line-height: 30px;
        padding: 0 14px;
        position: relative;
        text-align: left;
        width: 95%;
        }
        
        .loader-container p 
        {
        font-size: 14px;
        color: #444f51;
        font-family: helvetica;
        margin-top: 20px;
        }
        
        body {
        background: none !important;
        font-family: sans-serif !important;
        font-variant: all-petite-caps !important;
        font-weight: bold !important;
        background-color: #aab3b3 !important;
        font-style: italic !important;
        }
        
        
        .button-on {
        border: 1px solid #7B8589;
        border-radius: 5px;
        color: #FFFFFF !important;
        cursor: pointer;
        float: right;
        font-family: DINBold, helvetica, arial;
        
        }
        
        .button-off {
        border: 1px solid #CCCCCC; */
        color: #FFFFFF !important;
        pointer-events: none;
        float: right;
        margin-top: 8px;
        padding: 5px 22px 7px 22px;
        }
        .loader
        {
        width: 128px;
        height: 128px;
        background: url({!URLFOR($Resource.LiveAgentCustomResources,'/img/loader.png')}) top left no-repeat; 
        margin: 0 auto;
        }
        .loader-container p {
        text-align: center;
        }
        .loader-container 
        {
        padding-top: 50px;
        }           
        
        
        .container {
        border: 2px solid #dedede;
        background-color: #F8F8FF;
        border-radius: 5px;
        padding: 10px;
        margin: 10px 0;
        list-style:none
        
        }
        
        .darker {
        border-color: #ccc;
        background-color: #ddd;
        text-align: right;
        }
        
        .container::after {
        content: "";
        clear: both;
        display: table;
        }
        
        .container img {
        float: left;
        max-width: 60px;
        width: 100%;
        margin-right: 20px;
        border-radius: 50%;
        }
        
        .container img.right {
        float: right;
        margin-left: 20px;
        margin-right:0;
        }
        
        
    </style>
    <!-- Top header box -->
    
    <div class="inner-box">
        <ul class="inner-box-header">
            
            <h3>Custom Chat Window </h3>
            
        </ul>
        
        <div class="inner-box-content">
            
            <liveAgent:clientchat >
                
                <liveAgent:clientChatMessages />
                
                <div class="loader-container">
                    <div id="waitingMessage"  class="loader" style="background-position: -2560px 0%; ">
                    </div>
                    <p>Please wait for the agent to accept the chat.</p>
                </div>                 
                
                <liveAgent:clientChatLog />
                
                <div id="chatInput">             
                    <div class="textarea message-container" style="display: none;">
                        <liveagent:clientChatInput id="message" />
                        <label class="infield" for="{!$Component.message}" style="opacity: 0; display: none; word-wrap:break-word;">type your message here</label>
                        
                    </div>
                    <liveAgent:clientChatQueuePosition/>
                    <ul class="chat-buttons">
                        <li class="send-button"><liveAgent:clientChatSendButton id="sendButton" label="Send"/></li>
                        <li class="end-button"><liveAgent:clientChatEndButton id="endButton" label="End chat"/></li>
                    </ul>                               
                </div>
                
            </liveAgent:clientchat>
        </div> 
        
    </div>
    <div class="clear"></div>
    <apex:includescript value="{!URLFOR($Resource.LiveAgentCustomResources,'/js/jquery.spritely-0.6.1.js')}" />
    <script type="text/javascript"> 
    
    
    
    
    $(document).ready(function(){       
        
        $('.loader').sprite({fps: 12, no_of_frames: 47});
        window.elementInQuestion = $('#liveAgentClientChat');
        
        var hasLiveAgentState = false;
        var hasLiveAgentStateEnded = false;
        
        function rewriteChatText(){
            $('#liveAgentChatLogText').children().each(function(){
                if( $(this).hasClass('operator') ){
                    $myname = $(this).html().match(/<strong>(.*?)<\/strong>/)[1];
                    $mymessage = $(this).html().replace(/<strong>(.*?)<\/strong>/,'').replace(/<STRONG>(.*?)<\/STRONG>/,'');
                    $newItem = $('<li class="container">' + $myname + '--' + $mymessage + '</li>');                       
                    $(this).after($newItem).remove();
                    $("div.chat-container").scrollTop(1000000);  
                }else if( $(this).hasClass('client') ){
                    $mymessage = $(this).html().replace(/<strong>(.*?)<\/strong>/,'').replace(/<STRONG>(.*?)<\/STRONG>/,'');  
                    $newItem = $('<li class="container darker">' +'<b>You :</b>'+ $mymessage + '</li>');                        
                    $(this).after($newItem).remove();
                    $("div.chat-container").scrollTop(1000000);  
                }
            });  
            
        }
        function checkClass(){
            
            if (window.elementInQuestion.hasClass('liveAgentState') && !hasLiveAgentState) {
                $(document).trigger('elementLiveAgentState');
                hasLiveAgentState = true;
            }
            if (window.elementInQuestion.hasClass('liveAgentStateEnded') && !hasLiveAgentStateEnded) {
                $(document).trigger('elementLiveAgentStateEnded');
                clearInterval(window.classCheckerInterval);
                hasLiveAgentStateEnded = true;
            }
            
        }
        
        window.classCheckerInterval = setInterval(checkClass, 100);
        window.classCheckerInterval = setInterval(rewriteChatText, 100);
        
        $(document).bind('elementLiveAgentStateEnded', function(){
            $('.chat-buttons').hide();
            $('.loader-container').hide();
            $('.textarea.message-container').hide();
        });
        
        $(document).bind('elementLiveAgentState', function(){
            $('.loader-container').hide();
            
            $('#liveAgentChatLog').removeClass("liveAgentChatElement");
            $('#liveAgentChatLog').addClass("chat-container");
            $('#liveAgentChatLog').css("border", "none");
            $('#liveAgentChatLog').css("height", "410px");               
            
            $('#liveAgentChatLogText').addClass("chat-container");              
            
            $('.textarea.message-container').css("display","");
            $input = $("#liveAgentChatInput");
            $input.attr("style", "display: block; resize: none; width: 629px; background: #F8F8FF; border-radius: 5px; height: 48px; border: 1px solid #0000FF; padding: 5px; font-size: 15px;");
            $sendButton = $('span[id$="sendButton"]');
            $newSendButton = $('<a href="javascript:SfdcApp.LiveAgent.Chasitor.sendMessage();"  class="button-on"  title="send">Send</a>');  
            $sendButton.after($newSendButton).remove();             
            $endButton = $('span[id$="endButton"]');
            $newEndButton = $('<a href="javascript:SfdcApp.LiveAgent.Chasitor.endChat();" class="button-off"   title="Cancel">End chat</a>');
            $endButton.after($newEndButton).remove().wrapAll('<div class="buttonsRow"/>');;     
            
        });
    });    
    </script> 
</apex:page>

Add it the Chat buttons and automated invitation as shown below.

You can see the chat window as shown below

 

 

 

 

 

Live Agent post chat page

Live agent post chat page allows you to share the details with customers at the end of a chat session. For example, you can direct your customers to another
Web page after they complete a chat with an agent, or forward them to a survey about their chat experience. You can create a Visualforce page to host your post-chat page, or you can develop a page on your own and add the URL to your chat
button configuration.

<apex:page showHeader='false'>
    <div id='details'>
        <!-- This will present all the post chat parameters available to this page -->
        <h1>Post Chat Page</h1>
        <p>
            <!-- These variables are passed to the post-chat page and can be used to
customize your post-chat experience -->
            Request Time: <apex:outputText id='c_rt'
                                           value='{!$CurrentPage.parameters.requestTime}' /><br/>
            Start Time: <apex:outputText id='c_st'
                                         value='{!$CurrentPage.parameters.startTime}' /><br/>
            Deployment Id: <apex:outputText
                                            value='{!$CurrentPage.parameters.deploymentId}' /><br/>
            Button Id: <apex:outputText value='{!$CurrentPage.parameters.buttonId}'
                                        /><br/>
            Chat Key: <apex:outputText value='{!$CurrentPage.parameters.chatKey}'
                                       /><br />
            Last Visited Page: <apex:outputText
                                                value='{!$CurrentPage.parameters.lastVisitedPage}' /><br/>
            Original Referrer: <apex:outputText
                                                value='{!$CurrentPage.parameters.originalReferrer}' /><br/>
            <!-- When the GeoLocation is not available this will appear as Unknown
-->
            Latitude: <apex:outputText value='{!$CurrentPage.parameters.latitude}'
                                       /><br/>
            Longitude: <apex:outputText value='{!$CurrentPage.parameters.longitude}'
                                        /><br/>
            City: <apex:outputText value='{!$CurrentPage.parameters.city}' /><br/>
            Region: <apex:outputText value='{!$CurrentPage.parameters.region}' /><br/>
            Country: <apex:outputText value='{!$CurrentPage.parameters.country}'
                                      /><br/>
            <!-- End of GeoLocation information -->
            Organization: <apex:outputText
                                           value='{!$CurrentPage.parameters.organization}' /><br/>
            Disconnected By: <apex:outputText
                                              value='{!$CurrentPage.parameters.disconnectedBy}' /><br/>
            Window Language: <apex:outputText
                                              value='{!$CurrentPage.parameters.windowLanguage}' /><br/>
            Chat Details: <apex:outputText
                                           value='{!$CurrentPage.parameters.chatDetails}' /><br />
            Transcript: <apex:outputText value='{!$CurrentPage.parameters.transcript}'
                                         /><br/>
            Attached Records : <apex:outputText
                                                value='{!$CurrentPage.parameters.attachedRecords}' /><br />
            Error: <apex:outputText value='{!$CurrentPage.parameters.error}' /><br
                                                                                   />
        </p>
    </div>
    <hr/>
    <!-- Message to show if chat is abandoned -->
    <div id='abandoned' style='display: none;'>
        We are sorry you decided to leave the chat. Feel free to initiate a new session.
    </div>
    <!-- Code to decide if we show the abandoned block or the full data -->
    <script type='text/javascript'>
    var requestTime = '{!$CurrentPage.parameters.requestTime}';
    var startTime = '{!$CurrentPage.parameters.startTime}';
    // when startTime doesn't have a value, it means the chat never started
    if (!startTime) {
        document.getElementById('details').style.display = 'none';
        document.getElementById('abandoned').style.display = 'block';
    }
    </script>
</apex:page>

Now go and update the chat button and automated invitations”post chat page ” as shown below with the visual force page your created.

Once chat is ended which will display the result as shown below.insted of showing the simple chat details even you can build your own logic like sending automatic post chat surveys or feedback etc by using post chat pages.

Salesforce Live Agent

Introduction

In this blog, I am going to explain Live agent set up in Salesforce. Live Agent is a comprehensive chat solution that makes it easy for your support organization’s agents and support supervisors to assist customers. With Live Agent, your support organization can leverage the comprehensive customer service tools that are available in the Salesforce console while providing real-time chat support.Before starting the customizing the live agent, let us make your org is ready for the live agent.

Enabled Live Agent
The Live agent is not enabled by default. So you need to enable it.From Setup enter Live Agent Settings in the Quick Find box, then select Live Agent Settings and enable it.

Create Live Agent Users

Before your users can assist customers with chat, you need to assign the users as Live Agent users. Live Agent users are supported agents and supervisors who have the Salesforce permissions to assist customers with chat. Go to salesforce user record and edit then Select Live Agent User and save it as shown below.

Static Resource 

Download any two images and upload them to static resource to use them to show the online and offline status of the chat

Let’s Get Started 

Now you can start configuring the live agent in your Org after completing the above configurations. Here are the details explain about how to configure the live agent.

1.Creating Skills

Skills identify your agents’ areas of expertise like “Repair ” or “Product installation” or “Maintenance” and etc are the few examples. When you assign an agent to a skill, that agent receives chat requests that are related to the agent’s skill areas. You can also empower your supervisors to assign skills to agents.

 

2. Live Agent Configurations

With the live agent configuration settings, you can able to control the functionality that’s available to agents and their supervisors while agents chat with customers. Apply settings when you create or edit a Live Agent configuration. Live Agent configurations define the Live Agent functionality that’s available to your agents and support supervisors when agents chat with customers.You can create multiple configurations that define Live Agent’s functionality for multiple types of users to fit into your business model. From Setup enter Live Agent Configurations in the Quick
Find box, then select Live Agent Configurations and create a new live agent configurations as shown below under Basic Information.

  • Chat Capacity Indicates how many chats an agent who is
    assigned to this configuration can be engaged in at the same time
  • Sneak Peek Enabled Indicates whether agents can see what a chat customer is typing before the customer sends a chat message.
  • Request Sound Enabled, Disconnect Sound Enabled, Notifications Enabled are Indicates whether to play an audio alert when new chat is started or ended
  • Custom Agent Name Sets the agent’s name as it appears to customers in the chat window.
  • Auto Greeting Sets a customized greeting message that the customer receives automatically when an agent accepts the customer’s chat request
  • Auto-Away on Decline Sets the agent’s Live Agent status to “Away” automatically when the agent declines a chat request
  • Auto-Away on Push Time-Out Sets an agent’s Live Agent status to “Away” automatically when a chat request that’s been pushed to the agent times out
  • Critical Wait Alert Time Determines the number of seconds that the agent has to answer a customer’s chat before the chat tab alerts the agent to answer it.
  • Agent File Transfer Enabled Indicates whether an agent can enable customers to transfer files through a chat
  • Visitor Blocking Enabled Indicates whether an agent can block visitors from an active chat within the Salesforce console
  • Assistance Flag Enabled Indicates whether an agent can send a request for help to a supervisor.

 

Assign eligible users to the configuration to give them access to Live Agent functionality.Users can be assigned to only one Live Agent configuration at a time. If you assign the same user to a second Live Agent configuration, the system removes that user from the first Live Agent configuration without warning you. 

Supervisor settings determine the Live Agent functionality that’s available to support supervisors. In addition, these settings determine the default filters that apply to the Agent Status list in the supervisory panel.

  • Chat Monitoring Enabled Indicates whether supervisors can monitor their agents’ chats in real-time while their agents interact with customers
  • Whisper Messages Enabled Indicates whether supervisors can send private messages to agents while agents chat with customers
  • Agent Sneak Peek Enabled Indicates whether supervisors can preview an agent’s chat messages before the agent sends them to the customer
  • Default Agent Status Filter Determines the default agent status, such as Online, Offline, or Away, by which to filter agents in the supervisor panel
  • Default Skill Filter Determines the default skill by which to filter agents in the supervisor panel.
  • Default Button Filter Determines the default button by which to filter agents in the supervisor panel.
  • Assigned Skills Determines the skills that are visible to supervisors in the supervisor panel.

Chat Conference Settings Determine whether agents can invite other agents to join them in a customer chat. Chat conferencing lets your agents include multiple
agents in a single chat.

  • Chat Transfer to Agents Enabled Indicates whether agents can transfer chats to another agent directly
  • Chat Transfer to Skills Enabled Indicates whether agents can transfer chats to agents assigned to a particular skill
  • Chat Transfer to Skills Determines the skill groups to which agents can transfer chats.
  • Chat Transfer to Live Chat Buttons Enabled Indicates whether agents can transfer chats to a button or queue
  • Chat Transfer to Live Chat Buttons Determines the buttons to which agents can transfer chats.
3. Live Agent Deployments

With the deployment, you will get of JavaScript to add it to your site. A deployment is a place on your company’s website that’s enabled for Live Agent. Create deployments to implement Live Agent and control its functionality on your website.To customize the chat window that your customers see, you first need to create a Force.com site to host your custom images. Your organization
can have a single Live Agent deployment or multiple deployments. For example, if you have a single service center that supports multiple websites, creating a separate deployment for each site enables you to present multiple chat windows to your visitors. From Setup in Salesforce Classic, enter Deployments in the Quick Find box, then select Deployments and Click New and  Save it .

After you saving Salesforce generates the deployment code as shown in the below image. Copy the deployment code, and then paste it on each Web page where you want to deploy ( visualforce Page in this example ).

4.Chat Buttons

Create chat buttons to enable customers to request a chat with an agent directly from your website.You need to create the buttons that visitors click to start chats. Like a deployment, a button consists of several lines of JavaScript that you copy and paste into Web pages.  From Setup enter Chat Buttons in the Quick Find box, then select Chat Buttons & Invitations to create a New then Select Chat Button from the Type field.

  • Enable Customer Time-Out Indicates whether chats are ended if the customer doesn’t respond within a specified period.
  • Customer Time-Out (seconds) Sets the amount of time that a customer has to respond to an agent message before the session ends
  • Customer Time-Out Warning Sets the amount of time that a customer has to respond to an agent message before a warning appears and a timer begins a countdown

  • Routing Type Sets how chats are routed to an agent.
  • Push Time-Out (seconds) Sets the amount of time an agent has to answer a chat request before the request is rerouted to another agent.
  • Enable Queue Indicates that queueing is enabled. Queueing allows incoming chat requests to wait in a queue until an agent with the appropriate skills is available to accept the chat.
  • Queue Size Per Agent Determines the queue’s capacity to hold chat requests per available agent. For Live Agent routing or when chats have a size of 1, this is the number of chats allowed to queue for each agent.
  • Overall Queue Size Lets a chat request that’s been declined by all available agents be rerouted and sent to all available agents again. Available only for requests with Least Active and Most Available routing types
  • Automatically Accept Chats Lets chat requests originating from this button be automatically accepted by the first available agent
  • Site for Resources Determines the Force.com site that’s associated with the chat button
  • Online Image Sets the custom button graphic that appears when the chat button is unavailable
  • Offline Image Sets the custom button graphic that appears when the chat button is available for customers to request new chats.
  • Custom Chat Page Replaces the standard Live Agent chat window with a custom chat window page that you’ve developed.
  • Pre-Chat Form Page Directs Live Agent to the Force.com page that hosts your customized pre-chat form that customers see before they begin
    a chat with an agent.
  • Pre-Chat Form URL Directs Live Agent to the URL of the Web page that hosts your pre-chat form.
  • Post-Chat Page Directs Live Agent to your customized post-chat page that customers see after they complete a chat
  • Post-Chat Page URL Directs Live Agent to the URL of the Web page that hosts your post-chat page.

Now Copy the button code, and then paste it on each Web page where you’ve deployed Live Agent ( Visualforce page in this example )

Now create a visualforce page with the script which you got from the Chat buttons and deployments as shown below

<apex:page >
    <head>
        
        
    </head>    
    <body>
        <!--Deployments-->
        <script type='text/javascript' src='https://c.la1-c1-iad.salesforceliveagent.com/content/g/js/41.0/deployment.js'></script>
        <script type='text/javascript'>
            liveagent.init('https://d.la1-c1-iad.salesforceliveagent.com/chat', '5726A000000gPLj', '00D6A000000vnuz');
        </script>
        <!--Chat Buttons & Invitations -->
        
        <img id="liveagent_button_online_5736A000000gBrn" style="display: none; border: 0px none; cursor: pointer" onclick="liveagent.startChat('5736A000000gBrn')" src="https://5dfg34-developer-edition.na50.force.com/resource/1505938566000/ttttteee__Chat_Agent_Online" /><img id="liveagent_button_offline_5736A000000gBrn" style="display: none; border: 0px none; " src="https://5dfg34-developer-edition.na50.force.com/resource/1505938566000/ttttteee__Chat_Agent_Online" />
        <script type="text/javascript">
        if (!window._laq) { window._laq = []; }
        window._laq.push(function(){liveagent.showWhenOnline('5736A000000gBrn', document.getElementById('liveagent_button_online_5736A000000gBrn'));
                                    liveagent.showWhenOffline('5736A000000gBrn', document.getElementById('liveagent_button_offline_5736A000000gBrn'));
                                   });</script>
        
        
    </body>
    
    
</apex:page>

Now go to the console app and enabled the live agent in the console app to use the live agent.

After you enabled the live agent you can able to see the live agent as shown below

Go to the visualforce page and click on Preview then you will see the output as shown below. then click on the button to start the chat. Make sure use is login into the console and update the live agent status to online.

Now go to the console and accept the chat request from the live agent chat request

You can see the chat from the salesforce console app as shown below .