What’s trending
UPCOMING EVENTS
Unleashing Apex With Salesforce Data Cloud Segments
By Eoghan McMullen
Imagine being able to take action in Salesforce based on dynamic customer segments in Data Cloud.
The drag-and-drop interface in Data Cloud offers incredibly powerful tools for building segments. If, like me, you’ve come across a scenario where it makes sense to take an action in Salesforce based on changes in your Data Cloud segments, then this is the blog for you.
Setting the Scene
To show you the power of this approach, I’ll be walking you through a fictitious business scenario with the goal of helping you unlock some ideas for your own orgs.
Big Bicycle Co. rents bicycles and related equipment to customers and relies heavily on Salesforce to manage its rental processes. The company also has a Salesforce Experience Cloud site, where customers can log in to plan a weekend outing on one of their bikes.
Jane, the Marketing Head at Big Bicycle Co., wants to reward regular customers with accessory coupons. She wants full control over which customers receive them, basing eligibility on past purchases. To encourage more customers to use the Experience Cloud site, Jane has decided these coupons will be redeemable only through the customer portal.
Now that we have our business scenario, here are a few things to note before we continue.
- This use case is for demonstration purposes only and is not necessarily the best way to implement this use case.
- We will be using custom objects for simplicity vs using some out-of-the-box objects (Product2, I’m looking at you).
- We will be skipping some coding best practices for brevity’s sake – though I will point it out when I do so.
- Although I am showing you how to achieve this in Apex, you could also try your hand at achieving it in a flow.
- When you’re implementing Data Cloud, spend some time analyzing if you can use the out-of-the-box Data Cloud Data Model Objects(DMOs). For simplicity, this blog will map the custom objects to custom Data Model Objects.
Setting Up Our Environment
To successfully implement this use case, we’ll need the following components:
- A Salesforce Data Model: Defines how rental and coupon data is structured.
- A Custom Lightning App: Provides an intuitive interface for Jane to manage segments and coupons.
- Data Streams, Data Model Objects, and Relationships in Data Cloud: Enables Salesforce data to be ingested and related within Data Cloud.
- Sample Segments: Helps us test targeting and automation.
- Data Actions and Data Action Targets: Triggers events in Salesforce based on Data Cloud segment changes.
- A Platform Event Trigger: Listens for segment changes and initiates actions in Salesforce.
The following diagram highlights our target architecture. Don’t worry, we’ll be diving into each portion below.

In Core Salesforce CRM
Data Model
In core Salesforce, we need a data model that will allow customers to rent bikes and also receive their coupons.
The following Entity Relationship Diagram is a simplified representation of the Data Model we’ll be using for this use case.

- Contact represents our customer.
- A Rental Agreement represents an instance of a customer renting a bicycle.
- The Bicycle object captures a particular bicycle unit.
- The Model object captures the type of bike we are using, e.g. the brand, colour, etc. (typically, we’d use product2 for this).
- The Customer Coupon ties a customer to a particular coupon or offer.
- The Coupon object is used to tie a segment to a particular coupon. By doing this, we will be able to generate Customer Coupon records for a given segment.
Platform Event Trigger
To act on our segment changes, we will need an Apex trigger that can consume the event and generate the Customer Coupon records in our core Salesforce instance. We’ll dive into this implementation later in the blog.
A Custom Lightning App
We’ll create a custom Lightning App to make navigating all of this easy for Jane, our marketing head.

In Salesforce Data Cloud
Data Streams and Data Model Objects (DMOs)
We’re going to stream Salesforce data into Data Cloud using the out-of-the-box Salesforce connector.
This involves creating a data stream per object, creating the Data Model Objects, mapping the Data Lake Objects to the Data Model Objects, and finally creating the relationships between the data model objects.
The relationships will allow us to drill into related information in the segment builder. Our target Data Model within Data Cloud will look something like the image below.
We’ve only had to pull in Contacts, Rental Agreements, Models, and Bicycles – this is enough to allow Jane to perform some pretty targeted segmentation. The Account Contact node is highlighted in green to denote that the category of the data is “Profile”. This means we’ll be able to segment on it.
The other nodes all represent data with a category of “Other”; we’ve set it as this as we don’t need to segment directly on that data.
Segments
Data Streams and Data Model Mapping from our Salesforce org are required so we can segment our bike rental customers. Since this blog is not focused on creating and mapping data in Data Cloud, I’ll simply be showing the Segments we generate.
If segments are new to you, they essentially capture a set of related data. For example, we could have a segment of all of our Salesforce Contacts whose birthdays are in the year 1956 or customers whose first name is “John”. Data Cloud has a drag-and-drop interface available for creating segments by filtering the data within your data cloud environment.
I’m going to create a segment that targets our customers who have at least six rental agreements. Jane wants to offer a coupon to these customers through the customer portal.
The segment I’ve created runs on Account Contacts – we are drilling into the related Rental Agreement records. Our rules state that to be included in the segment, the Account Contact must have at least six of these records.

You’ll see in the above image that we have one customer that matches this criteria – just enough to test out our solution.
Platform Event Setup
Now the fun begins. Our end goal is to subscribe to platform events using an Apex Trigger. We want our trigger to fire any time a member is added or removed from a segment. Data Cloud makes raising these platform events easy.
Data Action Target Creation
A Data Action Target allows us to define how our Data Actions will be processed. There are a few target types, but we’ll be leveraging the Salesforce Platform Event type. This will allow us to push a data action to the core Salesforce event bus.
Firstly, navigate to Data Cloud → Data Action Targets → and click New.

Next, we want a Manual type Data Action Target, so select Manual and click Next.

We then need some basic information for the Data Action Target, so provide a meaningful Name and API Name.
For Data Action Target Type choose Salesforce Platform Event and ensure you choose the correct Salesforce Org if you have multiple connections.

The Data Action Target setup is complete. We now need a Data Action that will make use of this Data Action Target.
Data Action
A Data Action allows us to monitor changes to our Data Model Objects in Data Cloud. We select a Data Action Target to choose where to send these changes. In our use case, we want to monitor the changes via a Salesforce Platform event.
Navigate to Data Actions → Click New.

Then choose Standard Data Action and the Manual option for creating the Data Action.

Now, we need to select the Data Action Target we previously created. This will ensure the changes we are monitoring are raised as a Salesforce platform event.

The Data Space and Objects screen is next up.
Set the following values:
- The Data Space you are working in
- Object Type = Data Model Object
- Primary Object = Account Contact – Latest
- Leave Related Object blank
The Account Contact – Latest is a Data Model Object within Data Cloud that gets populated whenever a segment is published.

Now, we set the Event and Action Rules.
Set the following values:
- Check the box for each of Record Created, Record Updated, and Record Deleted.
- We don’t need any Action Rules, so we won’t add any conditions.
- Under Trigger Data Action for Updated Records, choose the Default option.

In the final screen, we simply need a meaningful name for the Data Action; be sure to provide a description, too.

Finally, hit Save and Publish.
Verifying Our Setup
At last, we’re at the point where we can see our platform events in Action – we now need to subscribe to our events, which we’ll be doing with an Apex Trigger.
Below, you’ll see a very simple Trigger that subscribes to the DataObjectDataChgEvent platform event. To make things very easy to read, we are not going to use a trigger framework or introduce any handler patterns; in your implementation, you should be considering these best practices.
The DataObjectDataChgEvent is a platform event that notifies subscribers of an action that takes place in Data Cloud. Since we have created our Data Action on Account Contact – Latest, this platform event should fire any time we publish a segment.
trigger DataObjectDataChangeEventTrigger on DataObjectDataChgEvent (after insert) {
for (DataObjectDataChgEvent event : Trigger.new) {
System.debug('Start Event');
System.debug('ActionDeveloperName: ' + event.ActionDeveloperName);
System.debug('EventCreationDateTime: ' + event.EventCreationDateTime);
System.debug('EventPrompt: ' + event.EventPrompt);
System.debug('EventPublishDateTime: ' + event.EventPublishDateTime);
System.debug('EventSchemaVersion: ' + event.EventSchemaVersion);
System.debug('EventType: ' + event.EventType);
System.debug('EventUuid: ' + event.EventUuid);
System.debug('Offset: ' + event.Offset);
System.debug('PayloadCurrentValue: ' + event.PayloadCurrentValue);
System.debug('PayloadPrevValue: ' + event.PayloadPrevValue);
System.debug('PayloadSchema: ' + event.PayloadSchema);
System.debug('ReplayId: ' + event.ReplayId);
System.debug('SourceObjectDeveloperName: ' + event.SourceObjectDeveloperName);
System.debug('End Event');
}
}
Event Attribute Name | Description |
---|---|
ActionDeveloperName | The API name of our Data Action that we created earlier. |
EventPrompt | Will be either DELETE, INSERT, or UPDATE. We should take action accordingly. |
EventType | The type of event that caused the event to fire. CDC stands for Change Data Capture. |
SourceObjectDeveloperName | The name of the object that has had a data change on it. AccountContact_SM_1741706103380__dlm is our API name for Account Contact – Latest. |
PayloadCurrentValue | Current data value with enriched fields. If you open the Data Action in Data Cloud and view the Attributes related list, you’ll see that these match up with the payload. |
Before adding any additional logic, we should check that the events are firing as expected. We’ll set a debug log on the Automated Process user and then see if we are receiving debug logs in the developer console.
In Setup quick find, go to Debug Logs → New, and set a trace on the Automated Process entity.

Now, let’s publish our segment and see if a log fires. Navigate to the segment that we set up and hit the Publish Now button.

Once we click Publish, Now our Segment will enter the publication queue. It could be 15 minutes or so before we receive our platform event.
Our segment publication will be complete once the segment publish status is equal to Success.
To ensure that our segment is publishing as expected, we can leverage the Data Explorer.
In Data Cloud, navigate to Data Explorer → choose the appropriate Data Space → Choose Data Model Object → Choose Account Contact – Latest.
Once the segment has successfully published, you should see your Account Contact record here. To filter, you can use the filter option and enter the segment Id, and you can also find the segment Id in the URL when you open your segment.

There are a couple of important pieces of information to note in the above screenshot. For each row in the Account Contact – Latest DMO, we have an Id and a Segment Id. The Id represents the Account Contact Id, and the segment Id represents the segment on which we clicked the Published button.
If we hit refresh on the Debug Logs page, we should see a debug log from the Automated Process user. The Operation should be listed as a Platform Event. Let’s open the Debug Log and look at some of the information we receive.

I’ve extracted the interesting pieces of information from the System.debug statements we set in the Trigger.
ActionDeveloperName: Account_Contact_Segment_CRUD
EventPrompt: INSERT
EventType: CDCEvent
SourceObjectDeveloperName: AccountContact_SM_1741706103380__dlm
PayloadCurrentValue: {
"AccountContact_SM_1741706103380__dlm_Delta_Type__c": "new",
"AccountContact_SM_1741706103380__dlm_Id__c": "003gL0000009v10QAA",
"AccountContact_SM_1741706103380__dlm_KQ_Id__c": null,
"AccountContact_SM_1741706103380__dlm_Parent_Segment_Id__c": null,
"AccountContact_SM_1741706103380__dlm_Segment_Id__c": "1sggL00000000hZ",
"AccountContact_SM_1741706103380__dlm_Snapshot_Type__c": "F",
"AccountContact_SM_1741706103380__dlm_Timestamp__c": "2025-03-11 20:22:13",
"AccountContact_SM_1741706103380__dlm_Version_Stamp__c": "2025-03-11 20:20:43"
}
Our base setup is complete. We’ve ensured our platform events are firing when we publish segments, and we have subscribed to these events using an Apex Trigger.
Making Jane’s Job Easy
Before finishing off our trigger, let’s walk through the experience for Jane. Jane wants to generate Customer Coupon records for anyone in the Segment we created earlier. Before Jane publishes the segment, she needs to generate a Coupon record.
In the Customer Coupon Lightning Application, Jane will navigate to the Coupons tab and click New. Jane has two fields to fill in – A Coupon name, which she can name as anything she deems relevant, as well as a Segment Id.
We need the segment Id from Jane so that we can link Segment Members, i.e. Contacts, to this Coupon.

In our simple example, we’ll be getting the Segment Id from the URL in the segment screen. But in a real world scenario, you could opt to enhance the user experience by overwriting the New button, then leveraging an LWC or Flow to allow Jane to choose a segment from a list of available segments.
Unfortunately, Salesforce does not currently support Lookups to segments, hence the workaround.

Once we have the Segment Id, we can save the Coupon Record.

Now that we have a Coupon record that is associated with a segment Id, Jane is ready to publish the segment.
Once the segment is published, Jane should be able to see all of the Customer Coupon records associated with a Coupon record.

Creating the Trigger Logic
Our foundation is set, and our end goal is clear. Now, we can start writing code!
Our Trigger will need to account for the following items:
- Apply filters so that our logic only fires on appropriate platform events.
- Analyze relevant data from the event JSON strings
- Find Coupon records for which we should be creating Customer Coupon records.
- Create the Customer Coupon records.
Remember, we’re taking a simplified approach here – I am not going to handle duplicates, error handling, etc. as it would overcomplicate what I want you to gain from this article. We’ll keep it as simple as possible while still showing you how you can take action in Salesforce core from segment changes in Data Cloud.
I highly encourage you to follow good coding standards – such as using String constants, null checks, Field Level Security checks, JSON class wrappers, etc. – in a real-world implementation.
When creating your platform event trigger logic, keep in mind that there are some different limits specific to platform events you should check out. For example, a regular trigger will process 200 records at a time, while a platform event trigger will process up to 2000.
With all that said, here’s a sample trigger that we’ll leverage for our use case:
trigger DataObjectDataChangeEventTrigger on DataObjectDataChgEvent (after insert) {
// A Map from Segment Id to the Contacts that should be added to that segment
Map<Id/*Segment Id*/, Set<Id>/*Contact Ids*/> segmentIdToContactIds = new Map<Id, Set<Id>>();
//Loop over the platform events, filter for the relevant ones and gather the Segment Ids and Contact Ids
for (DataObjectDataChgEvent event : Trigger.new) {
//Check if this event is for our Data Action on Account Contact Segments
if (event.ActionDeveloperName == 'Account_Contact_Segment_CRUD'
&& event.EventType == 'CDCEvent'
&& event.SourceObjectDeveloperName == 'AccountContact_SM_1741706103380__dlm') {
Map<String, Object> payload = (Map<String, Object>) JSON.deserializeUntyped(event.PayloadCurrentValue);
Id segmentId = (Id) payload.get('AccountContact_SM_1741706103380__dlm_Segment_Id__c');
Id contactId = (Id) payload.get('AccountContact_SM_1741706103380__dlm_Id__c');
Set<Id> contactIds = segmentIdToContactIds.get(segmentId);
if (contactIds == null) {
contactIds = new Set<Id>();
}
contactIds.add(contactId);
segmentIdToContactIds.put(segmentId, contactIds);
}
}
//Now that we have all of the Segment Ids we can find the Coupon records that are related to those segments
if(!segmentIdToContactIds.isEmpty()) {
List<Customer_Coupon__c> customerCoupons = new List<Customer_Coupon__c>();
for(Coupon__c coupon : [SELECT Id, Segment_Id__c FROM Coupon__c WHERE Segment_Id__c IN :segmentIdToContactIds.keySet()]) {
if(segmentIdToContactIds.containsKey(coupon.Segment_Id__c)) {
//For each Coupon, create a Customer_Coupon__c record for each Contact in the Segment
for(Id contactId : segmentIdToContactIds.get(coupon.Segment_Id__c)) {
customerCoupons.add(
new Customer_Coupon__c(
Coupon__c = coupon.Id,
Contact__c = contactId
)
);
}
}
}
//Insert the Customer_Coupon__c records
insert customerCoupons;
}
}
The Home Stretch
All that’s left to do now is to hit the segment publish button and check if our Customer Coupon records get generated.
Once the segment finishes publishing, we’ll see the records created by our platform event trigger.

If you click into the Customer Coupon record, you’ll see it was created by the Automated Process user.

And with that, our sample use case is complete. The Customer Coupon records can now be easily exposed to customers on the customer portal. With this method, we were able to publish segments in Data Cloud and react to segment member changes within our Salesforce Core platform.
We have taken one of the core functionalities of Data Cloud (Segmentation) and used it to target specific customers on our Salesforce platform – pretty powerful stuff. Let’s hope Jane likes it!
Key Considerations
- When implementing a use case like this, consider the amount of data you’ll be processing. It might affect your approach.
- Always consider your Data Cloud usage credits.
- In some scenarios, it might be better to query Data Cloud data from Salesforce core rather than copying it over; both approaches have their pros and cons.
- Before jumping into an implementation, take a look through the Salesforce limits pages for the various features you plan on using.
Final Thoughts
Now that you’ve seen a full walkthrough of creating Data Cloud segments and acting on membership changes of those Segments in Salesforce core, I hope you can think up some of your own use cases where you can apply similar techniques. Be sure to grab yourself a Salesforce Developer Edition org with Data Cloud enabled so you can try this all out for yourself.