[SalesForce] Automatically associate chat transcript to case and account

We're using the service cloud console and live agent chat. We have chosen not to automatically create a new case for every inbound chat request (So Deployment API and pre-chat API are probably not in play here).

We would like to automatically populate the account and case lookups on the chat transcript based on what the agent is doing/looking at.

We already have APEX code that executes when agents view an account and when they create a new case, so we can add additional code that performs the association. The code can be straight APEX, Javascript using the console integration toolkit, or a combination of both.

Ideally, the method would allow the association to be picked up by the normal "Attach" feature of the live chat window (the paperclip).

Thanks. All ideas are appreciated.

Best Answer

When manually creating the Case in a console component instead of letting Salesforce create the Case automatically via pre-chat or deployment API then you will need to use an apex trigger on the LiveChatTranscript object and add a custom text field Chat Key to your Case object to correlate the records in the trigger.

Custom Console Component

Here is sample javascript that listens for a new chat session to start and creates a new Case record, populating the Case record with the Chat Key.

<apex:page>

    <apex:includeScript value="/support/console/37.0/integration.js"/>

    <apex:remoteObjects>
        <apex:remoteObjectModel name="Case" fields="Id,Chat_Key__c"/>
    </apex:remoteObjects>

    <script type="text/javascript">

        // on chat start, create case manually and populate the chat_key__c field.
        // once agent closes the chat/case tabs then salesforce creates transcript.
        // because we created case manually and not through pre-chat or deployment api then
        // salesforce does not automatically link the transcript to this case, that is
        // where the LiveChatTranscriptTrigger comes into play and links them for us.

        sforce.console.chat.onChatStarted( function( chatResult ) {

            if ( chatResult.success ) {

                // create case and set the chat_key__c field
                // you can use the sforce.connection API, REST API, Remote Actions, etc.
                // just make sure when you create the case you get that chat key field populated

                var cs = new SObjectModel.Case({
                    Subject : 'Live Chat Test',
                    Origin : 'Web',
                    Chat_Key__c : chatResult.chatKey
                });

                cs.create( function( err, records, evt ) {

                    console.log( err );
                    console.log( records );
                    console.log( evt );

                    if ( err ) {

                        alert( err.message );

                    } else {

                        sforce.console.getFocusedPrimaryTabId( function( primaryTabResult ) {

                            console.log( 'getFocusedPrimaryTabId' );
                            console.log( primaryTabResult );

                            if ( primaryTabResult.success ) {

                                console.log( 'primaryTabId: ' + primaryTabResult.id );
                                console.log( 'caseId: ' + records[0] );

                                sforce.console.openSubtab(
                                    primaryTabResult.id,
                                    '/' + records[0] + '/e',
                                    true,
                                    'Edit Case',
                                    null,
                                    function( openSubtabResult ) {
                                        console.log( 'openSubtabResult' );
                                        console.log( openSubtabResult );
                                    }
                                ); // end open sub tab

                            } // end if

                        }); // end get focused primary tab id

                    } // end if

                }); // end case create callback

            } // end if

        }); // end on chat started callback

    </script>

</apex:page>

LiveChatTranscript Trigger

The LiveChatTranscript record will have the ChatKey populated on it but the CaseId will be blank (in this scenario). So we look up the related Case indirectly by the chat key custom field we setup earlier.

trigger LiveChatTranscriptTrigger on LiveChatTranscript ( after insert ) {

    Set<String> chatKeys = new Set<String>();

    for ( LiveChatTranscript transcript : Trigger.new ) {
        if ( String.isBlank( transcript.caseId ) && String.isNotBlank( transcript.chatKey ) ) {
            chatKeys.add( transcript.chatKey );
        }
    }

    System.debug( 'chatKeys=' + chatKeys );

    if ( chatKeys.size() > 0 ) {

        // chat_key__c should be a unique, external id field
        // populated in the console once the chat has started and case created
        List<Case> cases = new List<Case>([
            SELECT
                id, chat_key__c
            FROM
                Case
            WHERE
                chat_key__c IN :chatKeys
            ORDER BY
                createdDate ASC
        ]);

        // chatKey => case
        Map<String, Case> chatKeyCasesMap = new Map<String, Case>();

        for ( Case cs : cases ) {
            chatKeyCasesMap.put( cs.chat_key__c, cs );
        }

        System.debug( 'chatKeyCasesMap=' + chatKeyCasesMap );

        List<LiveChatTranscript> transcriptsToUpdate = new List<LiveChatTranscript>();

        for ( LiveChatTranscript transcript : Trigger.new ) {

            if ( String.isBlank( transcript.caseId ) && String.isNotBlank( transcript.chatKey ) ) {

                Case cs = chatKeyCasesMap.get( transcript.chatKey );

                if ( cs != null ) {
                    transcriptsToUpdate.add( new LiveChatTranscript(
                        id = transcript.id,
                        caseId = cs.id
                    ));
                }

            }

        }

        if ( transcriptsToUpdate.size() > 0 ) {
            System.debug( 'transcriptsToUpdate: ' + transcriptsToUpdate );
            update transcriptsToUpdate;
        }

    }

}

Unit Test

Simple unit test for code coverage of above trigger.

@isTest
private class LiveChatTranscriptTriggerTest {

    @isTest
    static void link_transcript_to_case() {

        Case cs = new Case(
            subject = 'Test Case',
            origin = 'Web',
            chat_key__c = '123'
        );

        insert cs;

        LiveChatVisitor visitor = new LiveChatVisitor();

        insert visitor;

        Test.startTest();

        LiveChatTranscript tx = new LiveChatTranscript(
            chatKey = '123',
            liveChatVisitorId = visitor.id
        );

        insert tx;

        Test.stopTest();

        tx = [ SELECT id, caseId, chatKey FROM LiveChatTranscript WHERE id = :tx.id ];

        System.assertEquals( cs.chat_key__c, tx.chatKey );
        System.assertEquals( cs.id, tx.caseId );

    }

}
Related Topic