> 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

Configurez The Wallet Crew pour envoyer des e-mails transactionnels via Salesforce Marketing Cloud.

Utilisez ce connecteur pour permettre à The Wallet Crew d’envoyer **des e-mails transactionnels** via **Salesforce Marketing Cloud**, tandis que Salesforce Marketing Cloud reste l’endroit où la marque gère les ressources d’e-mail, le suivi et les rapports.

Cette intégration utilise le **fournisseur de messagerie de script**. The Wallet Crew déclenche l’envoi. Le script du tenant transmet l’événement à Salesforce Marketing Cloud.

## Comment ça marche

The Wallet Crew appelle l’implémentation du tenant de `runtime.scriptable.emailEngine.SendEmail`. Ce script appelle ensuite l’API REST de Salesforce Marketing Cloud pour déclencher un événement (à l’aide d’un `EventDefinitionKey`). Salesforce Marketing Cloud utilise cette charge utile d’événement pour rendre 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 n’envoie que les variables dont Salesforce Marketing Cloud a besoin, comme l’URL de téléchargement de la Carte et le libellé CTA localisé.

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

## Avant de commencer

Trois éléments sont requis :

* Un **package installé** Salesforce Marketing Cloud
* qui peut appeler des API REST (client id + client secret). **une ressource Salesforce Marketing Cloud qui peut être**déclenchée par API `EventDefinitionKey`.
* , en exposant un `id.customerId`stable dans la charge utile d’e-mail de The Wallet Crew (exemple : ) 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 à 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 le modèle d’e-mail Salesforce Marketing Cloud attend les mêmes noms de variables que ceux envoyés dans `Données`.

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

## Activer Salesforce Marketing Cloud dans The Wallet Crew

Définissez le fournisseur sur `script` afin que The Wallet Crew appelle l’ `SendEmail` implémentation du tenant.

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

```yaml
provider :
  type : script
resources :
  - /locales/emails/
```

{% endcode %}

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

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

{% hint style="warning" %}
Cette implémentation délègue le rendu à Salesforce Marketing Cloud. The Wallet Crew `buildEmail()` le callback n’est délibérément pas utilisé.
{% endhint %}

{% code title="Exemple Salesforce Marketing Cloud (implémentation de 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.
 */

/**
 * Envoyez un e-mail en utilisant le nom du modèle fourni et les données.
 * L'appelant fournit les cultures prises en charge et un rappel
 * pour générer le contenu de l'e-mail rendu.
 *
 * @param {string} recipient - Adresse e-mail cible.
 * @param {string} emailTemplate - Nom du modèle à rendre.
 * @param {Object.<string, any>} data - Données du modèle transmises au script.
 * @param {string[]} cultures - Noms de cultures disponibles fournis par le 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",
      "Données": {
          "CléAbonné": recipient,
          "AdresseEmail": recipient,
          "Titre": locale.title,
          "URL": url,
          "LibelléCTA": 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 e-mail transactionnel réel, puis validez de bout en bout :

* L’équipe Wallet Crew appelle le script sans erreur.
* L’appel à l’API Salesforce Marketing Cloud renvoie un `eventInstanceId`.
* Salesforce Marketing Cloud génère l’e-mail avec `Titre`, `URL`, et `LabelCTA`.
* Le CTA ouvre l’URL de The Wallet Crew et la Carte peut être installée.

## Dépannage

Si les envois échouent, isolez le problème dans cet ordre :

* **Échec d’OAuth (401/403)**: l’identifiant/le secret client est incorrect, révoqué ou le package installé n’a pas accès à l’API.
* **Non `eventInstanceId`**: le `EventDefinitionKey` est invalide, non publié ou le schéma de la charge utile est rejeté.
* **Variables vides dans l’e-mail**: le modèle Salesforce Marketing Cloud attend des noms de champs différents de ceux envoyés dans `Données`.
* **Langue incorrecte**: `cultures[0]` ne correspond pas à la table de correspondance des paramètres régionaux. Ajoutez un repli (par exemple : définir par défaut à `en`).

## FAQ

<details>

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

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

</details>

<details>

<summary><strong>Les modèles The Wallet Crew et <code>buildEmail()</code> peuvent-ils encore être utilisés ?</strong></summary>

Oui, mais cela devient une stratégie différente. Dans ce modèle, The Wallet Crew génère `Objet` et `Body`, et Salesforce Marketing Cloud n’est utilisé que comme passerelle de livraison. Dans ce cas, alignez l’asset Salesforce Marketing Cloud pour accepter le HTML généré et éviter le double templating.

</details>

<details>

<summary><strong>Où les identifiants SFMC doivent-ils être stockés ?</strong></summary>

Stockez-les comme secrets du tenant et chargez-les à l’exécution (comme dans l’exemple avec `getSecret('SFMC-CLIENTID')` et `getSecret('SFMC-CLIENTSECRET')`). N’intégrez pas en dur les identifiants dans les scripts.

</details>

<details>

<summary><strong>Que doit-on 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 un identifiant CRM fonctionne aussi lorsqu’il s’agit de la stratégie de clé de contact Salesforce Marketing Cloud. Conservez la cohérence avec la façon dont le parcours ou l’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.
