Dynamic telephone number presentation based on Apex Trigger


During a recent Computer Telephony Integration (CTI) project with a customer we had a requirement that the outbound (or presented telephone number) should be selected dynamically for each call made using a custom Apex Class.

Luckily, NewVoiceMedia's CTI solution features a hook which allows for a custom Apex Class that would handle this logic and alternate the presented number.

This write up covers the Trigger and Class, stored for prosperity.

Why would you need this?

Dynamic Caller ID or CLID presentation allows you to display the most appropriate calling number relevant to that Account/Contact in Salesforce.

For example, if I were calling a Spanish customer and I had a Spanish freephone number available as one of my outbound numbers, I would ideally like that number to be used.

If I called an American number I might wish to display a local US number so that the customer could call straight back at local telephone rates.

How does this code work?

  1. The code first identifies which object the telephone number resides in Salesforce (Account/Contact/Lead etc). 
  2. The code then gets the ZIP code from the address field on that object. 
  3. We then query a central table called AreaCodeMap__c to see if we have a desired outbound CLID matching that ZIP code
  4. If there is a match, the new outbound number is used
  5. If there is not a match, the call is made using a default outbound number
Here's the full Class and Test Class.

Apex Class

global class SelectPresentedClidByTableAreaCode implements NVMContactWorld.ISelectPresentedClid {

    private static final Logger log = Logger.getLogger(SelectPresentedClidByTableAreaCode.class);

    // The clickToDialResult parameter contains the response string from the Salesforce ClickToDial event.
    // Salesforce passes the clickToDialResult parameter to us:
    // for example '{number: "07890123456", objectId: "0032000001FTGSo", object: "Contact"}'
    // Find more information at: https://www.salesforce.com/us/developer/docs/api_cti/Content/sforce_api_cti_onclicktodial.htm

    global String GetPresentedClid(String clickToDialResult){
        Map<String,Object> clickToDialResultMap = (Map<String,Object>) JSON.deserializeUntyped(clickToDialResult);

        String objectId = (String) clickToDialResultMap.get('objectId');
        String objectType = (String) clickToDialResultMap.get('object');

        //Query NVMDefaultCLID to get default Presented CLID
        NVM__c cp = NVM__c.getOrgDefaults();
        String presentedClid = cp.Default_CLID__c;
        log.debug('Default CLID loaded as ' + presentedClid);

        String zip;
        Integer zipNumber = 0;

        if (objectType == 'Contact') {
            System.debug('User clicked on Contact');
            Contact c = [select Id, Zip__c from Contact where Id = :objectId];
            zip = c.Zip__c;
        } else if (objectType == 'Lead') {
            System.debug('User clicked on Lead');
            Lead l = [select Id, Zip__c from Lead where Id = :objectId];
            zip = l.Zip__c;
        } else if (objectType == 'Account') {
            System.debug('User clicked on Account');
            Account a = [select Id, Zip__c from Account where Id = :objectId];
            zip = a.Zip__c;
        log.debug('ZIP is ' + zip);
        if (!String.isBlank(zip)) {
            zipNumber = Integer.valueof(zip);
            List<AreaCodeMap__c> z = [select Id, CLIDValue__c, ZIP__c from AreaCodeMap__c where ZIP__c = :zipNumber];
            log.debug('Trying to find ZIP in AreaCodeMap__c ' + z);
            if(!z.isEmpty()) {
                presentedClid = z[0].CLIDValue__c ;
                log.debug('Set new presentedClid value. Value is now ' + presentedClid);
             } else {
                presentedClid = cp.Default_CLID__c;
        log.debug('Final returned number is currently' + presentedClid );
        return presentedClid;

Test Class

public class TestSelectedPresentedClidByTableAreaCode {
    static testMethod void simulateContactCall() {
        String value ='{number: "07890123456", objectId: "0032000001FTGSo", object: "Contact"}';
    static testMethod void simulateLeadCall() {
        String value2 ='{number: "07890123456", objectId: "0032000001FTGSo", object: "Lead"}';
    static testMethod void simulateAccountCall() {
        String value3 ='{number: "07890123456", objectId: "0032000001FTGSo", object: "Account"}';
} //end of class