Skip to content

Run Salesforce Automation when a Sales Engagement Cadence is completed or the last step of a cadence is completed

In Salesforce, you cannot directly trigger a Flow or Apex Trigger when a Sales Engagement Cadence is completed, because Salesforce does not expose a native “Cadence Completed” event or field out-of-the-box that Flows or Apex can monitor.

However, you can work around this limitation depending on what your goal is. Here is an overview of the solution using Change Data Capture and Apex trigger on CDC event:

STEP 1: Enable Change Data Capture for the ActionCadenceStepTracker object as mentioned in the following screenshot.

STEP 2: Create an Apex Trigger on the ActionCadenceStepTrackerChangeEvent object

This Apex trigger runs on the ActionCadenceStepTracker Change Event. It checks whether the State field has been updated to 'Completed' and verifies if the completed step is the last step in the cadence. If both conditions are met, it further checks if the cadence name is either "My Sample Cadence 1" or "My Sample Cadence 2". If the cadence is related to an Opportunity, the trigger updates the Opportunity’s Description field.

You can modify the logic and update different records based on your specific requirements.

trigger ActionCadenceStepTrackerCDCTrigger on ActionCadenceStepTrackerChangeEvent (after insert) {
    
    set<Id> ActionCadenceStepTrackerIds = new set<Id>();
    
    for(ActionCadenceStepTrackerChangeEvent event : Trigger.New) {
        
        EventBus.ChangeEventHeader header = event.ChangeEventHeader;        
        
        System.debug('Received change event for ' + 
                     header.entityName +
                     ' for the ' + 
                     header.changeType + 
                     ' operation.'
                    );
        
        system.debug('event::'+event);
        
        List<String> changedFields = event.ChangeEventHeader.getChangedFields();
        
        Boolean isStateCompleted = 'Completed'.equals(event.State);
        Boolean isStateFieldChanged = changedFields.contains('State');
        
        if (header.changeType.equalsIgnoreCase('update') && isStateCompleted && isStateFieldChanged) {
            
            for(Id recordId : header.getRecordIds()){
                ActionCadenceStepTrackerIds.add(recordId);
            }
        }
    }
    
    Map<Id, ActionCadenceStepTracker> ActionCadenceStepTrackerMap = new Map<Id, ActionCadenceStepTracker>([SELECT Id, ActionCadenceName, ActionCadenceTrackerId, ActionCadenceTracker.State, ActionCadenceTracker.CurrentStepId, ActionCadenceTracker.RelatedToId, StepTitle, State, ActionCadenceId FROM ActionCadenceStepTracker WHERE ID IN :ActionCadenceStepTrackerIds]);
    system.debug('ActionCadenceStepTrackerMap::'+ActionCadenceStepTrackerMap);
    
    for(ActionCadenceStepTracker acst : ActionCadenceStepTrackerMap.values()){
        
        
        if((acst.ActionCadenceName == 'My Sample Cadence 1' || acst.ActionCadenceName == 'My Sample Cadence 2') && acst.State == 'Completed' && acst.ActionCadenceTracker.CurrentStepId == NULL && acst.ActionCadenceTracker.State == 'Complete') {
            system.debug(acst.ActionCadenceName+' cadence completed.');
            
            //Example of Performing an action on the Opportunity
            if(acst.ActionCadenceTracker.RelatedToId != NULL && String.valueOf(acst.ActionCadenceTracker.RelatedToId).StartsWith('006')){
                Opportunity opp = new Opportunity(Id = acst.ActionCadenceTracker.RelatedToId);
                opp.Description = acst.ActionCadenceName+' cadence completed.';
                update opp;
            }
        }
    }
}
Leave a Reply

Your email address will not be published. Required fields are marked *