Maintaining consistency in address fields is a simple but critical aspect of CRM hygiene. Whether you’re tracking customers, partners, or vendors, having synchronized billing and shipping information ensures accuracy across transactions, reports, and integrations.
In this blog, we walk through an efficient Apex trigger that keeps the Shipping Address aligned with the Billing Address on the Account object—only when the CopyBillingToShipping__c
checkbox is selected. This logic runs during updates, making sure any change to the billing address is immediately mirrored in the shipping fields.
This automation helps avoid mismatched data, reduces manual effort, and ensures the integrity of customer records across departments like sales, logistics, finance, and customer service.
🧠 Why Billing and Shipping Address Sync Matters
In many business processes, both billing and shipping details need to match—especially in:
-
B2B transactions
-
Contract delivery workflows
-
Invoice generation
-
Shipping operations
However, relying on users to manually update both sets of address fields increases the risk of inconsistency. With this trigger:
-
Data updates remain accurate and reliable
-
Users don’t have to repeat the same data entry
-
Teams have confidence that both addresses reflect the latest info
-
You reduce time spent fixing mismatches during critical processes
This automation gives your Salesforce instance a built-in safety net for address consistency.
🔍 What This Blog Covers
-
How to use a before update Apex trigger on the Account object
-
How to conditionally sync fields based on a checkbox (
CopyBillingToShipping__c
) -
Why comparing old and new checkbox values prevents unwanted overwrites
-
How to use handler classes to keep trigger logic clean and reusable
-
Where this kind of automation adds value in day-to-day CRM workflows
The trigger ensures that the shipping address fields only update when the checkbox is newly selected, making the logic intentional, controlled, and non-intrusive.
🎯 Real-World Use Cases for This Trigger
-
Sales teams managing Account updates with minimal data entry
-
Order processing or fulfillment teams who rely on correct shipping details
-
Finance teams using shipping fields in invoice or delivery document templates
-
Customer support reps needing consistent location details across teams
-
Admin teams who want to enforce logical consistency across records
This is especially helpful during integrations with ERPs or eCommerce platforms, where clean, mirrored address data is critical.
👨💻 Developer & Admin Tips
The trigger uses Trigger.oldMap
to compare the previous value of CopyBillingToShipping__c
with the current one. The address sync logic runs only when:
-
The checkbox is checked for the first time
-
The old value was
false
or unchecked
This prevents the trigger from overwriting shipping address values unintentionally during general updates where the checkbox remains unchanged.
All updates happen in the before update context, meaning no explicit DML operation is required—Salesforce will save the changes automatically with the record.
The logic is neatly tucked into a handler class method to promote reusability and testability, following best practices for scalable Apex architecture.
Always bulk-test this logic with batch updates and API jobs to ensure governor limits are respected and logic behaves as expected in multi-record updates.
🎥 Visual Walkthrough Available – YouTube Playlist
Want to see this trigger in action? Head over to the Salesforce Makes Sense YouTube playlist where this use case is featured step-by-step. You’ll learn:
-
How to structure your handler method
-
How to write and test the comparison logic using
oldMap
-
How to validate the sync behavior in your org
This playlist is designed for learners at all levels, giving you the confidence to replicate and extend the logic in your own environments.
Solution:
trigger AccountTrigger on Account (before update) {
if(Trigger.isUpdate){ if(Trigger.isBefore){
AccountTriggerHandler.copyBillToShip(Trigger.New,
Trigger.oldMap);
}
}
}
public class AccountTriggerHandler { public static void
copyBillToShip(List<Account> accList,Map<Id,Account> oldMap){
for(Account acc:accList){ if((oldMap==null && acc.CopyBillingToShipping__c) ||
(!oldMap.get(acc.Id).CopyBillingToShipping__c &&
acc.CopyBillingToShipping__c)){
acc.ShippingCity=acc.BillingCity;
acc.ShippingCountry=acc.BillingCountry;
acc.ShippingPostalCode=acc.BillingPostalCode;
acc.ShippingState=acc.BillingState; acc.ShippingStreet=acc.BillingStreet;
}
}
}
}