This guide is intended for advanced Salesforce admins. For Salesforce education, contact Salesforce directly or use trailheads for specific knowledge.
This guide walks you through building a record-triggered Salesforce Flow that automatically updates a contact's Natterbox Consent records when the standard Do Not Call checkbox on the Contact changes. The flow handles both directions in a single automation: opting the customer out when Do Not Call is ticked, and opting them back in when it is unticked. This is useful when a customer requests opt-in or opt-out through a channel other than messaging, for example a web form, a phone call, or an email.
Prerequisites
Natterbox Messaging is configured in your Salesforce org with the Natterbox managed package installed.
At least one Natterbox Consent record exists in your org. Consent records are created automatically when messaging conversations begin.
You have the System Administrator profile, or the Manage Flows permission.
You understand how the Natterbox consent model works, in particular that a consent record represents a unique phone-number pairing (your number and the customer's number), not a contact. See Keywords & Consent.
How consent records work
Before building the flow, it is important to understand the fields the flow will set. A Natterbox Consent record (nbavs__Consent__c) is considered active based on a combination of three fields: nbavs__Status__c, nbavs__Temporary__c, and nbavs__ConsentEndTime__c. Only certain combinations of these values are valid.
Status | Temporary | Consent End Time | Meaning |
|---|---|---|---|
| Unchecked (false) | Empty | Permanent consent. The record is active indefinitely. |
| Checked (true) | Set (in the future) | Temporary consent (for example, implied consent when a customer messages in first). The record is active only until the end time. |
| Unchecked (false) | Set (now) | Opted out. The record is not active. |
Always set the Consent End Time when opting out
Setting
Status = Opt OutwithTemporary = falsebut leaving the Consent End Time empty produces an invalid state that can break consent processing on a live org. Whenever this flow opts a contact out, it must also set the Consent End Time to the current date and time. Likewise, when opting a contact back in permanently, the flow must clear the Consent End Time.
The flow therefore sets the fields as follows:
Do Not Call = true (opt out): Status =
Opt Out, Temporary =false, Consent End Time = the current date and time.Do Not Call = false (opt in): Status =
Opt In, Temporary =false, Consent End Time = cleared (empty), giving permanent consent.
Matching consent records to a contact
The Natterbox Consent object does not have a lookup to the Contact. Instead, each record stores the customer's number in nbavs__ExternalAddress__c and your number in nbavs__InternalAddress__c. To find a contact's consent records, the flow matches nbavs__ExternalAddress__c against the contact's phone number.
A single customer number can be paired with several different Natterbox-owned numbers (for example a sales line and a support line), and each pairing is a separate consent record. To catch every one of them, the flow first retrieves all consent records whose External Address matches the contact's number, then loops through the returned collection so that each record is evaluated and updated individually.
Phone number format matters
The External Address is stored as full international digits with no plus sign, spaces, or punctuation, for example
447450295814(UK) or12483454273(US). A standard Contact phone field such asMobilePhoneis usually stored with formatting (for example+44 7450 295814or(248) 345-4273), so a direct comparison will not match. Before comparing, strip the formatting from the contact's number, and make sure it resolves to the same international format (including country code) as the stored External Address. The most reliable approach is to hold a normalised, digits-only version of the number on the Contact.
Building the flow
Step 1: Create a new record-triggered flow
Click the Setup cog in Salesforce and select Setup.
In the Quick Find box, search for Flows and click Flows.
Click New Flow.
Select Start From Scratch and then Next.
Select type Record-Triggered Flow and then Create.
Step 2: Configure the trigger (Start element)
Click the Start element and configure the following:
Object:
ContactTrigger the Flow When: A record is updated
Condition Requirements: Formula Evaluates to True
Formula:
ISCHANGED({!$Record.DoNotCall})Optimize the Flow for: Actions and Related Records
This ensures the flow only runs when the Do Not Call field actually changes value, rather than on every Contact update.
Step 3: Create a phone-matching formula
Create a formula resource that strips formatting from the contact's number so it can be compared against the stored External Address.
In the Toolbox, next to Manager, click New Resource.
Resource Type: Formula.
API Name:
forExternalAddress.Data Type: Text.
Formula (adjust to match the phone field you use, and to prefix a country code if required by your data):
SUBSTITUTE( SUBSTITUTE( SUBSTITUTE( SUBSTITUTE( SUBSTITUTE({!$Record.MobilePhone}, "+", ""), " ", ""), "-", ""), "(", ""), ")", "")Click Done.
Step 4: Retrieve the consent records (Get Records)
This element retrieves every consent record for the contact's number, across all of the Natterbox-owned numbers it may be paired with.
Click the + icon after the Start element and select Get Records.
Label:
Get Consent Record.Object:
Natterbox Consent(nbavs__Consent__c).Filter Natterbox Consent Records (All Conditions Are Met):
Field:
nbavs__ExternalAddress__cOperator:
EqualsValue:
{!forExternalAddress}
How Many Records to Store: All records.
How to Store Record Data: Automatically store all fields.
Click Done.
Step 5: Add a Decision element
The Decision element determines which path to follow based on the current value of the Do Not Call field.
Click the + icon after the Get Records element and select Decision.
Label:
Check Do Not Call Value(the API Name auto-populates).Configure the first outcome:
Label:
Do Not Call is TrueCondition Requirements: All Conditions Are Met (AND)
Resource:
{!$Record.DoNotCall}Operator:
EqualsValue:
{!$GlobalConstant.True}
Rename the Default Outcome to
Do Not Call is False.Click Done.
Step 6: Opt Out path (loop and update)
Under the Do Not Call is True outcome, loop through the consent records and opt out each one that is not already opted out.
Under the Do Not Call is True outcome, click the + icon and select Loop.
Label:
Loop for all consent records.Collection Variable:
{!Get_Consent_Record}.Direction: First item to last item. Click Done.
Inside the loop, on the For Each path, click the + icon and select Decision.
Label:
Check if record needs updating. Configure the first outcome:Label:
Record needs updatingCondition Requirements: All Conditions Are Met (AND)
Resource:
{!Loop_for_all_consent_records.nbavs__Status__c}Operator:
EqualsValue:
Opt In
Rename the Default Outcome to
No change to record, then click Done. Records that are already opted out follow this path and are left untouched.Under the Record needs updating outcome, click the + icon and select Update Records.
Label:
Update Consent to Opt Out.How to Find Records to Update and Set Their Values: Specify conditions to identify records, and set fields individually.
Object:
Natterbox Consent(nbavs__Consent__c).Filter Natterbox Consent Records (All Conditions Are Met):
Field:
IdOperator:
EqualsValue:
{!Loop_for_all_consent_records.Id}
Set Field Values for the Natterbox Consent Records:
nbavs__Status__c- Value:Opt Outnbavs__Temporary__c- Value:{!$GlobalConstant.False}nbavs__ConsentEndTime__c- Value:{!$Flow.CurrentDateTime}
Click Done.
Step 7: Opt In path (loop and update)
Under the Do Not Call is False (Default) outcome, loop through the consent records and permanently opt in each one that is not already permanently opted in.
Under the Do Not Call is False outcome, click the + icon and select Loop.
Label:
Loop for all consent records.Collection Variable:
{!Get_Consent_Record}.Direction: First item to last item. Click Done.
Inside the loop, on the For Each path, click the + icon and select Decision.
Label:
Check if record needs updating. Configure the first outcome:Label:
Record needs updatingCondition Requirements: Any Condition Is Met (OR)
Row 1:
{!Loop_for_all_consent_records.nbavs__Status__c}Does Not EqualOpt InRow 2:
{!Loop_for_all_consent_records.nbavs__Temporary__c}Equals{!$GlobalConstant.True}Row 3:
{!Loop_for_all_consent_records.nbavs__ConsentEndTime__c}Is Null{!$GlobalConstant.False}
Rename the Default Outcome to
No change to record, then click Done. Records that are already permanently opted in follow this path and are left untouched.Under the Record needs updating outcome, click the + icon and select Update Records.
Label:
Update Consent to Opt In.How to Find Records to Update and Set Their Values: Specify conditions to identify records, and set fields individually.
Object:
Natterbox Consent(nbavs__Consent__c).Filter Natterbox Consent Records (All Conditions Are Met):
Field:
IdOperator:
EqualsValue:
{!Loop_for_all_consent_records.Id}
Set Field Values for the Natterbox Consent Records:
nbavs__Status__c- Value:Opt Innbavs__Temporary__c- Value:{!$GlobalConstant.False}nbavs__ConsentEndTime__c- add the field and leave the value blank to clear it (permanent consent has no end time).
Click Done.
Why loop instead of a single bulk update?
Looping lets the flow evaluate each consent record on its own and only update the ones that actually need changing, using the Check if record needs updating decision. Records already in the correct state take the No change to record path, which avoids unnecessary record updates and keeps the automation efficient when a contact has several pairings.
Step 8: Add fault paths (recommended)
Add a fault path to each Update Records element so that failures are handled gracefully rather than causing the whole transaction to roll back silently.
Hover over an Update Records element and click the + on the Fault connector.
Add an action to record or surface the error, for example a Create Records element that logs the fault, or an email alert to an administrator.
Repeat for the second Update Records element.
If no consent record matches
The Get Records element filters by phone number. If a contact has no consent record for that number yet, the returned collection is empty, the loop runs zero times, and nothing is updated. This is expected: a consent record is created the first time a conversation takes place on that number pairing.
Step 9: Save and activate the flow
Click Save.
Enter a Flow Label, for example
Update Natterbox Consent on Do Not Call Change.Click Save.
Once saved, click Activate to make the flow live.
Understanding multiple consent records
A single contact can have several consent records, because consent is stored per phone-number pairing. Multiple records can exist when:
The customer has been contacted on more than one of their own numbers (for example, mobile and landline).
Your organisation uses more than one Natterbox-owned number (for example, a sales line and a support line), so the same customer number is paired with each.
The Get Records element retrieves every consent record whose External Address matches the contact's number, regardless of which Natterbox-owned number it is paired with. The Loop then processes each record in turn, and the Check if record needs updating decision ensures only the records that require a change are updated.
Matching more than one customer number
This flow matches a single contact phone field (
MobilePhonein the example formula). If a contact can be reached on several of their own numbers and you want to update the consent records for all of them, create a formula for each number and expand the Get Records filter using Any Condition Is Met (OR). Speak with your Natterbox administrator about your specific requirements.
Testing the flow
Test the automation in a sandbox or on test data before relying on it in production.
Identify a Contact whose phone number matches the
nbavs__ExternalAddress__cof one or more existing consent records.Open the Contact, tick the Do Not Call checkbox, and save.
Open the related Natterbox Consent records and confirm that Status is
Opt Out, Temporary is unchecked, and Consent End Time is populated with the current date and time.Edit the Contact again, untick Do Not Call, and save.
Confirm the consent records now show Status
Opt In, Temporary unchecked, and Consent End Time empty.If the contact has multiple matching consent records, verify that all of them were updated.
You can inspect the records directly in the Developer Console with a query such as:
SELECT Id, nbavs__ExternalAddress__c, nbavs__InternalAddress__c,
nbavs__Status__c, nbavs__Temporary__c, nbavs__Active__c,
nbavs__ConsentStartTime__c, nbavs__ConsentEndTime__c
FROM nbavs__Consent__c
WHERE LastModifiedDate = TODAYDebugging tip
If the flow does not appear to fire, open it in Setup → Flows and use Debug to run it against a specific Contact. Check Setup → Process Automation → Paused and Failed Flow Interviews for errors.
Troubleshooting
Issue | Possible cause | Solution |
|---|---|---|
Flow does not fire when Do Not Call changes | The flow is not activated, or the entry-condition formula has a syntax error. | Confirm the flow is active and that the formula reads exactly |
Consent records are not updated | The Get Records element returned nothing because the contact's phone number does not match the stored External Address format. | Compare the value of your |
Consent processing breaks after an opt out | The record was set to Opt Out with Temporary unchecked but no Consent End Time. | Ensure the Opt Out path sets |
Only some consent records are updated | The Get Records filter matched only one pairing, or some records took the No change to record path. | Confirm the External Address on each pairing matches the normalised number, and review the Check if record needs updating conditions. |
Status value not accepted | The picklist value does not exactly match the values on the Consent object. | Confirm the values under Object Manager → Natterbox Consent → Fields & Relationships → Status. They should be |