I'd like to know the max date of any event we've held with a given customer. While some events are sf-generated (and therefore records), many are managed directly within gmail and then synced via Einstein Activity Capture. It appears these do not show up in standard Event SoQL queries (as expected, since these are not "Events" so much as "runtime_sales_activities__activityTimelineEventStreamDetail"...

Ultimately, the question I need to solve is "which customers have not had a meeting scheduled with us in the last x days", and without data-access to the EAC data, doesn't seem like that would be possible. How are folks solving this gap with EAC?

1 Answer 1


Thanks to the latest Salesforce release, Winter '24, we now have a small window into what they call "Unified Activities", by way of Standard Reports. That seems to be the only available mechanism at the moment, so I've created a simple batch job to run every so often to toss the latest scheduled event on the related Account. The key is to define a new report using their new Accounts with Unified Events Report Type and then just make sure that there are two columns: Account Name and Activity Date/Time (IMPORTANT: sorted DESC). I set a filter to show the last week's worth of activities so that a failed batch would be "self-healed" by the next batch (plus some buffer) and my Report's DeveloperName was saved as AccountsWithUnifiedEvents:

enter image description here

public class BatchUpdateUnifiedEvents implements Database.Batchable<sObject> {
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([SELECT Id, DeveloperName FROM Report WHERE DeveloperName = 'AccountsWithUnifiedEvents']);

    public void execute(Database.BatchableContext bc, List<Report> rpts) {

        Map<Id, Account> accounts = new Map<Id, Account>();

        for (Report rpt : rpts) {
            Reports.ReportMetadata mdt = Reports.ReportManager.describeReport(rpt.Id).getReportMetadata();
            Reports.ReportResults results = Reports.ReportManager.runReport(rpt.Id, mdt, true);
            if (rpt != null) {
                for (Reports.ReportFact fact : results.getFactMap().values()) {
                    Reports.ReportFactWithDetails factDetails = (Reports.ReportFactWithDetails)fact;
                    for (Reports.ReportDetailRow detail : factDetails.getRows()) {
                        String accountId;
                        DateTime eventAt;
                        for (Reports.ReportDataCell cell : detail.getDataCells()) {
                            if (cell.getValue() instanceOf String && String.valueOf(cell.getValue()).length() == 18 && String.valueOf(cell.getValue()).startsWith('001')) {
                                accountId = String.valueOf(cell.getValue());
                            } else if (cell.getValue() instanceOf DateTime) {
                                eventAt = DateTime.valueOf(cell.getValue());
                        if (eventAt != null && String.isNotBlank(accountId) && !accounts.containsKey(accountId)) {
                            accounts.put(accountId, new Account(
                                Id = accountId,
                                LatestScheduledUnifiedEvent__c = eventAt

        if (!accounts.isEmpty()) {
            update accounts.values();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .