Tracking revenue at the account level is a foundational need for most Salesforce implementations. Whether you’re managing B2B sales, enterprise partnerships, or long-term client engagements, having a real-time reflection of all related deals helps teams stay aligned, make smarter decisions, and trust their dashboards.
In this blog, we explore a powerful Apex trigger that automatically calculates the total Opportunity Amount for all related Opportunities and updates the Account’s Annual Revenue field. This trigger runs whenever Opportunities are inserted, updated, or deleted, making sure the Account-level revenue metric always reflects the most recent deal data.
It’s the kind of automation that eliminates manual data entry, prevents reporting mismatches, and gives your CRM that extra layer of intelligence.
🧠 Why This Trigger Is Important
The Annual Revenue field on the Account object is often used in:
-
Pipeline and forecast dashboards
-
Strategic account planning
-
Territory and quota assignments
-
Executive reporting and board summaries
-
Segmentation and marketing targeting
Without automation, keeping this field up to date becomes a manual process—one that’s easily forgotten or inconsistently applied. If users don’t update it (or update it incorrectly), you risk:
-
Misleading revenue totals
-
Inaccurate dashboards and segmentation
-
Reduced confidence in CRM data
-
Missed opportunities in cross-sell, upsell, or renewals
This trigger solves that problem by automatically rolling up the sum of Opportunity Amounts into the Annual Revenue field—giving your users real-time insights, without lifting a finger.
🔍 What This Blog Covers
-
How to build a trigger that responds to Opportunity creation, updates, and deletions
-
Why updating Account fields based on related child records is a best practice
-
How this logic helps sync deal data to strategic metrics
-
The importance of running calculations during insert, update, delete, and undelete events
-
How to wrap this logic in a clean handler method for future scaling
This is a real-world example of data hygiene in action—one that pays off immediately in cleaner reports and smoother operations.
🎯 Real-World Use Cases for This Trigger
-
Sales operations teams automating forecast metrics
-
Customer success managers reviewing client potential based on deal history
-
Marketing teams segmenting accounts by revenue range
-
Finance teams assessing account-level revenue for billing or invoicing
-
Strategic planners prioritizing accounts with highest deal value
In any org where Opportunities flow into Accounts, this trigger ensures that parent records reflect the actual financial reality.
👨💻 Developer & Admin Tips
Here’s how the logic works in simple terms:
-
It collects the IDs of all affected Accounts based on the inserted, updated, or deleted Opportunities
-
For each of those Accounts, it calculates the total Opportunity Amount
-
It updates the Annual Revenue field on the Account to reflect the new total
-
It handles all events—insert, update, delete, and undelete—ensuring no gaps in tracking
All of this happens automatically, in the background, and with full support for bulk operations.
The logic is housed in a trigger handler method, making the code:
-
Modular
-
Testable
-
Easy to extend in the future
Want to take this further? You can:
-
Add filters to include only certain Opportunity stages (like Closed Won)
-
Use a custom field instead of Annual Revenue if needed
-
Trigger notifications when revenue thresholds are crossed
-
Update additional fields like “Largest Deal Value” or “Latest Closed Date”
Make sure to test this trigger with:
-
Single and batch Opportunity inserts
-
Updates that change Amount or Account associations
-
Deletes and undeletes from UI, API, and bulk tools
This ensures consistent, reliable behavior across every possible use case.
🎥 Watch It in Action – YouTube Playlist
For a visual walkthrough of this trigger and how to test it, visit the Salesforce Makes Sense YouTube playlist. The video demo includes:
-
A breakdown of the trigger logic
-
How the handler method calculates the total
-
Live updates to the Account’s Annual Revenue field
-
Tips for making the logic more dynamic or configurable
These tutorials make even complex concepts approachable and implementation-friendly.
Solution:
//Call this method for insert, update, delete and undelete event public static void populateAmountOnAccount(List<Opportunity>
oppList,Map<Id,,Opportunity> oldMap){ Set<Id> accIds = new Set<Id>();
for(Opportunity opp : oppList){ if(oldMap != null){
if(opp.AccountId!=null&&opp.Amount!=null&&opp.Amount!=old
Map.get(opp.Id).Amount){
accIds.add(opp.AccountId);
}
}else{ if(opp.AccountId != null && opp.Amount != null){
accIds.add(opp.AccountId);
}
}
}
List accList=[SELECT Id,AnnualRevenue,(SELECT Id, Amount
FROM Opportunities) FROM Account WHERE Id IN: accIds];
if(!accList.isEmpty()){ for(Account acc:accList){
Decimal total=0;
for(Opportunity opp:acc.Opportunities){
total=total+opp.Amount;
}
acc.AnnualRevenue=total;
}
}
if(!accList.isEmpty()){
update accList;
}
}