Getting Started
Installation
Permissions
Widget & Inline Page
Classic - Distribution Engine Inline Page
Lightning - Distribution Engine Record Detail
Widget - Introduction
Adding Widget to a Lightning App
Adding Widget to a Lightning Page
Adding Widget to Salesforce Mobile
Adding Widget to a Classic Console
Adding Widget to Classic Homepage
Changing the Widget logout reason list
Before you Begin
Installation Overview
Whats in the Package
Triggers
Installation Process
Managed Package Licences
Page Layouts
Leaving A Review
Uninstall
Upgrading Distribution Engine
Configure Distribution Engine
Distribution Classifier
Territories
Territories Introduction
Create a Map
Import Territories
Territory Map Zoom Levels
Object Settings
Detecting Territories
Settings
Territories - Technical Details
Territory Distributor
Lead Matching
Lead Matching - Introduction
Duplicate Rule Setup
Related Owner - Lead Matching
Lead matching vs lookup owner
Classifier Lead Matching Setup
Lead to Account/Contact/Lead Settings
Custom Classification
Custom Classification - Introduction
Stamp Groups
Stamps
Custom Classification - Synchronized Tag Collections
Lead Auto-Conversion
Lead Auto-Conversion - Introduction
Lead De-Duplication
Lead Conversion
Configuring Auto-Conversion
Auto-Conversion Rules
Distribution Classifier - Introduction
Backfill
Delay Filters
Distribution Teams
Distributors
Distribution Methods
Distribution Methods - Introduction
Lookup Owner
Load Balancing
Round Robin
Related Owner
Sticky Assignment
Distributors Introduction
Distributor Types
Standard Distributor Settings
Pull Distributor Settings
Trigger Distributor Settings
Manual Distributor Settings
Distributor Sources
Distributing from a Designated User
Distributor Filters
Distributor Team Member Filters
Distributor Sort Order
Advanced Filter Mode
Distributor Test Tool
Weighting and Caps
Distribution Hours
Tracking & SLAs
Team Settings
Distribution Teams Introduction
Distribution Assignment Process view
Team Summary
Team Members
Team Availability
Team Performance
Assignment Rejection
Post Assignment
Stamp Rejection
Distribution Tags
Distribution Availability
Distribution Availability
Shift Hours
Out of Office
Distribution Holidays
Holiday Regions
Regional Holidays
User Availability Toggle
Distribution Settings
Distribution Settings
Calendar Integration
Advanced Settings
Distribution Engine Running User
Licensed users list
Export & Import
Import Errors
Trigger Settings
Email Notifications
Email Notifications - Introduction
Custom Email Notifications
Disabling Standard Email Notifications
Customising the Email Template
Disabling Custom Email Notifications
From Email Address
Email Notification as Flow
Assignment Simulator
Assignment Simulator - Introduction
Configure Assignment Simulation
Assignment Simulator Result Explorer
Advanced
Q2Q teams
Integrating InsideSales.com power dialer
Pardot
Auto archive feature
Uploading tags via dataloader
Salesforce Mobile
Tuning Distribution Engine
Setup Introduction
Queue Basics
Queues
Distribution Sync
Monitoring
Distribution Console
Console Introduction
Application Monitoring
Today's Distributions
Sources Console
Availability Calendar
Distribution Logs
Distribution Logs
Distribution Logs List
Territories Logs List
Lead Matching Logs List
Custom Classification Log List
Auto-Conversion Logs List
Object Sync Logs List
Scheduler Logs List
Archive Logs List
Exporting Log Data
Distribution Analytics
Distribution Engine Details Object
Distribution Engine Dashboard
Salesforce Reports
Reports - Leads and Distribution Logs
Change History
Setup Examples
Skill Based Matching
Assigning Contacts - Pairing SDRs and AEs
Delaying Distribution
Enforce Cap for Manually Assigned Records
Criteria Caps
Salesforce Admins
Workflow Rule Examples
Formula Examples
Domain Formula
Timezone Bucket Formula
Has Activity Formula
Territory Formula
Age Formula
Distribution Engine Details Formula
id Field to Text
Flow Examples
Chatter Notifications
Slack Notifications
Desktop or Mobile Notifications
Custom Assignment Rejection
Classify on Address Change
Assign on Action
Process Builder Examples
Process Builder - Avoiding Clashes
Opportunity Assignment - Updating Related Accounts & Contacts
Rejection API Process
Assign License and Permission Set on Team Member Addition
Assign License on Team Member Addition
Tasks on Record Assignment by Distribution Engine
Information for New Admins
Validation Rules
Developers
Apex API
Availability API
Classifier API
Out of Office API
Tags API
Team Members API
DE Apex API Introduction
Rejection API
System API
Trigger Distribution API
Apex Trigger Examples
Omni-Channel Presence Integration
Salesforce Presence Integration
Invalid Email trigger
Custom Triggers
Visualforce Examples
Troubleshooting
Warnings and Errors
Health Checker Messages
Scheduler Restarted
Distributor Failures - Records on Hold
Assignment Errors
Classifier Errors
Apex CPU time limit exceeded
Timeout when deleting a Team Member or Distributor
Records Stuck / Not Being Assigned
Support
Previous Releases
2.9
3
4
4.12
4.15
Armadillo
Bison
Chameleon
Dragon
Dragon beta release - install guide
Eagle upgrade process
Eagle
Fox
Gorilla
Gorilla Upgrade Process
Hummingbird
Hummingbird Upgrade Process
Impala
Impala Upgrade Process
Jellyfish
Jellyfish Upgrade Process
Koala
Koala Upgrade Process
Llama
Llama Upgrade Process
Meerkat
Meerkat Upgrade Process
Upgrade Links
Frequently Asked Questions
Legacy Widget - New status
Distribution Engine Aborted
Alerts not Firing
Distribution Engine Delayed
Can one Distributor Assign from Multiple Queues / Users?
Can't See Distribution Engine
Distribution Engine Not Running
Manual Shutdown of Distribution Engine
Exclude members from Holidays
Distribution Engine Health Checker Restart
Dashboard Running User Error
Assignments going to wrong user
Contact Support
Grant Login Access
Upgrading Distribution Engine Steps
Purchase
Purchasing Steps
Purchasing FAQs
Support Packages
Legal Agreement Details
GDPR
Policies
Migrating Licences
Contact us
Latest Release
- All Categories
- Developers
- Apex Trigger Examples
- Salesforce Presence Integration
Salesforce Presence Integration
Updated by Simon Maskell
The following article describes how the user availability toggles, normally updated via the Distribution Engine widget, could be controlled by whether a user is logged into Salesforce or not.
There are two main methods of determining whether a user is logged into Salesforce: login/logout events and session polling. Depending on your configuration it may make sense to handle one or both of these methods.
Login/Logout Events
Salesforce allow for a Flow to be initiated when a user logs into the org. As part of this, logic can be added to automatically toggle that user on within DE. See Create a Login Flow with Flow Builder for more information.
Salesforce can also be configured to publish events when users log out of the org, which can be captured by a Trigger to automatically toggle that user off within DE. See Create Logout Event Triggers for more information.
Step 1 - Create the flow
- Go to Setup > Process Automation > Flows
- Click New Flow
- Select "Screen Flow"
- Click Create
Step 2 - Create the user id variable
- In the Toolbox on the left, click New Resource
- Resource Type: Variable
- API Name: LoginFlow_UserId
- Data Type: Text
- Available for input: Check
Other input variables can also be created, which will be passed in from from the login event, see Login Flow Examples for more information.
Step 3 - Filter to DE users
To avoid potential overhead, it is worth adding a Decision step to determine whether the user is a DE user, and therefore should have their trigger updated. This could, for example, be based on an attribute on their user record or a permission set. As part of the configuration you'll do later, the login flow will be associated to a profile, so that may be enough, or you may require additional filtering. Therefore, this step will change depending on your specific requirements.
- Click the Add Element button and select "Decision"
- Label: Should Toggle User
- Outcome details Label: Is DE User
- Condition: <Based on your requirements>
- Default outcome details Label: Is Not DE User
Step 4 - Toggle user on
This step uses the DE Availability API, see this article for more information.
- In the "Is DE User" branch, click the Add Element button and select "Action"
- In the category "Distribution Engine" search for the action "DE Toggle Users"
- Label: Toggle User On
- Toggle user online?: {!$GlobalConstant.True}
- User id: {!LoginFlow_UserId}
- Click Done
- You will end up with the following Flow
Step 5 - Save the flow
- Click Save on the toolbar
- Flow Label: Toggle DE User On Login
- Click Save
- Click Activate on the toolbar
Step 6 - Associate the flow with the login event
- Go to Setup > Identity > Login Flows
- Click New
- Type: Flow
- Name: Toggle DE User On Login
- Flow: Toggle_DE_User_On_Login
- User License: Salesforce
- Profie: <Desired profile>
- Click Save
Step 7 - Create logout trigger
Standard development practices for writing code in your org should be followed.
- Use the below code to create a trigger for the logout event
- Include your own logic to determine whether to run the trigger for the user
trigger LogoutDEEventTrigger on LogoutEventStream (after insert) {
LogoutEventStream event = Trigger.new[0];
/* Logic to determine whether the user is relevant to DE */
List<n2de.DistributionEngineGlobal.ToggleUserDTO> userDtoList = new List<n2de.DistributionEngineGlobal.ToggleUserDTO>();
userDtoList.add(new n2de.DistributionEngineGlobal.ToggleUserDTO(event.UserId, false, 'Logged out of Salesforce'));
n2de.DistributionEngineGlobal.toggleUsers(userDtoList);
}
This step uses the DE Availability API, see this article for more information.
Step 8 - Enable logout event streaming
- Go to Setup > Events > Event Manager
- Click on the row menu for "Logout Event" and click Enable Streaming
Session Polling
There is an object within Salesforce called AuthSession that holds session information for users. This object can be used to determine whether a user has an active session within Salesforce. A session can extend beyond when a user has closed their browser, if they did not explicitly log out, and will depend on your org settings for sessions, so that needs to be taken into consideration.
A job can be created to poll this object every so often and toggle users on/off based on whether they have an active session. Below is an example of a queueable job that will continue indefinitely until aborted, running about every 5 minutes. This queries the AuthSession object for application login types and UI session types, but that may need to change based on your specific use case. You also need to make sure that this job runs under a user that can query all records in the AuthSession object.
public with sharing class ToggleDEUserBasedOnSession implements System.Queueable {
public void execute(QueueableContext context) {
// Fetch all DE user ids
Map<Id, Map<Id, Boolean>> teamUserAvailability = n2de.DistributionEngineGlobal.getUserAvailabilityAllTeams();
Set<Id> allDEUserIds = new Set<Id>();
for (Map<Id, Boolean> teamAvailability : teamUserAvailability.values()) {
allDEUserIds.addAll(teamAvailability.keySet());
}
// Collect the UI auth sessions for the users
List<AuthSession> authSessions = [SELECT UsersId, LastModifiedDate, NumSecondsValid FROM AuthSession WHERE UsersId IN :allDEUserIds AND SessionType = 'UI' AND LoginType = 'Application' ORDER BY LastModifiedDate ASC];
Set<Id> usersWithSessions = new Set<Id>();
for (AuthSession authSession : authSessions) {
if (authSession.LastModifiedDate.addSeconds(authSession.NumSecondsValid) > now) {
usersWithSessions.add(authSession.UsersId);
}
}
// Determine whether the users are online
List<n2de.DistributionEngineGlobal.ToggleUserDTO> userDtoList = new List<n2de.DistributionEngineGlobal.ToggleUserDTO>();
for (Id userId : allDEUserIds) {
Boolean active = usersWithSessions.contains(userId);
userDtoList.add(new n2de.DistributionEngineGlobal.ToggleUserDTO(userId, active, active ? null : 'No active session'));
}
// Toggle the users
n2de.DistributionEngineGlobal.toggleUsers(userDtoList);
// Schedule the next job in 5 minutes
System.enqueueJob(new ToggleDEUserBasedOnSession(), 5);
}
/**
* Static method to start the queueable job
*/
public static void startJob() {
System.enqueueJob(new ToggleDEUserBasedOnSession());
}
/**
* Static method to abort any pending or running queueable jobs
*/
public static void abortJob() {
List<AsyncApexJob> jobs = [SELECT Id, Status FROM AsyncApexJob WHERE Status IN ('Holding', 'Queued', 'Prepared', 'Processing') AND ApexClass.Name = :ToggleDEUserWithSession.class.getName()];
if (!jobs.isEmpty()) {
System.abortJob(jobs.get(0).Id);
}
}
}
To start the job running, in anonymous Apex execute the command ToggleDEUserBasedOnSession.startJob();
which will start the queueable job running until it is aborted. If you want to abort the job you can execute ToggleDEUserBasedOnSession.abortJob();
. If preferred, the same code could be scheduled to run within a scheduled job.