> ## Documentation Index
> Fetch the complete documentation index at: https://wegive.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Communication Lists & Preferences

> Mapping between WeGive Communication Lists and Preferences to Salesforce custom objects

**Salesforce Objects:**

* `wegive__Communication_List__c` (custom object - Lists)
* `wegive__Communication_Preference__c` (custom object - Preferences/Subscriptions)

**WeGive Models:**

* CommunicationList
* CommunicationListDonor (pivot/junction table)

## Overview

This document describes how communication list and preference data syncs between WeGive and Salesforce. These objects work together to manage donor communication preferences and subscriptions:

* **Communication Lists** - Define the list/segment itself (e.g., "Monthly Newsletter", "Event Updates")
* **Communication Preferences** - Track which donors are subscribed to which lists

**Note:** These features require the WeGive managed package to be installed in Salesforce, which includes the custom communication objects.

***

# Part 1: Communication Lists

**Salesforce Object:** `wegive__Communication_List__c`\
**WeGive Model:** CommunicationList

## How Communication List 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

### Mapping Types

* **Hard-coded** - Built into the integration logic and cannot be changed

***

## Sync Triggers - Lists

### From WeGive to Salesforce (Export)

Communication List data is exported from WeGive to Salesforce when:

* **List Created:** A new communication list is created in WeGive
* **List Updated:** An existing list is modified in WeGive (e.g., name changed, description updated, settings modified)

The export happens automatically after the create or update action in WeGive.

### From Salesforce to WeGive (Import)

Communication List data is imported from Salesforce to WeGive based on:

* **Last Modified Date:** WeGive periodically polls Salesforce for Communication Lists that have been modified since the last sync
* **Sync Frequency:** The integration checks for updated Lists on a scheduled basis (frequency varies by integration configuration)
* **Modified Field Tracking:** Only Lists with a `LastModifiedDate` newer than the last successful sync are pulled into WeGive

### Communication List Mappings - Lists

| Salesforce Field               | WeGive Field   | WeGive API Field | Direction              | Type       | Notes                                                     |
| :----------------------------- | :------------- | :--------------- | :--------------------- | :--------- | :-------------------------------------------------------- |
| Id                             | Salesforce ID  | salesforce\_id   | Import from Salesforce | Hard-coded | Salesforce's unique identifier for this list              |
| Name                           | List Name      | name             | Both Ways              | Hard-coded | Display name of the communication list                    |
| wegive\_\_WeGive\_Id\_\_c      | WeGive List ID | id               | Export to Salesforce   | Hard-coded | WeGive's unique identifier                                |
| wegive\_\_Description\_\_c     | Description    | description      | Both Ways              | Hard-coded | Description of the list purpose (HTML stripped on export) |
| wegive\_\_UUID\_\_c            | UUID           | uuid             | Both Ways              | Hard-coded | Unique identifier for external integrations               |
| wegive\_\_Visible\_\_c         | Visible        | visible          | Both Ways              | Hard-coded | Whether the list is publicly visible for opt-in           |
| wegive\_\_Double\_Opt\_In\_\_c | Double Opt-In  | double\_opt\_in  | Both Ways              | Hard-coded | Whether double opt-in is required                         |
| wegive\_\_Show\_To\_\_c        | Show To        | show\_to         | Both Ways              | Hard-coded | Who can see this list (e.g., "all", "donors", "admin")    |

## Important Notes - Lists

### List Visibility

Communication lists have multiple visibility settings:

* **Visible:** Controls whether the list appears in public subscription interfaces
* **Show To:** Defines which user types can see and subscribe to the list
  * Common values: "all", "donors", "admin"
* These settings work together to control list accessibility

### Double Opt-In

The `double_opt_in` field controls subscription confirmation:

* When enabled, new subscribers must confirm via email
* Helps ensure GDPR/CAN-SPAM compliance
* Reduces accidental or fraudulent subscriptions
* Recommended for all marketing lists

### Description Handling

List descriptions can contain HTML in WeGive:

* On export to Salesforce, HTML tags are stripped
* This ensures clean data in Salesforce text fields
* Full HTML description is preserved in WeGive

### UUID Field

The `uuid` field provides a stable identifier:

* Used for external integrations (email platforms, etc.)
* Remains consistent even if list is renamed
* Useful for API integrations and webhooks

***

# Part 2: Communication Preferences (Subscriptions)

**Salesforce Object:** `wegive__Communication_Preference__c`\
**WeGive Model:** CommunicationListDonor

## How Communication Preference 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

### Mapping Types

* **Hard-coded** - Built into the integration logic and cannot be changed

***

## Sync Triggers - Preferences

### From WeGive to Salesforce (Export)

Communication Preference data is exported from WeGive to Salesforce when:

* **Subscription Created:** A donor subscribes to a list in WeGive
* **Subscription Updated:** A subscription status changes (subscribed/unsubscribed)

**Prerequisites for Creating Preferences:** Before creating a preference in Salesforce, the integration ensures:

1. **Donor exists in Salesforce:** The donor must have a `salesforce_id` (Contact) or `salesforce_account_id` (Account)
2. **Communication List exists in Salesforce:** The list must have a `salesforce_id`

The integration will automatically push the donor and list if they don't have Salesforce IDs yet.

### From Salesforce to WeGive (Import)

Communication Preference data is imported from Salesforce to WeGive based on:

* **Last Modified Date:** WeGive periodically polls Salesforce for Communication Preferences that have been modified since the last sync
* **Sync Frequency:** The integration checks for updated Preferences on a scheduled basis
* **Modified Field Tracking:** Only Preferences with a `LastModifiedDate` newer than the last successful sync are pulled into WeGive

***

## Complete Field Mapping - Preferences

| Salesforce Field  | WeGive Field      | Direction | Create Only | Default Mapping | Notes               |
| ----------------- | ----------------- | --------- | ----------- | --------------- | ------------------- |
| `contact_id`      | `contact_id`      | Both      | No          | Yes             | Contact reference   |
| `list_id`         | `list_id`         | Both      | No          | Yes             | List reference      |
| `status`          | `status`          | Both      | No          | Yes             | Subscription status |
| `opt_in_date`     | `opt_in_date`     | Both      | No          | Yes             | Opt-in timestamp    |
| `opt_out_date`    | `opt_out_date`    | Both      | No          | Yes             | Opt-out timestamp   |
| `source`          | `source`          | Both      | No          | Yes             | Subscription source |
| `preference_type` | `preference_type` | Both      | No          | Yes             | Type of preference  |
|                   |                   |           |             |                 |                     |

## Important Notes - Preferences

### Contact or Account

Communication preferences can link to either:

* **Contacts** (individual donors) - Uses `wegive__Contact__c`
* **Accounts** (company donors) - Uses `wegive__Account__c`

The integration automatically determines which field to populate based on the donor type. Only one field will be populated per preference record.

### Subscription Status

The `subscribed` field tracks the current subscription state:

* `true` - Donor is currently subscribed to the list
* `false` - Donor has unsubscribed or never subscribed
* Changes to this field trigger updates in both directions
* This is the primary field for managing list memberships

### Double Opt-In Tracking

The `double_opt_in_required` field indicates:

* Whether the subscription required confirmation
* Helps with compliance tracking and auditing
* Set at time of subscription creation
* Typically matches the list's double opt-in setting

### Automatic Donor and List Push

When creating a preference, the integration automatically ensures prerequisites:

1. If the donor doesn't have a Salesforce ID, the donor is pushed first
2. If the list doesn't have a `salesforce_id`, the list is pushed first
3. Then the preference relationship is created

This cascading push ensures data integrity without manual intervention.

***

## Communication List Matching & Create/Update Logic

### When WeGive Exports a Communication List to Salesforce

**Step 1: Check for Existing Salesforce List ID**

* If the WeGive list has a `salesforce_id`: The integration **UPDATES** the existing List record in Salesforce
* If no `salesforce_id` exists: The integration **CREATES** a new List record in Salesforce

### When Salesforce Exports a Communication List to WeGive

**Step 1: Check for Existing WeGive List**

* The integration searches for an existing list by `salesforce_id`
* If found, it updates that list
* If not found, it creates a new list

**Step 2: Import Data**

* All mapped fields are imported
* Boolean values are properly converted
* Description HTML is preserved in WeGive

***

## Communication Preference Matching & Create/Update Logic

### When WeGive Exports a Preference to Salesforce

**Step 1: Ensure Prerequisites Exist**

* Check if the donor has a Salesforce ID:
  * For individuals: Must have `salesforce_id` (Contact ID)
  * For companies: Must have `salesforce_account_id` (Account ID)
  * If not, push the donor first
* Check if the list has a `salesforce_id`
  * If not, push the list first

**Step 2: Check for Existing Salesforce Preference ID**

* If the WeGive preference has a `salesforce_id`: The integration **UPDATES** the existing Preference record in Salesforce
* If no `salesforce_id` exists: The integration **CREATES** a new Preference record in Salesforce

### When Salesforce Exports a Preference to WeGive

**Step 1: Find Related Records**

* Find the donor in WeGive:
  * If `wegive__Contact__c` is set: Search for individual donor with matching `salesforce_id`
  * If `wegive__Account__c` is set: Search for company donor with matching `salesforce_account_id`
  * If donor not found, throw an exception
* Find the list in WeGive by matching `wegive__Communication_List__c` to `salesforce_id`
  * If list not found, throw an exception

**Step 2: Find or Create Preference** The integration searches for an existing preference:

1. First, try to find by `salesforce_id`
2. If not found, try to find by matching WeGive ID (if `wegive__WeGive_ID__c` is set)
3. If still not found, try to find by matching `donor_id` and `communication_list_id`
4. If still not found, create a new preference

**Step 3: Update Preference**

* Link to the communication list
* Link to the donor
* Set the subscription status
* Set the double opt-in required flag
* Store the Salesforce ID
* Save the record

### Why This Matters

This matching logic ensures:

* Each WeGive preference maps to exactly one Salesforce preference record
* The correct donor type (Contact or Account) is used
* Prerequisites (donor and list) always exist before creating the preference
* Subscription status changes are synced in both directions
* No duplicate preferences are created

***

## Required Fields

**For Communication Lists (WeGive to Salesforce):**

* Name

**For Communication Preferences (WeGive to Salesforce):**

* wegive\_\_Contact\_\_c OR wegive\_\_Account\_\_c (Donor reference)
* wegive\_\_Communication\_List\_\_c (List Salesforce ID)
* wegive\_\_Subscribed\_\_c (Subscription status)

**For Salesforce to WeGive:**

* Id (Salesforce ID)
* Communication List and Donor references
* Subscription status

## Usage in WeGive

Communication Lists and Preferences in WeGive are used for:

* **Email Marketing:** Segment donors for targeted email campaigns
* **Preference Centers:** Allow donors to manage their own subscriptions
* **Compliance:** Track opt-ins and opt-outs for CAN-SPAM/GDPR
* **Segmentation:** Create donor segments based on interests
* **Communication Management:** Control who receives what messages
* **Double Opt-In:** Confirm subscriptions to reduce spam complaints
* **Reporting:** Analyze subscription trends and list growth

***

## Usage in Salesforce

Communication Lists and Preferences in Salesforce are used for:

* **Marketing Automation:** Sync with marketing platforms for email sends
* **Preference Tracking:** Maintain historical record of subscription changes
* **Compliance Reporting:** Document opt-in and opt-out activity
* **Segmentation:** Create Salesforce reports and dashboards by list membership
* **Campaign Management:** Link lists to Salesforce Campaigns
* **Data Integration:** Share preference data with other connected systems
* **Donor 360:** View complete donor communication preferences in one place

***

## Integration with Contact Fields

In addition to the preference object, WeGive also syncs list subscriptions as custom fields on the Contact record. This provides an alternative view of subscription data:

* Each communication list can have a corresponding custom field on Contact
* Field API name follows pattern: `CL_[list_id]_[list_slug]`
* Field stores boolean true/false for subscribed/unsubscribed
* This allows for easier reporting and filtering in Salesforce
* Both the preference records and Contact fields are maintained

**Example:**

* List ID: 123
* List Slug: monthly\_newsletter
* Contact Field: `CL_123_monthly_newsletter`
* Value: `true` (if subscribed) or `false` (if unsubscribed)

***

## Best Practices

1. **Use double opt-in** for all marketing lists to ensure compliance
2. **Create clear list names** that describe the content type
3. **Write descriptive list descriptions** so donors know what they're subscribing to
4. **Set appropriate visibility** - not all lists need to be publicly visible
5. **Respect unsubscribe requests** - sync them immediately
6. **Audit preferences regularly** to ensure data accuracy
7. **Document list purposes** for internal team reference
8. **Test subscription flows** before launching new lists
9. **Monitor sync logs** for failed preference updates
10. **Coordinate with marketing team** on list strategy and usage

***

## Troubleshooting

**Communication list not syncing:**

* Verify the WeGive managed package is installed
* Check that list has been modified since last sync
* Ensure integration has access to `wegive__Communication_List__c` object

**Preference not syncing:**

* Verify donor has a Salesforce ID (Contact or Account)
* Check that list has a `salesforce_id`
* Ensure integration has access to `wegive__Communication_Preference__c` object
* Verify donor type matches expected object (Contact vs Account)

**Subscription status not updating:**

* Check that the `subscribed` field is being updated in both systems
* Verify sync is running and processing preference changes
* Ensure no competing processes are overwriting status

**Duplicate preferences:**

* Preferences should be unique per donor + list combination
* If duplicates exist, they may have been created outside the integration
* Delete duplicates in Salesforce, keeping the one with correct status

**Company donors not subscribing:**

* Verify company donors have `salesforce_account_id` populated
* Ensure `wegive__Account__c` field is being used (not `wegive__Contact__c`)
* Check that Account record exists in Salesforce

**Double opt-in not working:**

* Verify the `double_opt_in` setting on the list
* Check that email confirmation workflows are configured
* Ensure the `double_opt_in_required` field is being set correctly

**Contact custom fields not syncing:**

* These are handled separately from preference objects
* Check that custom field mapping rules exist for the Contact
* Verify field API names follow the `CL_[id]_[slug]` pattern

***

## Understanding Hard-coded Mappings

All communication list and preference field mappings are hard-coded because:

* The WeGive managed package defines the object structure
* The data model is standardized across all implementations
* Custom fields are rarely needed on these objects
* The integration needs to handle both Contact and Account preferences automatically

***

## Compliance Considerations

Communication preferences are critical for compliance with:

* **CAN-SPAM Act:** Track opt-outs and honor unsubscribe requests
* **GDPR:** Maintain consent records and allow preference management
* **CASL (Canada):** Document consent and manage subscriptions
* **State Privacy Laws:** Provide transparency and control over communications

The integration helps maintain compliance by:

* Syncing subscription status immediately
* Tracking double opt-in confirmations
* Preserving historical preference data
* Enabling self-service preference management
