APEX CLASS
Description
pushtopics.SalesforceDataTransformer is a global interface that enables custom Apex logic within DSP formulas, extending the package’s out-of-box transformations when built-in functions are insufficient. Reference an implementation in a formula using the placeholder syntax #ApexClassName.

global interface pushtopics.SalesforceDataTransformer {
/**
* Specifies an array of field API names to retrieve from the source records.
* This ensures DSP includes all required fields during the Retrieve step,
* making them available for the Scoping, Match, and Mapping steps.
*/
String[] retrieveSourceFields();
Object transform(List<Map<String, Object>> contextSourceRecords,
Map<String, Object> currentSourceRecord,
String assignedToFieldName);
}Example
global with sharing class BulkifiedDataTransformerExample implements pushtopics.SalesforceDataTransformer {
private static Map<Id, Account> cachedAccountMap = null;
global String[] retrieveSourceFields() {
// Ensures fields(including relational fields) are retrieved by DSP in the source records.
return new String[]{'RecordType.DeveloperName', 'GetAllOpportunityAmounts__c'};
}
global Object transform(
List<Map<String, Object>> contextSourceRecords,
Map<String, Object> currentSourceRecord,
String assignedToFieldName
){
Object recordTypeDevName = ((RecordType)currentSourceRecord.get('RecordType')).DeveloperName;
Object getAllOpportunityAmounts = currentSourceRecord.get('GetAllOpportunityAmounts__c');
if(recordTypeDevName == 'Business' && getAllOpportunityAmounts == true){
Account account = getAccountWithChildRelationships(
contextSourceRecords,
currentSourceRecord
);
String ret = '';
for(Opportunity opportunity : account.Opportunities){
ret += opportunity.StageName + ':' + opportunity.Amount + ';';
}
return ret;
}
else{
return null;
}
}
private Account getAccountWithChildRelationships(
List<Map<String, Object>> contextSourceRecords,
Map<String, Object> currentSourceRecord
){
// Bulkified logic: lazy loads data on first use and then caches it in a static variable for the rest of the transaction to avoid repeat queries.
if(cachedAccountMap == null){
cachedAccountMap = new Map<Id, Account>(
[SELECT Id,
(SELECT Amount, StageName FROM Opportunities)
FROM Account
WHERE Id IN :getFieldValuesAsString(contextSourceRecords, 'Id')]
);
}
return cachedAccountMap.get((Id)currentSourceRecord.get('Id'));
}
// A reusable utility method for extracting string field values from a list of JSON objects.
private static String[] getFieldValuesAsString(
List<Map<String, Object>> records,
String fieldName
){
String[] ret = new String[]{};
for(Map<String, Object> record : records){
String fieldValueAsString = (String)record.get(fieldName);
if(fieldValueAsString != null){
ret.add(fieldValueAsString);
}
}
return ret;
}
}