> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/connectors/fr/email-provider/salesforce-marketing-cloud.md).

# Salesforce Marketing Cloud

Utilisez ce connecteur lorsque vous souhaitez que The Wallet Crew envoie **des e-mails transactionnels** via **Salesforce Marketing Cloud**, tandis que Salesforce Marketing Cloud reste l’endroit où votre marque gère les ressources d’e-mails, le suivi et les rapports.

Cette intégration utilise le **fournisseur d’e-mails script**. The Wallet Crew déclenche l’envoi. Votre script transmet l’événement à Salesforce Marketing Cloud.

## Fonctionnement

The Wallet Crew appelle votre implémentation de `runtime.scriptable.emailEngine.SendEmail`. Votre script appelle ensuite l’API REST de Salesforce Marketing Cloud pour déclencher un événement (en utilisant un `EventDefinitionKey`). Salesforce Marketing Cloud utilise cette charge utile d’événement pour générer et envoyer l’e-mail.

Ce modèle évite de dupliquer les modèles. Salesforce Marketing Cloud possède le modèle. The Wallet Crew envoie uniquement les variables dont Salesforce Marketing Cloud a besoin, comme l’URL de téléchargement de la Carte et le libellé de CTA localisé.

Si vous n’avez pas encore configuré le fournisseur script, commencez par [Extensibilité d’EmailSender](/connectors/fr/custom-connector/emailsender-extensibility.md).

## Avant de commencer

Vous avez besoin de trois éléments :

* Un Salesforce Marketing Cloud **Package installé** pouvant appeler des API REST (ID client + secret client).
* Une ressource Salesforce Marketing Cloud qui peut être **déclenchée par l’API**, exposant un `EventDefinitionKey`.
* Un identifiant stable dans votre charge utile d’e-mail Wallet Crew (exemple : `id.customerId`) pour générer l’URL de la Carte.

## Configuration requise dans Salesforce Marketing Cloud

Dans Salesforce Marketing Cloud, créez un point d’entrée déclenché par API et le contenu d’e-mail associé.

1. Créez un **Package installé** et conservez le **Client Id** et **Client Secret**.
2. Créez la ressource d’envoi que vous souhaitez déclencher (généralement un événement d’entrée de parcours ou un événement API), puis copiez son `EventDefinitionKey`.
3. Assurez-vous que votre modèle d’e-mail Salesforce Marketing Cloud attend les mêmes noms de variables que vous enverrez dans `Data`.

{% hint style="info" %}
La configuration de Salesforce Marketing Cloud varie selon la configuration du compte et l’ensemble de fonctionnalités. Conservez un contrat de charge utile stable : les noms de champ dans `Data` doivent correspondre à ce que votre ressource Salesforce Marketing Cloud attend.
{% endhint %}

## Activez Salesforce Marketing Cloud dans The Wallet Crew

Définissez le fournisseur sur `script` afin que The Wallet Crew appelle votre `SendEmail` implémentation.

{% code title="/server/emails.yml" %}

```yaml
fournisseur :
  type : script
ressources :
  - /locales/emails/
```

{% endcode %}

### Exemple de script (déclencher un événement Salesforce Marketing Cloud)

Cet exemple déclenche un événement Salesforce Marketing Cloud en utilisant le point de terminaison REST `interaction/v1/events`. Il envoie un titre localisé, un libellé de CTA localisé et une URL de la Carte Wallet Crew construite à partir d’un identifiant client.

{% hint style="warning" %}
Cette implémentation délègue le rendu à Salesforce Marketing Cloud. L'équipe Wallet `buildEmail()` le callback n'est volontairement pas utilisé.
{% endhint %}

{% code title="Exemple Salesforce Marketing Cloud (implémentation SendEmail)" %}

```javascript
const CUSTOM_DOMAIN = "wallet.brand.com";
const TENANTID = "brand";
const SMFC_DOMAIN = "xxx";

/**
 * @typedef {Object} EmailData
 * @property {string} Subject - Ligne d'objet rendue.
 * @property {string} Body - Contenu du corps rendu.
 */

/**
 * Envoyer un e-mail en utilisant le nom de modèle et les données fournis.
 * L'appelant fournit les cultures prises en charge et un rappel
 * pour construire le contenu de l'e-mail rendu.
 *
 * @param {string} recipient - Adresse e-mail cible.
 * @param {string} emailTemplate - Nom du modèle à générer.
 * @param {Object.<string, any>} data - Données du modèle transmises au script.
 * @param {string[]} cultures - Noms de culture disponibles provenant du fournisseur de cultures.
 * @param {(templateName: string) => Promise<EmailData>} buildEmail
 * Fonction de rappel qui renvoie le contenu final de l'e-mail rendu.
 *
 * @returns {Promise<void>}
 */
async function sendEmail(recipient, emailTemplate, data, cultures, buildEmail){

  const customerId = data["id.customerId"];
  const url = `https://${CUSTOM_DOMAIN}/${TENANTID}/Carte?id.customerId=${customerId}`;  

  const locales = {
    "en": {
      title: "🎉 Votre compte est prêt – Ajoutez votre Carte au Wallet !",
      label: "Ajouter au Wallet"
    },
    "fr": {
      title: "🎉 Votre compte est prêt – Ajoutez votre Carte au Wallet !",
      label: "Ajouter au Wallet"
    }
  };

  const locale = locales[cultures[0]];

  const response = await fetch(`https://${SMFC_DOMAIN}.rest.marketingcloudapis.com/interaction/v1/events`,  {
    Méthode : "POST", 
    Authentification : {
        mode : 'OAuth2.0', 
        grantType : 'clientCredentials',
        accessTokenUrl : `https://${SMFC_DOMAIN}.auth.marketingcloudapis.com/v2/token`, 
        sendCredentialsAsFormParams: true,
        clientId: await getSecret('SFMC-CLIENTID'), 
        clientSecret : await getSecret('SFMC-CLIENTSECRET')
    }, 
    Headers: {
      "Content-Type": "application/json",
    },
    Body: {
      "ContactKey": recipient,
      "EventDefinitionKey": "confirmationCompteNeostore",
      "Data": {
          "SubscriberKey": recipient,
          "EmailAddress": recipient,
          "Title": locale.title,
          "Url": url,
          "LabelCTA": locale.label,
      }
    }
  });
  const responseData = JSON.parse(response.ResponseText); 
  if(!responseData?.eventInstanceId){
    throw new Error(`erreur lors de l'envoi du statut de l'e-mail personnalisé : ${response.StatusCode} - contenu : ${response.ResponseText}`)
  }
}

export default function(context) {
  context.register('runtime.scriptable.emailEngine', {
    SendEmail: sendEmail 
  })
}
```

{% endcode %}

### Ce qu'il faut valider

Déclenchez un véritable e-mail transactionnel, puis validez de bout en bout :

* Wallet Crew appelle votre script sans erreurs.
* L'appel à l'API Salesforce Marketing Cloud renvoie un `eventInstanceId`.
* Salesforce Marketing Cloud rend l'e-mail avec `Titre`, `URL`, et `LabelCTA`.
* Le CTA ouvre l'URL de Wallet Crew et la carte peut être installée.

## Dépannage

Si l'envoi échoue, isolez le problème dans cet ordre :

* **L'authentification OAuth échoue (401/403)**: l'ID client/secret est incorrect, révoqué, ou le package installé n'a pas accès à l'API.
* **Aucun `eventInstanceId`**: le `EventDefinitionKey` est invalide, non publié, ou le schéma du payload est rejeté.
* **Variables vides dans l'e-mail**: le modèle Salesforce Marketing Cloud attend des noms de champs différents de ceux que vous envoyez dans `Data`.
* **Langue incorrecte**: `cultures[0]` ne correspond pas à votre mappage de paramètres régionaux. Ajoutez un repli (par exemple : définir par défaut sur `en`).

## FAQ

<details>

<summary><strong>Qui possède le HTML de l'e-mail, Salesforce Marketing Cloud ou Wallet Crew ?</strong></summary>

Salesforce Marketing Cloud possède le HTML dans ce modèle. Wallet Crew n'envoie que des variables (titre, libellé du CTA, URL) afin que votre équipe marketing puisse faire évoluer le modèle sans déployer de modifications Wallet Crew.

</details>

<details>

<summary><strong>Peut-on toujours utiliser les modèles Wallet Crew et <code>buildEmail()</code>?</strong></summary>

Oui, mais cela devient une stratégie différente. Dans ce modèle, Wallet Crew rend `Objet` et `Body`, et Salesforce Marketing Cloud est utilisé uniquement comme passerelle de diffusion. Si vous souhaitez cela, alignez l'asset Salesforce Marketing Cloud pour accepter le HTML rendu et éviter le double templating.

</details>

<details>

<summary><strong>Où stockons-nous les identifiants SFMC ?</strong></summary>

Stockez-les en tant que secrets du tenant et chargez-les à l'exécution (comme dans l'exemple avec `getSecret('SFMC-CLIENTID')` et `getSecret('SFMC-CLIENTSECRET')`). Ne codez pas les identifiants en dur dans les scripts.

</details>

<details>

<summary><strong>Que devons-nous utiliser comme <code>ContactKey</code>?</strong></summary>

Utilisez un identifiant de contact Salesforce Marketing Cloud stable. De nombreuses marques utilisent l'adresse e-mail, mais vous pouvez aussi utiliser un identifiant CRM si cela correspond à votre stratégie de clé de contact Salesforce Marketing Cloud. Gardez-le cohérent avec la manière dont votre Journey/asset résout les destinataires.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.thewalletcrew.io/connectors/fr/email-provider/salesforce-marketing-cloud.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
