# Adobe Journey Optimizer

Utilisez cette option lorsque vous avez **Adobe Journey Optimizer (AJO)** et que vous voulez **envois déclenchés par API** qui conviennent à l'orchestration moderne des parcours.

Avant d'aller plus loin, assurez-vous de comprendre comment le fournisseur de script fonctionne dans The Wallet Crew. Commencez par [Adobe Marketing Cloud](https://app.gitbook.com/s/WLc8AHXW4tdrAXUBfrYF/connect/email-provider/adobe-marketing-cloud) et le préalable [Extensibilité EmailSender](https://app.gitbook.com/s/WLc8AHXW4tdrAXUBfrYF/connect/custom-connector/emailsender-extensibility).

### Quand l'utiliser

Vous choisissez généralement AJO lorsque vous souhaitez des envois quasi en temps réel et que votre équipe marketing gère déjà des parcours dans AJO.

### Configuration requise dans Adobe

Créez un parcours ou une campagne déclenchée par API qui peut accepter un appel d'exécution. Ensuite, configurez l'action email.

Au minimum, mettez-vous d'accord sur ce que votre script envoie à AJO.

* **HTML entièrement rendu** de The Wallet Crew (`Objet`, `Corps`).
* Ou **variables de contexte uniquement**, avec le modèle géré dans AJO.

{% hint style="warning" %}
Choisissez une stratégie de rendu. Évitez de dupliquer la mise en modèle à la fois dans The Wallet Crew et dans Adobe.
{% endhint %}

### Remarques d'implémentation (OAuth + trigger)

AJO utilise Adobe IMS pour OAuth2 (client credentials). Votre script demande généralement un jeton d'accès, puis appelle le point de terminaison d'exécution AJO pour votre campagne ou parcours.

{% hint style="info" %}
Les points de terminaison Adobe et la forme des charges utiles dépendent de la configuration de votre organisation, de la région et de la fonctionnalité AJO que vous utilisez (parcours vs campagne). Traitez l'extrait ci-dessous comme un squelette et alignez-le avec la documentation officielle d'Adobe pour votre version produit.
{% endhint %}

Stockez ces valeurs en tant que secrets avant de tester :

* `adobe-clientId`
* `adobe-clientSecret`
* `adobe-orgId`
* `adobe-sandboxName`
* `adobe-ajo-triggerUrl` (URL complète du trigger AJO)
* `adobe-scope` (optionnel, dépend de votre configuration Adobe)

{% code title="Exemple Adobe Journey Optimizer (implémentation SendEmail)" %}

```javascript
import { getSecret } from "neo/secrets";

const CUSTOM_DOMAIN = "wallet.brand.com";
const TENANTID = "brand";

// Adobe IMS (OAuth2 client credentials)
// Votre environnement d'exécution fournit un `fetch` personnalisé capable d'effectuer des flux OAuth client credentials.
const IMS_TOKEN_URL = "https://ims-na1.adobelogin.com/ims/token/v3";

/**
 * @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 à rendre.
 * @param {Object.<string, any>} data - Données du modèle passées au script.
 * @param {string[]} cultures - Noms des cultures disponibles fournis par le fournisseur de cultures.
 * @param {(templateName: string) => Promise<EmailData>} buildEmail
 * Rappel qui retourne le contenu final de l’e‑mail rendu.
 *
 * @returns {Promise<void>}
 */
async function sendEmail(recipient, emailTemplate, data, cultures, buildEmail) {
  const email = recipient;
  const countryCode = data["country"] || "fr";
  const language = `${cultures[0]?.toLowerCase()?.substring(0, 2) || "fr"}_${countryCode.toLowerCase()}`;
  const customerId = data["id.customerId"];

  if (!customerId) {
    throw new Error('Missing "id.customerId" in email data.');
  }

  // URL sur laquelle le client doit cliquer pour télécharger sa carte.
  // Vous pouvez changer le chemin pour correspondre à la disposition de distribution.
  const url = `https://${CUSTOM_DOMAIN}/${TENANTID}/pass?id.customerId=${encodeURIComponent(customerId)}`;

  // Optionnel : conservez le rendu The Wallet Crew disponible.
  // Si votre modèle AJO est entièrement géré dans Adobe, vous pouvez supprimer ceci.
  const rendered = await buildEmail(emailTemplate);

  // La configuration AJO doit être fournie en tant que secrets.
  // Utilisez une URL complète pour éviter d'encoder en dur des chemins spécifiques au produit dans ce script.
  // Exemple (varie selon la configuration) : "https://platform.adobe.io/journey/execute/<CAMPAIGN_OR_JOURNEY_ID>"
  const ajoTriggerUrl = await getSecret("adobe-ajo-triggerUrl");
  const orgId = await getSecret("adobe-orgId");
  const sandboxName = await getSecret("adobe-sandboxName");
  const clientId = await getSecret("adobe-clientId");
  const clientSecret = await getSecret("adobe-clientSecret");

  // Laissez le scope configurable. Différentes configurations Adobe requièrent des scopes différents.
  // Valeurs d'exemple observées : "openid,AdobeID"
  let scope = "openid,AdobeID";
  try {
    scope = (await getSecret("adobe-scope")) || scope;
  } catch (e) {
    // Secret optionnel. Conservez le scope par défaut.
  }

  // Votre `fetch` d'exécution gère les identifiants OAuth client et attache le jeton.
  // Cela évite d'appeler manuellement IMS puis de transmettre le token Bearer.
  const result = await fetch(ajoTriggerUrl, {
    Method: "POST",
    Authentication: {
      mode: "OAuth2.0",
      grantType: "clientCredentials",
      sendCredentialsAsFormParams: true,
      accessTokenUrl: IMS_TOKEN_URL,
      clientId,
      clientSecret,
      scope,
    },
    Headers: {
      "x-api-key": clientId,
      "x-gw-ims-org-id": orgId,
      "x-sandbox-name": sandboxName,
      "Content-Type": "application/json",
    },
    Body: JSON.stringify({
      // La forme exacte de la charge utile doit correspondre à la configuration de votre campagne/parcours déclenchée par API AJO.
      // Conservez ce contrat stable entre votre script et votre ressource AJO.
      recipient: {
        email,
        language,
      },
      context: {
        // Variable minimale pour un modèle géré par Adobe :
        url,

        // Variables optionnelles si vous souhaitez réutiliser le rendu The Wallet Crew dans Adobe :
        subject: rendered.Subject,
        body: rendered.Body,

        // Métadonnées utiles pour le routage / le débogage :
        template: emailTemplate,
        customerId,
      },
    }),
    ThrowOnError: false,
  });

  if (result.StatusCode < 200 || result.StatusCode >= 300) {
    throw new Error(`L'appel de trigger AJO a échoué (${result.StatusCode}) : ${result.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 ces points :

* AJO reçoit l'appel d'exécution et l'accepte.
* L'action email AJO a accès aux champs de contexte que vous envoyez.
* Si vous transmettez du HTML, l'email final s'affiche correctement dans les clients courants.

### FAQ

<details>

<summary><strong>Avons-nous besoin d'un « parcours déclenché par API » dans AJO ?</strong></summary>

Oui. Votre script a besoin d'une ressource AJO publiée qui peut être déclenchée par un appel API. Le type exact de ressource (parcours vs campagne) dépend de ce que votre organisation Adobe utilise.

</details>

<details>

<summary><strong>AJO peut-elle envoyer un email construit par The Wallet Crew ?</strong></summary>

Oui. Un schéma courant consiste à appeler `buildEmail()` dans votre script, puis à transmettre `subject` et `body` en tant que contexte à AJO. Votre action email AJO doit être configurée pour utiliser ces champs.

</details>

<details>

<summary><strong>Comment tester sans envoyer d'emails à de vrais clients ?</strong></summary>

Utilisez un sandbox AJO si vous en avez un. Si ce n'est pas le cas, limitez les tests aux adresses internes et créez un parcours/campagne « test » dédié. Conservez le contrat de charge utile identique à la production pour éviter des ruptures de schéma de dernière minute.

</details>

<details>

<summary><strong>Pourquoi avons-nous besoin d'autant d'en-têtes Adobe ?</strong></summary>

Les gateways AJO exigent couramment des en-têtes org, sandbox et clé API pour le routage et l'autorisation. L'ensemble exact peut varier selon la configuration et la région Adobe, donc considérez la documentation officielle d'Adobe comme source de vérité pour votre locataire.

</details>
