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

# Salesforce Actions

> What Mary does after she classifies a reply — Salesforce contact/lead updates, campaign adds, and native unsubscribes.

**Actions** are what Mary *does* once she's classified a reply and pulled out any [extracted data](/use-cases/erm/data-extraction). They run automatically the moment a match is confirmed, so by the time an email shows up in the [Messages](/use-cases/erm/untitled-page-1) feed, the downstream work in Salesforce is already done.

Actions are configured per category. A reply that lands in `Unsubscribe` runs one set of actions; one that lands in `Left Company` runs another.

## Available action types

### Forward Email

<img src="https://mintcdn.com/allgoodtechnologyinc/SR0L3Vw0BLXD811n/images/Forward-Email.png?fit=max&auto=format&n=SR0L3Vw0BLXD811n&q=85&s=54f5ba40101140878e4a634375928a53" alt="Forward Email" width="1582" height="1300" data-path="images/Forward-Email.png" />

Forward the classified reply to another email address. This is the go-to action when a reply needs a human — for example, routing a `Human Request` reply to your shared sales inbox, or looping a specific rep in on `Out-Of-Office` replies for accounts they own.

Forward Email is a **generic action** and works the same way regardless of which marketing automation platform you're connected to.

| Field            | What it does                                                                                                                                                |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `To`             | Destination email address. Accepts tokens (e.g., `{{ owner.email }}`).                                                                                      |
| `Subject`        | Subject line for the forwarded message. Defaults to `Fwd: {{ subject }}`.                                                                                   |
| `Message`        | Optional custom message body. Supports **Markdown** formatting and token insertion via **Insert Data**. Leave empty to use the default forwarding template. |
| `Original Email` | Controls how the original email is included in the forward — see below.                                                                                     |

The `Original Email` dropdown controls what happens with the source message:

| Option           | Behavior                                                                  |
| ---------------- | ------------------------------------------------------------------------- |
| `Include Inline` | Original message body is appended directly beneath your message           |
| `Include Quoted` | Original message is included as a quoted reply — the familiar default     |
| `Don't Include`  | Forward only contains the message you wrote; the original body is dropped |

Under **Advanced**:

| Field           | What it does                                                                                                         |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
| `Message Style` | Rendering style for the forwarded email. `AllGood Branded` uses the allGood template; other styles may be available. |
| `CC`            | Additional addresses to CC on the forward. Accepts tokens.                                                           |
| `Reply-To`      | Override the reply-to address so recipient replies land somewhere other than the original sender.                    |
| `From Name`     | Display name shown in the recipient's inbox (e.g., "Support Team" instead of the raw address).                       |

### Add to Worksheet

<img src="https://mintcdn.com/allgoodtechnologyinc/SR0L3Vw0BLXD811n/images/Add-to-Worksheet.png?fit=max&auto=format&n=SR0L3Vw0BLXD811n&q=85&s=19dd1d9d424dd22034b37b14cb2e5f59" alt="Add To Worksheet" width="1574" height="706" data-path="images/Add-to-Worksheet.png" />

Push the sender into an allGood worksheet, optionally running it through the worksheet's flow steps. This is how you take a classified reply and hand it off to another allGood workflow — for example, adding a `Human Request` sender to a follow-up worksheet that triages and routes them, or pushing extracted replacement contacts from `Left Company` replies into a new-lead worksheet.

Add to Worksheet is a **generic action** and works the same way regardless of which marketing automation platform you're connected to.

| Field                    | What it does                                                                                                                                                                |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Worksheet`              | The worksheet to add the contact to. Search by name to pick from your existing worksheets.                                                                                  |
| `Include all email data` | When checked, attaches the full email content (subject, body, from, headers) to the worksheet row. Useful when downstream flow steps need access to the raw reply.          |
| `Fields`                 | Map worksheet fields to values or tokens. Left column is the worksheet field name; right column is the value or token to write. Click **+ Add Field** to add more mappings. |

Under **Advanced**:

| Field                     | What it does                                                                                                                                                      |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Behavior`                | Choose whether Mary just adds the contact to the worksheet, or adds and immediately runs them through the worksheet's flow steps (`Add to Worksheet + Run Flow`). |
| `Include source metadata` | Attaches metadata about where the entry originated (which ERM configuration, category, classification rationale, etc.) so downstream steps can reference it.      |
| `Only If`                 | Standard [conditional expression](#conditional-actions) that must evaluate to `true` for the action to run. Use to fan out behavior within a single category.     |

### Sync Contact/Lead to Salesforce

<img src="https://mintcdn.com/allgoodtechnologyinc/qJC8ejYE_Zx6tUhe/images/Salesforce-ERM-Docs-1.png?fit=max&auto=format&n=qJC8ejYE_Zx6tUhe&q=85&s=536d95e0af48c07b603efcd96077cb78" alt="Salesforce ERM Docs 1" width="1630" height="828" data-path="images/Salesforce-ERM-Docs-1.png" />

Create or update a record in Salesforce, identified by the sender's email address. Mary looks the record up by email — preferring a **Contact**, then falling back to a **Lead** — then creates or updates it depending on the sync mode you choose.

You can set:

* **Static values** — e.g., `leadStatus = Unqualified`
* **Dynamic values** — tokens that resolve at runtime from Mary's classification or [extracted data](/use-cases/erm/data-extraction), e.g., `allgood_reason = [allGood] {{ classification }}`

Each row in the **field map** pairs a Salesforce field's API name with a value or token. The email address is always included automatically — it's the lookup key.

You also choose a **sync mode** under the advanced tab:

| Mode               | Behavior                                                               |
| ------------------ | ---------------------------------------------------------------------- |
| `Create or Update` | Update the record if it exists, otherwise create it (the safe default) |
| `Create Only`      | Create a new record; fail if one already exists for that email         |
| `Update Only`      | Update an existing record; fail (or skip) if no record is found        |

Common tokens you can reference:

| Token                              | What it resolves to                                                                      |
| ---------------------------------- | ---------------------------------------------------------------------------------------- |
| `{{ classification }}`             | The category Mary assigned (e.g., `Unsubscribe`)                                         |
| `{{ rationale }}`                  | Mary's plain-English reasoning for the classification                                    |
| `{{ from.address }}`               | The sender's email address                                                               |
| `{{ from.name }}`                  | The sender's display name                                                                |
| `{{ extractedFields["<field>"] }}` | Any field defined in [Data Extraction](/use-cases/erm/data-extraction) for that category |

### Add to Salesforce Campaign

<img src="https://mintcdn.com/allgoodtechnologyinc/qJC8ejYE_Zx6tUhe/images/Salesforce-ERM-Docs-2.png?fit=max&auto=format&n=qJC8ejYE_Zx6tUhe&q=85&s=8d86b1073026e36c37840c887bd94a8e" alt="Salesforce ERM Docs 2" width="1634" height="948" data-path="images/Salesforce-ERM-Docs-2.png" />

Add the sender to a specific Salesforce campaign as a campaign member. Mary looks the record up by email and adds them to the campaign you specify. The campaign is identified by its **Campaign ID** — the 15- or 18-character Salesforce Campaign record ID.

<Warning>
  When adding someone to a Salesforce campaign, the Contact or Lead must already exist in Salesforce. If it might not, add a **Sync Contact/Lead to Salesforce** action *before* the **Add to Salesforce Campaign** action — the sync (in `Create or Update` mode) will create the record if it doesn't exist.
</Warning>

### Unsubscribe in Salesforce

<img src="https://mintcdn.com/allgoodtechnologyinc/qJC8ejYE_Zx6tUhe/images/Salesforce-ERM-Docs-3.png?fit=max&auto=format&n=qJC8ejYE_Zx6tUhe&q=85&s=35a208b4a8c3c316b17718617d441911" alt="Salesforce ERM Docs 3" width="1628" height="804" data-path="images/Salesforce-ERM-Docs-3.png" />

Opt the sender out of email in Salesforce. Mary looks the record up by email — preferring a **Contact**, then falling back to a **Lead** — and sets their email opt-out status. This is the cleanest way to honor an opt-out, because it uses Salesforce's native email opt-out field rather than just flipping a custom field.

<Note>
  If the record isn't found in Salesforce, this action skips quietly by default. You can flip this behavior with the **skip if not found** toggle if you'd rather treat a missing record as a hard error.
</Note>

## Example: Unsubscribe actions

<Frame>
  <img src="https://mintcdn.com/allgoodtechnologyinc/qJC8ejYE_Zx6tUhe/images/Salesforce-ERM-Docs-Example.png?fit=max&auto=format&n=qJC8ejYE_Zx6tUhe&q=85&s=0a2d470b5c38537f2d7c578d17fcfc1b" alt="Salesforce ERM Docs Example" width="1626" height="1794" data-path="images/Salesforce-ERM-Docs-Example.png" />
</Frame>

Here's the action chain a typical `Unsubscribe` category would run:

<Steps>
  <Step title="Unsubscribe in Salesforce">
    Honor the opt-out using the Unsubscribe in Salesforce action so the suppression is respected everywhere.
  </Step>

  <Step title="Sync Contact/Lead to Salesforce">
    Record the reason on the record for the audit trail. Using `Create or Update` mode also guarantees the record exists before the later steps run.

    | Field            | Value                                             |
    | ---------------- | ------------------------------------------------- |
    | `leadStatus`     | `Unqualified`                                     |
    | `allgood_reason` | `[allGood] {{ classification }}: {{ rationale }}` |
  </Step>

  <Step title="Add to Salesforce Campaign">
    Drop the record into the Mary-managed unsubscribe campaign for downstream reporting and suppression.

    | Field         | Value                |
    | ------------- | -------------------- |
    | Email address | `{{ from.address }}` |
    | Campaign ID   | `701dL00002GXH2OQAX` |
  </Step>
</Steps>

The `{{ rationale }}` token is particularly useful here — it gives your ops team a human-readable audit trail directly on the record explaining *why* Mary marked someone as unsubscribed.

## Stacking and reordering actions

You can configure multiple actions per category, and they run in the order they're listed. Use the up/down arrows on each action row to reorder them. Click **+ Add Action** to add more.

Order matters in two cases:

* **Dependent actions.** If an `Add to Salesforce Campaign` depends on the record existing, put `Sync Contact/Lead to Salesforce` (in `Create or Update` mode) first.
* **Field dependencies.** If a later action references a field set by an earlier action, make sure the order reflects that dependency.

## Conditional actions

Every action supports an **only-if** condition — a token expression that must evaluate to `true` for the action to run. This lets you fan out behavior within a single category. For example, only add to a "Hot Leads" campaign when an extracted `intent` field is `high`, while still running the rest of the chain for everyone.

Actions that look a record up by email also expose a **skip if not found** toggle, which controls whether a missing record is treated as a quiet skip or a hard error.

## Best practices

* **Use the `[allGood]` prefix in audit fields.** Following the example above (`allgood_reason = [allGood] ...`) makes it easy to see at a glance which records were touched by Mary versus a human or another system.
* **Use field *API* names, not labels.** The field map keys must be Salesforce's API field names, not the friendly labels shown elsewhere in the UI. A field name that doesn't exist will fail at execution time.
* **Prefer the native unsubscribe.** For opt-outs, use **Unsubscribe in Salesforce** rather than just setting a custom field — it updates Salesforce's native email opt-out so suppression is honored everywhere.
* **Test the full chain, not just the classification.** The [Test Suite](/use-cases/erm/test-suite) validates categorization and extraction; once those pass, sanity-check the actions in a sandbox Salesforce instance before going live.
* **Watch the order when adding to campaigns.** Most campaign-add failures we see are records that didn't exist yet. Lead with a **Sync Contact/Lead to Salesforce** in `Create or Update` mode to be safe.
