Setting Up: Sendoso Spend Rollups in Salesforce

  • Updated

Introduction

As an alternative to viewing Sendoso spend one record at a time, you can roll Sendoso writeback spend up the Salesforce data model — from Lead to Contact to Account — so AEs and CSMs see total Sendoso program investment per account in reports, list views, and dashboards. 

This setup uses standard Salesforce Currency fields, a Contact-level formula field, a Lead → Contact conversion mapping, and one record-triggered flow.

You will need Salesforce admin permissions to complete this setup, including Customize Application and Manage Flows.

This article assumes the Sendoso ↔ Salesforce integration is already connected and writing back send data, and that the Sendoso writeback fields have been mapped per Setting Up: Additional Salesforce Tracking Fields and Activity Mapping.


Lead-Level Field Setup

To get started, go to 'Setup' and find Object Manager → Lead → Fields & Relationships.

Create a new Currency field on the Lead object using the values below.

Setting Value
Type Currency
Field Label Total $ Spent on Lead
Field Name Total_Spent_On_Lead
Length 16
Decimal Places 2
Description Total $ spent via Sendoso while this person was a Lead. Populated by the Sendoso ↔ Salesforce writeback.

shot-01-lead-field-form.png

Grant the Sendoso integration user Edit access via the permission set or profile that controls integration access (typically named something like Sendoso_Fields_Access):

  1. Setup → Permission Sets (or Profiles)
  2. Open the permission set assigned to the Sendoso integration user
  3. Object Settings → Lead → click Edit
  4. Set Read and Edit on Total $ Spent on Lead
  5. Save
shot-02-lead-fls.png

End-user profiles can be Read-Only.

Add the field to the 'Sendoso' section of any Lead page layouts that should display it.

This field is populated by Sendoso, not by Salesforce. Do not put a formula or default value on it.


Contact-Level Field Setup

You will create three custom fields on the Contact object. Two are populated by Sendoso, the third is a formula that adds them together.

shot-03-contact-three-fields.png

Go to 'Setup' and find Object Manager → Contact → Fields & Relationships.

Step 1 – Create Total $ Spent on Contact

Create a new Currency field using the values below.

Setting Value
Type Currency
Field Label Total $ Spent on Contact
Field Name Total_Spent_On_Contact
Length 16
Decimal Places 2
Description Total $ spent via Sendoso on this Contact since they became a Contact. Populated by the Sendoso ↔ Salesforce writeback.

Step 2 – Create Total $ Spent on Lead

Create a second Currency field using the values below.

Setting Value
Type Currency
Field Label Total $ Spent on Lead
Field Name Total_Spent_On_Lead
Length 16
Decimal Places 2
Description Total $ spent on this recipient while they were a Lead. Populated via Lead conversion mapping so Sendoso spend history is preserved after Lead-to-Contact conversion.

Step 3 – Create Total $ Sendoso Spend (formula)

Create a Formula field with return type Currency.

Setting Value
Type Formula → Currency
Field Label Total $ Sendoso Spend
Field Name Total_Overall_Sendoso_Spend
Decimal Places 2
Treat blank fields as Zero
Description Total overall Sendoso spend on this Contact across their lifetime, including spend accumulated while they were a Lead.

Paste the formula below into the formula editor:

Total_Spent_On_Contact__c + Total_Spent_On_Lead__c

shot-04-contact-formula.png

If your org has multi-currency enabled, wrap each field in convertCurrency(...) to keep totals in a consistent currency.

After all three fields are created, grant the Sendoso integration user the right access on each:

  1. Setup → Permission Sets (or Profiles)
  2. Open the permission set assigned to the Sendoso integration user
  3. Object Settings → Contact → click Edit
  4. Set Read and Edit on Total $ Spent on Contact and Total $ Spent on Lead
  5. Set Read on Total $ Sendoso Spend (formula fields are read-only by design)
  6. Save

End users typically need Read access on all three fields.

shot-05-contact-fls.png

Configure Sendoso Writeback to the New Fields

After creating the Lead and Contact fields, the Sendoso platform must be told to write to these specific Salesforce field API names. Without this step, Sendoso continues writing to its default fields and the new fields stay empty — even though the SFDC setup is complete.

Confirm with your Sendoso admin or Sendoso Customer Success Manager that the writeback configuration in Sendoso is mapped to:

Salesforce Object Sendoso writeback field New API name to map to
Lead Total $ Spent on Lead Total_Spent_On_Lead__c
Contact Total $ Spent on Contact Total_Spent_On_Contact__c

Refer to Setting Up: Additional Salesforce Tracking Fields and Activity Mapping for the field-mapping UI inside the Sendoso platform.

Until the Sendoso side is mapped, sending a gift will not populate the new fields. The Account rollup will stay at $0 even after the flow is deployed and active.


Lead → Contact Conversion Mapping

Without this step, Sendoso spend that accumulates on a Lead is lost the moment that Lead converts. The Account-level total will undercount lifetime spend for any Contact who entered as a Lead.

Go to Setup → Object Manager → Lead → Fields & Relationships → Map Lead Fields.

Find Total_Spent_On_Lead__c (Lead) and map it to Total_Spent_On_Lead__c (Contact). 

Save.

shot-06-map-lead-fields.png

After mapping, convert a test Lead with a non-zero Total $ Spent on Lead. Open the resulting Contact and confirm the value carried over and that Total $ Sendoso Spend reflects it.


Account-Level Field Setup

Go to Setup → Object Manager → Account → Fields & Relationships.

Create a new Currency field using the values below.

Setting Value
Type Currency
Field Label Total Sendoso Spend
Field Name Total_Sendoso_Spend
Length 16
Decimal Places 2
Description Total Sendoso spend across all Contacts on this Account. Populated by the Account Sendoso Rollup flow whenever a Contact on this Account is created or updated.
shot-07-account-field-form.png
shot-08-account-fls.png

Set field-level security:

  • End users: Read-Only
  • Sendoso integration user: Read-Only
  • Automated Process User and any user profile that triggers the flow (typically by saving Contact records): Edit

The flow runs in system context but writes the Account update on behalf of the user who triggered the save. If that user does not have Edit FLS on Account → Total Sendoso Spend, the flow will fail.

Add the field to the 'Sendoso' section of Account page layouts.


Account Rollup Flow Setup

The rollup is implemented as a record-triggered flow on the Contact object that fires after save (Create and Update). It pulls every Contact on the Account, sums Total $ Sendoso Spend, and writes the total back to Account → Total Sendoso Spend.

There are two ways to build this flow. Deloy the flow XML or Build the flow in Flow Builder.

Option A – Deploy the flow XML

If you are comfortable deploying metadata, save the XML below as Account_Sendoso_Rollup.flow-meta.xml in your force-app/main/default/flows/ directory and deploy with sf project deploy start.

Code Block for Account Sendoso Rollup Flow:

<?xml version="1.0" encoding="UTF-8"?>
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>58.0</apiVersion>
    <label>Account Sendoso Rollup</label>
    <description>Recalculates Account.Total_Sendoso_Spend__c as the sum of Total_Overall_Sendoso_Spend__c across all Contacts on the Account. Fires after save on Contact create or update.</description>
    <interviewLabel>Account Sendoso Rollup {!$Flow.CurrentDateTime}</interviewLabel>
    <processType>AutoLaunchedFlow</processType>
    <status>Active</status>
    <environments>Default</environments>

    <start>
        <object>Contact</object>
        <recordTriggerType>CreateAndUpdate</recordTriggerType>
        <triggerType>RecordAfterSave</triggerType>
        <connector>
            <targetReference>Has_Account</targetReference>
        </connector>
    </start>

    <decisions>
        <name>Has_Account</name>
        <label>Has Account</label>
        <defaultConnectorLabel>No Account</defaultConnectorLabel>
        <rules>
            <name>Yes_Has_Account</name>
            <label>Yes</label>
            <conditionLogic>and</conditionLogic>
            <conditions>
                <leftValueReference>$Record.AccountId</leftValueReference>
                <operator>IsNull</operator>
                <rightValue>
                    <booleanValue>false</booleanValue>
                </rightValue>
            </conditions>
            <connector>
                <targetReference>Get_All_Contacts</targetReference>
            </connector>
        </rules>
    </decisions>

    <recordLookups>
        <name>Get_All_Contacts</name>
        <label>Get All Contacts On Account</label>
        <object>Contact</object>
        <getFirstRecordOnly>false</getFirstRecordOnly>
        <storeOutputAutomatically>true</storeOutputAutomatically>
        <queriedFields>Id</queriedFields>
        <queriedFields>Total_Overall_Sendoso_Spend__c</queriedFields>
        <filterLogic>and</filterLogic>
        <filters>
            <field>AccountId</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>$Record.AccountId</elementReference>
            </value>
        </filters>
        <connector>
            <targetReference>Init_Sum</targetReference>
        </connector>
    </recordLookups>

    <variables>
        <name>totalSum</name>
        <dataType>Number</dataType>
        <scale>2</scale>
        <isCollection>false</isCollection>
        <isInput>false</isInput>
        <isOutput>false</isOutput>
    </variables>

    <assignments>
        <name>Init_Sum</name>
        <label>Initialize Sum</label>
        <assignmentItems>
            <assignToReference>totalSum</assignToReference>
            <operator>Assign</operator>
            <value>
                <numberValue>0.0</numberValue>
            </value>
        </assignmentItems>
        <connector>
            <targetReference>Loop_Contacts</targetReference>
        </connector>
    </assignments>

    <loops>
        <name>Loop_Contacts</name>
        <label>Loop Contacts</label>
        <collectionReference>Get_All_Contacts</collectionReference>
        <iterationOrder>Asc</iterationOrder>
        <nextValueConnector>
            <targetReference>Add_To_Sum</targetReference>
        </nextValueConnector>
        <noMoreValuesConnector>
            <targetReference>Update_Account</targetReference>
        </noMoreValuesConnector>
    </loops>

    <assignments>
        <name>Add_To_Sum</name>
        <label>Add Contact Spend To Sum</label>
        <assignmentItems>
            <assignToReference>totalSum</assignToReference>
            <operator>Add</operator>
            <value>
                <elementReference>Loop_Contacts.Total_Overall_Sendoso_Spend__c</elementReference>
            </value>
        </assignmentItems>
        <connector>
            <targetReference>Loop_Contacts</targetReference>
        </connector>
    </assignments>

    <recordUpdates>
        <name>Update_Account</name>
        <label>Update Account Total</label>
        <object>Account</object>
        <filterLogic>and</filterLogic>
        <filters>
            <field>Id</field>
            <operator>EqualTo</operator>
            <value>
                <elementReference>$Record.AccountId</elementReference>
            </value>
        </filters>
        <inputAssignments>
            <field>Total_Sendoso_Spend__c</field>
            <value>
                <elementReference>totalSum</elementReference>
            </value>
        </inputAssignments>
    </recordUpdates>
 </Flow>

After deploying, activate the flow:

  1. Setup → Process Automation → Flows
  2. Find Account Sendoso Rollup
  3. Click the dropdown arrow on the right → View Details and Versions
  4. Click Activate on the most recent version

The XML above is stripped of canvas coordinates. The flow will deploy and run identically — Flow Builder will auto-layout the elements the first time you open it.

Option B – Build the flow in Flow Builder

If you would rather click-build, navigate to Setup → Process Automation → Flows → New Flow → Record-Triggered Flow.

shot-09-flow-trigger-config.png

Configure the trigger:

Setting Value
Object Contact
Trigger A record is created or updated
Optimize the Flow for Actions and Related Records
Set conditions None

This flow has no entry criteria by design. It fires on every Contact create or update. For high-volume orgs, add an entry condition like ISCHANGED(Total_Overall_Sendoso_Spend__c) OR ISNEW() to reduce flow runs. For bulk loads (Data Loader, API, or background sync) of 200+ Contacts on the same Account, consider deactivating the flow during the load and running the backfill in the next section once the load completes.

Build the flow with six elements wired in this order.

Step 1 – Decision element: Has Account
Setting Value
Label Has Account
Outcome Yes
Condition $Record → AccountId Is Null False
Default outcome No Account (end the flow)
shot-10-flow-decision.png
Step 2 – Get Records: Get All Contacts On Account
Setting Value
Object Contact
Filter AccountId Equals $Record → AccountId
Number of records to store All records
How to store record data Choose fields and let Salesforce do the rest (Id, Total_Overall_Sendoso_Spend__c)
shot-11-flow-getrecords.png
Step 3 – Variable: totalSum

Create a flow Resource → Variable.

Setting Value
API Name totalSum
Data Type Number
Scale 2
Available for input No
Available for output No
shot-12-flow-variable.png
Step 4 – Assignment: Initialize Sum
Setting Value
Variable {!totalSum}
Operator Equals
Value 0
shot-13-flow-init-assignment.png
Step 5 – Loop: Loop Contacts
Setting Value
Collection variable {!Get_All_Contacts}
Direction First item to last item

Inside the loop, add an Assignment element Add Contact Spend To Sum:

Setting Value
Variable {!totalSum}
Operator Add
Value {!Loop_Contacts.Total_Overall_Sendoso_Spend__c}
shot-14-flow-loop-inner.png
Step 6 – Update Records: Update Account Total
Setting Value
How to find records Specify conditions
Object Account
Filter Id Equals $Record → AccountId
Field to update Total_Sendoso_Spend__c → {!totalSum}
shot-15-flow-update.png

Save the flow as Account Sendoso Rollup and Activate.

shot-17-flow-activate.png

Backfilling Existing Records

The flow only fires when a Contact is created or updated. If the org already has Sendoso spend on Contacts that have not been edited since the flow was activated, run a one-time backfill to populate the Account totals.

Open the Salesforce Developer Console → Debug → Open Execute Anonymous Window. Paste and run:

List<Contact> contactsToTouch = [
   SELECT Id FROM Contact WHERE AccountId != null
];
update contactsToTouch;
shot-18-execute-anon.png

For orgs with more than ~10,000 Contacts, run the backfill in batches with Data Loader instead of Execute Anonymous to avoid governor limits.


Verify Everything Works

Before waiting on real Sendoso send data, run a manual test to confirm the flow is wired correctly.

  1. Open any Contact record on an Account that has multiple Contacts
  2. Edit the Contact and set Total $ Spent on Contact to 100
  3. Save
  4. Open the parent Account
  5. Confirm Total Sendoso Spend increased by exactly $100

Once the manual test passes, your end-state should look like this once Sendoso writeback is flowing:

Object Field Expected Value
Lead (pre-conversion) Total $ Spent on Lead Sendoso writeback amount
Contact (post-conversion) Total $ Spent on Lead Same value carried over from the Lead
Contact Total $ Spent on Contact Sendoso writeback amount accumulated as a Contact
Contact Total $ Sendoso Spend Sum of the two fields above
Account Total Sendoso Spend Sum of Total $ Sendoso Spend across every Contact on the Account

To confirm the flow is firing on real saves, go to Setup → Process Automation → Flows → Account Sendoso Rollup → View Details and Versions and check the recent Interview history.

shot-19-verify-account.png

Troubleshooting

Problem Solution
Account → Total Sendoso Spend stays at $0 Confirm the Contact records on that Account have non-zero Total $ Sendoso Spend. If Contact fields are also $0, confirm the Sendoso side has been mapped to the new field API names (see Configure Sendoso Writeback to the New Fields).
Lead spend is lost after conversion Confirm the Lead → Contact field mapping is wired (Setup → Object Manager → Lead → Map Lead Fields).
Sendoso spend on an unconverted Lead is not on any Account Expected. Account totals only include spend on Contacts. Spend on Leads that never convert is visible only on the Lead record itself.
Account total is stale after a Contact is deleted The base flow does not fire on Contact delete. Touch any other Contact on the Account, or extend the flow to also trigger on Before Delete.
Account total is stale after a Contact is reparented The flow updates the new Account but not the old one. Touch a Contact on the prior Account, or extend the flow to recalculate the prior AccountId.
Flow throws "Insufficient Privileges" on the Account update Grant Edit FLS on Account → Total Sendoso Spend to the user profiles that trigger the flow (anyone whose actions cause Contact saves).
New Sendoso sends do not populate Lead or Contact spend fields The Sendoso platform writeback is still pointing at default fields. Map the Sendoso side to Total_Spent_On_Lead__c and Total_Spent_On_Contact__c per the Configure Sendoso Writeback to the New Fields section.
Roll-Up Summary Field option is greyed out on Account Account → Contact is a lookup, not master-detail. Roll-Up Summary is not available — that is why this article uses a flow.
Custom field references break after rename The flow references Contact.Total_Overall_Sendoso_Spend__c and Account.Total_Sendoso_Spend__c. Keep those API names stable. The underlying writeback fields can be renamed if you also update the Contact formula.

Related Articles

Was this article helpful?

0 out of 0 found this helpful

Have feedback about this article? Click here to share your thoughts.