Sync Process Overview
Contact-Level Synchronization
WeGive syncs individual donors at the Contact level in Salesforce. Each individual Donor in WeGive corresponds to one Contact. The Contact’sAccountId is stored on the donor as salesforce_account_id and is used to link the donor to a WeGive Household when the Account is an NPSP Household Account.
Pulling Data from Salesforce
Pulling Contacts is enabled by the Pull donors toggle under Sync Configuration. When pulling, WeGive queries Contacts whose pull column is within the sync window. The pull column defaults toLastModifiedDate and can be changed with the pull_by integration setting.
The query always selects Id, AccountId, and CreatedDate, plus every Salesforce field referenced by an import or both-ways mapping rule for the Contact object. Fields that are not referenced by a rule are not requested from Salesforce.
If the contacts_with_emails_only setting is enabled, the query adds Email != null, so Contacts with no standard Email value are never pulled, merged, or deleted through this integration.
For each Contact returned, WeGive:
- Looks for an existing individual donor with a matching
salesforce_id. - If none is found and the mapped data includes an
email_1value, looks for an individual donor with the sameemail_1that has nosalesforce_idyet, and links it. - Otherwise creates a new donor.
- Applies the mapped standard fields, custom fields, and address blocks, then saves without triggering an outbound push.
Pushing Data to Salesforce
Pushing Contacts is enabled by the Push donors toggle under Sync Configuration. When an individual donor is created or updated in WeGive, the integration compiles a payload for the Salesforce Contact object from the hard-coded defaults listed below plus every export or both-ways mapping rule for the Contact object, then inserts or updates the Contact. See Contact Matching and Create/Update Logic for how the target Contact is chosen. Donors flagged as marketing-only contacts and donors excluded by an integration ignore rule are not pushed.How Contact Data Syncs
Direction:- Import from Salesforce - Data imports from Salesforce into WeGive only
- Export to Salesforce - Data exports from WeGive to Salesforce only
- Both Ways - Data syncs in both directions
- Configurable - Provided by a mapping rule that can be customized in the integration settings
- Configurable (mapping rule) - Reaches Salesforce only if a mapping rule references it; there is no built-in default
- Hard-coded - Built into the integration logic and cannot be changed
Standard Field Mappings
Address field pairing
Contact pairs the Salesforce Mailing Address (primary) with WeGivemailing_address, and the Salesforce Other Address (secondary) with WeGive billing_address. This differs from Account, which pairs Billing (primary) with billing_address and Shipping (secondary) with mailing_address.
On import, address values that come back empty are stored as empty strings. When a donor is created from Salesforce, both a mailing and a billing address row are always created, even if no address fields are mapped.
Communication preference flags
On import, the integration recognizes four opt-out fields and converts them to booleans:do_not_email, do_not_sms, do_not_mail, and do_not_contact. Any of them can be populated from a Salesforce field through a mapping rule. Only npsp__Do_Not_Contact__c is listed above because it is the only one with a standard NPSP counterpart.
Communication list subscriptions
A mapping rule whose WeGive target is namedCL_<list id> (for example CL_42) is treated as a subscription flag for WeGive communication list 42. On import, a truthy value subscribes the donor and a falsy value unsubscribes them. On export, each communication list’s api_name is available to mapping rules with the donor’s subscribed status as its value.
WeGive Package Fields
(Requires WeGive Salesforce managed package installation.)
If these fields are not visible in your Salesforce org, contact WeGive support about installing the WeGive Salesforce managed package.
State and Country Picklists
By default, Contact state and country are imported from Salesforce only, not exported. The integration deliberately omitsMailingState, MailingCountry, OtherState, and OtherCountry from the hard-coded export payload because writing free-text values to these fields fails in orgs that use Salesforce picklists. To sync state and country in both directions, add mapping rules:
- Free-text orgs: add a both-ways rule on the plain fields (
MailingState,MailingCountry,OtherState,OtherCountry) mapped to the WeGive value fields (mailing_address.state,mailing_address.country,billing_address.state,billing_address.country). - Picklist orgs: Salesforce State and Country/Territory Picklists is an org-wide setting. When enabled, state and country must be mapped through the code fields using a one-directional export/import split.
state_code, state_full, country_code, and country_full.
State and country mapping for picklist-enabled orgs (Contact):
The split is required because the WeGive value field (
state, country) is the writable column, while the code accessor (state_code, country_code) is read-only and derives the ISO code from the stored value. Exporting from the code accessor sends a valid ISO code that the restricted picklist accepts; importing into the value field lets the incoming code land in a writable column. A single both-ways rule cannot serve both directions.
For the customer-facing setup walkthrough (including the equivalent Account mapping and how to remove conflicting rules), see Configuring Salesforce State and Country Picklist Mappings in the Knowledge Base.
Important Notes
Email Logic
When sending donor data to Salesforce, WeGive selects which email to populate in the standard Email field based on the donor’s Preferred Email setting:
This is hard-coded logic.
Name defaults
The hard-coded export sendsFirstName and LastName exactly as stored on the donor. Separately, the data made available to export mapping rules substitutes FNU (First Name Unknown) for an empty first_name and LNU (Last Name Unknown) for an empty last_name. Whether a Contact ends up with FNU/LNU therefore depends on a mapping rule for first_name or last_name being present. Salesforce requires LastName, so a donor with no last name and no rule for last_name will fail to insert.
Address Concatenation
When sending addresses to Salesforce, Address Line 1 and Address Line 2 are joined with a single space into the Street field (MailingStreet or OtherStreet). Address fields are only sent when the donor actually has that address record; otherwise they are sent as null. Empty strings in any payload are converted to null before the request is made.
AccountId handling
AccountId is never part of the hard-coded export payload. There is one exception: when WeGive reuses an existing Salesforce Contact found by email (see below) and no mapping rule has set AccountId, the integration copies that Contact’s current AccountId back into the update payload so Salesforce portal-user validation rules are satisfied. It does not send the donor’s own salesforce_account_id.
After WeGive inserts a brand new Contact, it reads the Contact back from Salesforce to capture the AccountId that NPSP assigned (normally the automatically created Household Account) and stores it on the donor as salesforce_account_id. If the donor belongs to a WeGive family household that has no Salesforce ID yet, that household’s salesforce_id is set to the same Account ID. This is the only way a WeGive household receives a Salesforce ID from the WeGive side; households themselves are not pushed. See Account.
Understanding Configurable vs Hard-coded
- Configurable mappings can be customized through integration settings if needed for your organization’s specific field setup.
- Hard-coded mappings are built into the integration’s core logic and handle special business rules (like email selection and address formatting).
Contact Matching and Create/Update Logic
When WeGive exports an individual donor to Salesforce, the integration determines whether to create a new Contact or update an existing one: Step 1: Check for an existing Salesforce ID. If the WeGive donor already has asalesforce_id, the integration updates that Contact. If the update returns a 404 (the Contact was deleted or merged away in Salesforce), the stale salesforce_id is cleared and the donor goes through the create path below. If there is no salesforce_id, it proceeds to Step 2.
Step 2: Search by Email 1. If the donor has an email_1 value, the integration queries Salesforce for Contacts whose standard Email equals that value, ordered by most recently modified, and takes the first result. Only email_1 is used; email_2, email_3, and the Preferred Email setting do not affect matching. If the donor has no email_1, or no Contact matches, a new Contact is created.
Step 3: Verify Contact availability. If no other WeGive donor in the organization is already linked to the matched Contact (same salesforce_id and salesforce_account_id), the integration updates that Contact with the donor’s payload, and stores its Id and AccountId on the donor. If another WeGive donor is already linked to it, the integration inserts a new Contact instead, and leaves the existing Contact untouched.
A short-lived lock prevents two concurrent pushes of the same donor from creating duplicate Contacts.
Matching also happens in the import direction. A pulled Contact that does not match any donor by
salesforce_id is matched to an existing individual donor by email_1 when that donor has no salesforce_id yet. Otherwise a new donor is created.Household Membership on Import
When a Contact’sAccountId matches the salesforce_id of an existing WeGive family household, the imported donor is attached to that household and WeGive does not create an automatic household for them. If the donor previously belonged to a different household, they are moved. See Account for how households are created from Household Accounts.
Merged Contacts
The integration detects Contacts merged in Salesforce by pulling Contacts whoseMasterRecordId is set (always filtered by LastModifiedDate, regardless of the pull_by setting, because Salesforce only stamps standard system fields during a merge). If both the losing Contact and the master Contact are linked to WeGive individual donors, those two donors are merged in WeGive, with the donor linked to the master Contact surviving. If either side is not linked to a WeGive donor, nothing happens. The contacts_with_emails_only filter also applies to this query.
Deleted Contacts
If thepull_deleted_donors setting is enabled, the integration queries Contacts with IsDeleted = true in the sync window and deletes the matching WeGive individual donor (matched by salesforce_id). Contacts not linked to a WeGive donor are ignored. The contacts_with_emails_only filter applies here too.
Settings Reference
Related Documentation
- Data Mapping Overview - object index and cross-cutting data conventions
- Account - company and household mapping
- Configuring Salesforce State and Country Picklist Mappings - customer setup walkthrough in the Knowledge Base