# Salesforce Marketing Cloud

The Salesforce Marketing Cloud (SFMC) integration connects your audience in Allegro to your email program in SFMC. It has four parts, and you can turn on any of them on its own:

| Feature                 | What it does                                                                                                      |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Newsletter lists**    | Subscribes members to SFMC lists and Journey Builder campaigns when they sign in, and reads back their lists.     |
| **Member data sync**    | Keeps one row per member in an SFMC data extension, filled from Allegro data, and updates it whenever it changes. |
| **Subscription Center** | Lets members opt in to and out of newsletters on your site. Their choices are read from and saved to SFMC.        |
| **Welcome event**       | Fires a Journey Builder entry event once per member, so a welcome journey starts when they sign up.               |

Turn on the **Salesforce Marketing Cloud** package under **Organization Settings → Packages** first. The settings page then appears at **Organization Settings → Salesforce Marketing Cloud**, and each property gets a **Salesforce Marketing Cloud** page in its own settings.

The organization page has five tabs: **Connection**, **Newsletter lists**, **Member data sync**, **Subscription Center** and **Welcome event**. **Save changes** on any tab saves every tab at once.

## Connect your SFMC account[​](#connect-your-sfmc-account "Direct link to Connect your SFMC account")

1. In SFMC, open **Setup → Apps → Installed Packages** and create a package with a **Server-to-Server** API integration. Give it access to what the features you plan to use work with:

   | Feature             | Works with                                       |
   | ------------------- | ------------------------------------------------ |
   | Newsletter lists    | Subscribers and lists, data extensions, journeys |
   | Member data sync    | Data extensions                                  |
   | Subscription Center | Data extensions                                  |
   | Welcome event       | Data extensions, journeys                        |

2. Copy the package's **Client Id**, **Client Secret** and **Authentication Base URI**.

3. In Allegro, open the **Connection** tab and paste them into **Client ID**, **Client Secret** and **Base Auth URL**. The base auth URL looks like `https://yoursubdomain.auth.marketingcloudapis.com`.

4. Click **Save changes**.

The client ID and secret are write-only: after saving, each field shows that a value is stored but never shows the value itself. Enter a new value to replace it, or click **remove it** to delete it on the next save.

The connection is shared by every property. Properties can use their own data extensions and events, but not their own SFMC account.

Can't connect to SFMC

If Allegro can't sign in to SFMC, a **Can't connect to SFMC** alert appears at the top of the organization and property pages with the error SFMC returned. Nothing is sent to or read from SFMC until it connects, so check the client ID, secret and base auth URL.

### Data extensions[​](#data-extensions "Direct link to Data extensions")

Several features read from or write to an SFMC data extension. Every field that takes one accepts its name or external key, and suggests the data extensions in your account as you type.

Allegro finds a member's row by email address, so each of these data extensions needs an `EmailAddress` column as its primary key.

After you save a data extension, the column fields suggest its columns. Allegro remembers a data extension's columns for an hour. If you add a column in SFMC, click **Refresh columns** to read them again.

## Newsletter lists[​](#newsletter-lists "Direct link to Newsletter lists")

The **Newsletter lists** tab subscribes members to lists and campaigns when they sign in, and keeps a copy of their lists in Allegro.

| Field                           | What it controls                                                                                           |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| **Default list IDs**            | The SFMC lists a member joins when they sign in. Comma-separated, such as `123, 456`.                      |
| **Default campaign IDs**        | The campaigns sent through the signup event when a member signs in. Comma-separated.                       |
| **Signup event definition key** | The Journey Builder entry event fired once for each campaign. It looks like `APIEvent-…`.                  |
| **Preferences data extension**  | A data extension of email preferences to copy into each member's profile. Leave it empty to turn this off. |

### When members are subscribed[​](#when-members-are-subscribed "Direct link to When members are subscribed")

Allegro subscribes a member when they request a magic link, sign in with a social provider, or are identified on your site. It creates the SFMC subscriber first if the email address is new to SFMC, then adds them to the lists.

For each campaign, Allegro fires the signup event with these values:

| Value                              | Description                 |
| ---------------------------------- | --------------------------- |
| `EmailAddress`                     | The member's email address. |
| `Record_CreatedDate`               | When the event was sent.    |
| `ProcessedFlag`                    | Always `false`.             |
| `Most_Recent_Acquisition_Campaign` | The campaign ID.            |

Campaigns need a signup event definition key. Without one, no campaign is sent.

Subscribing happens in the background, so it never slows down sign-in. If SFMC rejects a subscription, sign-in still succeeds.

### Reading lists back[​](#reading-lists-back "Direct link to Reading lists back")

Allegro stores the lists each member belongs to, and the member's row from the preferences data extension, in the `sfmc_email_subscriptions` profile. You can see it on the member's **Data** tab.

Allegro refreshes the profile when a member signs in and their copy is more than 7 days old, and every month for members who signed in within the last 30 days.

## Member data sync[​](#member-data-sync "Direct link to Member data sync")

The **Member data sync** tab keeps one row per member in an SFMC data extension, so your journeys and segments in SFMC can use Allegro data.

1. Pick the **Data extension** to write to.
2. Under **Column mapping**, click **Add column** for each column to fill. Pick the **SFMC column** and what it is **Filled from**.
3. Click **Save changes**.

Leave **Data extension** empty to stop sending members.

### Column sources[​](#column-sources "Direct link to Column sources")

| Source                                                     | Value                                                                                                   |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| **Audience Member ID**                                     | The member's Allegro ID.                                                                                |
| **Email**                                                  | The member's email address.                                                                             |
| **Last active**                                            | When the member was last active.                                                                        |
| **Profile updated**                                        | When the member's profile last changed.                                                                 |
| **Joined**                                                 | When the member joined the property. On the organization page, when they created their account.         |
| Any [user attribute](/product/audience/user-attributes.md) | The attribute's value for the member.                                                                   |
| ***column* (Subscription Center)**                         | Whether the member is subscribed to that newsletter in the [Subscription Center](#subscription-center). |

Other installed packages can add their own sources to this list.

Allegro formats values the way SFMC expects them: true/false values as `True` and `False`, and dates as `YYYY-MM-DD HH:MM:SS` in UTC. A value the member doesn't have clears the column.

### When rows are updated[​](#when-rows-are-updated "Direct link to When rows are updated")

Allegro writes a member's row when they:

* sign up, or join a property,
* have a mapped attribute set, changed or removed,
* change a newsletter in the Subscription Center.

Allegro waits 30 seconds before writing, so a form that saves several attributes at once produces a single update.

If the mapping names a column the data extension doesn't have, Allegro writes the other columns and skips that one until you add it in SFMC.

## Subscription Center[​](#subscription-center "Direct link to Subscription Center")

The **Subscription Center** tab connects the newsletter preferences members see on your site to an SFMC data extension that holds one row per subscriber, with a true/false column for each newsletter.

| Field                               | What it controls                                                                                                                                |
| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Data extension**                  | The preferences data extension. Leave it empty to stop reading and writing preferences.                                                         |
| **Editable newsletters**            | The newsletters members can change. For each, the true/false **Subscribed column** and the **Last change date column** set whenever it changes. |
| **Values for a new row**            | Columns to fill the first time a member's row is created, such as newsletters they start out on. Ignored once the row exists.                   |
| **Global subscription column**      | The true/false column for whether the member gets email at all.                                                                                 |
| **Global subscription date column** | Set when the global subscription is turned on, and when a member's row is first created.                                                        |
| **Opting in subscribes globally**   | When on, a member who opts in to any newsletter is also subscribed globally. Requires both global columns.                                      |

### How changes are saved[​](#how-changes-are-saved "Direct link to How changes are saved")

When a member changes their preferences, Allegro reads their current row from SFMC, then writes:

* `True` or `False` in each newsletter column they changed, and the current time in its last change date column,
* the global subscription column, when **Opting in subscribes globally** is on and they opted in to something,
* the **Values for a new row**, when SFMC had no row for them yet.

Members can opt out of everything by turning off the global subscription. They can't turn it on directly; that happens when they opt in to a newsletter.

A member who has no row in SFMC and only opts out of something gets no row.

Allegro keeps a copy of each member's row in the `sfmc_subscription_center` profile, refreshed on the same schedule as newsletter lists. A member who has never been read from SFMC is read when they first open their preferences, so they are never shown as unsubscribed by mistake.

### Preferences API[​](#preferences-api "Direct link to Preferences API")

Your site reads and saves a signed-in member's preferences through these endpoints. They use the member's Allegro session, the same way the SDK does, and accept 30 requests a minute.

| Method  | Path                                               | Description                                                                                         |
| ------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `GET`   | `/api/sfmc/communication-preferences`              | The member's row and editable newsletters for the property the site is on, else the organization's. |
| `PATCH` | `/api/sfmc/communication-preferences`              | Saves changes for that same Subscription Center.                                                    |
| `GET`   | `/api/sfmc/organization/communication-preferences` | The member's organization row, whichever property the site is on.                                   |
| `PATCH` | `/api/sfmc/organization/communication-preferences` | Saves changes to the organization's Subscription Center.                                            |

A `PATCH` takes the newsletter columns to change:

```json
{
    "subscription_data": {
        "Daily_Newsletter": true,
        "Weekend_Edition": false
    }
}

```

Both methods return the member's row, the columns they can change and the global column:

```json
{
    "data": {
        "property": "news",
        "subscription_data": {
            "EmailAddress": "jane@example.com",
            "Daily_Newsletter": "True",
            "Weekend_Edition": "False",
            "Global_Opt_In": "True"
        },
        "editable_columns": ["Daily_Newsletter", "Weekend_Edition"],
        "global_column": "Global_Opt_In"
    }
}

```

| Status | Code                              | When                                                                                          |
| ------ | --------------------------------- | --------------------------------------------------------------------------------------------- |
| `404`  | `SUBSCRIPTION_PROFILE_NOT_FOUND`  | The Subscription Center is off, doesn't apply to the member, or SFMC can't be read right now. |
| `422`  | `INVALID_SUBSCRIPTION_PREFERENCE` | The request names a column that isn't an editable newsletter.                                 |
| `502`  | `SUBSCRIPTION_UPDATE_FAILED`      | SFMC rejected the change. Nothing was saved.                                                  |

## Welcome event[​](#welcome-event "Direct link to Welcome event")

The **Welcome event** tab fires a Journey Builder entry event once per member, typically the entry to a welcome journey.

| Field                    | What it controls                                                                                          |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| **Event definition key** | The journey's entry event. Leave it empty to turn the welcome event off.                                  |
| **Data extension**       | The data extension the event writes to. Required with an event definition key.                            |
| **Fire when**            | When the member signs up or joins a property (the default), or when a chosen user attribute is first set. |

If your registration form collects details after the email address, pick the attribute the form writes last under **Fire when**. The event then waits until the member has filled in the form, so the journey has their details.

The event carries the member's [member data sync](#member-data-sync) values for the columns the welcome data extension has, plus `EmailAddress`, `Record_CreatedDate` (when they joined) and `ProcessedFlag` (`false`). Values the member doesn't have are left out, because SFMC rejects an event with an empty true/false or date value.

Allegro waits 30 seconds after the trigger before firing, and records that the event fired so the member never enters the journey twice. A property with its own welcome event fires it separately for its members.

## Properties[​](#properties "Direct link to Properties")

Each property chooses where each feature's settings come from on its own **Salesforce Marketing Cloud** settings page. The page has a tab for each feature with a **Settings** choice at the top:

| Setting                       | What it does                                                                                                                                 |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Use organization settings** | Uses the organization's settings, shown read-only with a link to edit them. This is the default.                                             |
| **Use custom settings**       | Uses the property's own data extension, mapping or event instead of the organization's. The fields are the same as on the organization page. |
| **Off**                       | The feature doesn't run for the property's members.                                                                                          |

A member gets each feature from every property they've joined: from the organization for properties that inherit, from the property for ones with custom settings, and not at all for ones that are off. A member of no property gets the organization's. So a member of two properties with custom member data sync has a row in both properties' data extensions.

For member data sync and the welcome event, **Joined** and **Fire when** on a property mean joining that property.

### Property newsletter lists[​](#property-newsletter-lists "Direct link to Property newsletter lists")

On a property's **Newsletter lists** tab, **Use custom settings** adds:

| Field                           | What it controls                                                                                                                        |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Newsletter list IDs**         | The SFMC lists this property owns. Only these are copied into the property's profile. Leave it empty to copy all of the member's lists. |
| **Default list IDs**            | Lists a member joins when they sign in on this property, instead of the organization's.                                                 |
| **Default campaign IDs**        | Campaigns sent when a member signs in on this property, instead of the organization's.                                                  |
| **Signup event definition key** | The journey event fired for each of this property's campaigns. Required when the property has default campaigns.                        |
| **Preferences data extension**  | A data extension of email preferences to copy into the property's profile.                                                              |

A property with custom newsletter settings and either newsletter list IDs or a preferences data extension gets its own profile for each member, named `sfmc_email_subscriptions:` followed by the property's slug, such as `sfmc_email_subscriptions:news`. The organization's `sfmc_email_subscriptions` profile keeps updating alongside it.

With newsletters **Off**, members who sign in on the property aren't subscribed to any default lists or campaigns.

### Subscription Centers on properties[​](#subscription-centers-on-properties "Direct link to Subscription Centers on properties")

The Subscription Center the [preferences API](#preferences-api) uses depends on the site the member is on. On a property with its own Subscription Center, members manage that property's newsletters, and must have joined the property. Use the `organization` endpoints to also show the organization's newsletters on that site.

## Member profiles[​](#member-profiles "Direct link to Member profiles")

The integration stores these profiles on each member. They appear on the member's **Data** tab, and you can fill user attributes from them with [Sync from external profiles](/product/audience/user-attributes.md#syncing-from-external-profiles).

| Profile                           | Contents                                                                                          |
| --------------------------------- | ------------------------------------------------------------------------------------------------- |
| `sfmc_email_subscriptions`        | `list_ids`, the SFMC lists the member belongs to, and `subscription_data`, their preferences row. |
| `sfmc_email_subscriptions:{slug}` | The same for one property with its own newsletter settings.                                       |
| `sfmc_subscription_center`        | The member's Subscription Center rows, under `organization` and under `properties.{slug}`.        |

## Known gaps[​](#known-gaps "Direct link to Known gaps")

* **Changes made in SFMC arrive later.** Allegro doesn't hear about changes made directly in SFMC, such as an unsubscribe from an email footer. They appear in Allegro at the member's next refresh.
* **Failed writes retry, then stop.** Allegro retries a data extension write or welcome event three times over a few minutes. If SFMC is still failing, the row waits until the member's data next changes, and the welcome event until its trigger happens again.
* **Failed subscriptions aren't retried.** If SFMC rejects a list subscription or campaign at sign-in, Allegro logs it and moves on.
* **New columns need a refresh.** Columns added in SFMC appear in Allegro's suggestions within an hour, or right away after **Refresh columns**.
* **Email address is the key.** Rows are matched by email address. When a member's email changes, their next write creates a new row under the new address, and the old row stays in SFMC.
