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

# Confirmation de réservation et récupération de réservation abandonnée

> Utilisez les événements personnalisés, Journeys et Data Feeds pour envoyer des emails de confirmation de réservation ou de récupération basés sur l'état de la réservation en temps réel.

## Aperçu

Dans ce tutoriel, vous allez configurer un flux de travail de réservation courant :

* Envoyer un email de confirmation de réservation après qu'un utilisateur complète une réservation.
* Envoyer un email de récupération si un utilisateur commence une réservation mais ne la complète pas à temps.

À la fin, vous aurez :

* Deux Événements Personnalisés (`booking_started`, `booking_complete`)
* Un Journey qui se divise selon l'achèvement vs l'abandon
* Un Data Feed de réservation pour les détails de confirmation
* Un Data Feed de coupon optionnel pour les incitations à la récupération

Ce guide se concentre sur la configuration de OneSignal. Votre système de réservation et backend peuvent être implémentés dans n'importe quel langage ou framework.

### Flux de configuration

1. Votre application suit un [événement personnalisé](./custom-events) `booking_started`.
2. Cela fait entrer l'utilisateur dans un Journey.
3. Le Journey attend un événement `booking_complete` et s'il n'est pas reçu à temps, il envoie des rappels de suivi.
4. Si la réservation se complète, OneSignal appelle un Data Feed de réservation au moment de l'envoi et envoie un email de confirmation avec les derniers détails de la réservation.
5. Si la réservation ne se complète pas dans la fenêtre d'attente, le Journey suit le chemin d'expiration et envoie un email de récupération.

***

## Configuration

### Prérequis

Avant de commencer, assurez-vous d'avoir :

* Une application OneSignal avec le canal [**Email**](./email-setup) activé
* Un endpoint backend qui peut renvoyer des données de réservation et/ou de coupon en JSON
* Un identifiant utilisateur stable partagé entre votre application, backend et [ID Externe](./users#external-id) OneSignal
* Accès aux [Événements Personnalisés](./custom-events)

### 1. Suivre les événements de réservation

Suivez les Événements Personnalisés suivants. Ceux-ci peuvent provenir de votre application (en utilisant notre SDK) ou de votre backend (en utilisant notre API REST).

**Noms d'événements :**

* `booking_started` — quand l'utilisateur commence le flux de réservation
* `booking_complete` — quand la réservation est complétée avec succès

<Tabs>
  <Tab title="Application - Mobile et Web">
    Utilisez la méthode `trackEvent()` sur notre [SDK Mobile](./mobile-sdk-reference) et/ou [SDK Web](./web-sdk-reference) pour envoyer des événements personnalisés directement depuis votre application/site web.

    ```js Exemple theme={null}
    OneSignal.User.trackEvent("booking_started");
    OneSignal.User.trackEvent("booking_complete");
    ```
  </Tab>

  <Tab title="Côté Serveur">
    Si vous suivez les événements depuis votre backend, utilisez l'[API Créer des Événements Personnalisés](/reference/create-custom-events) pour envoyer des événements à OneSignal.

    ```bash theme={null}
    curl --request POST \
      --url https://api.onesignal.com/apps/{app_id}/custom_events \
      --header 'Authorization: Key YOUR_APP_API_KEY' \
      --header 'Content-Type: application/json' \
      --data '{
        "events": [
          {
            "name": "booking_started",
            "external_id": "user123",
            "properties": {}
          }
        ]
      }'
    ```
  </Tab>
</Tabs>

<Note>
  Utilisez la même identité utilisateur lors du suivi des événements et lors du retour de données depuis votre backend. Les IDs non correspondants sont la cause la plus courante de personnalisation manquante.
</Note>

### 2. Créer des alias de Data Feed

Dans OneSignal, allez à **Paramètres > Data Feeds** et créez les alias suivants.

**Data Feed de Réservation :**
Utilisez ce feed pour extraire les derniers détails de réservation au moment de l'envoi.

* **Alias :** `booking_data`
* **Méthode :** GET
* **URL :**

```liquid Exemple d'endpoint theme={null}
https://your-domain.com/datafeed/booking?user_id={{subscription.external_id}}
```

Exemple de réponse :

```json JSON theme={null}
{
  "first_name": "Sam",
  "last_booking": {
    "service_type": "Consultation",
    "booking_date": "22 janvier 2026",
    "booking_time": "14:00",
    "price": 45
  }
}
```

**Data Feed de Coupon (optionnel) :**

Utilisez ce feed optionnel si vous voulez inclure un code de coupon dans votre email de récupération.

* **Alias :** `coupon`
* **Méthode :** GET
* **URL :**

```liquid Exemple d'endpoint theme={null}
https://your-domain.com/datafeed/coupon?user_id={{subscription.external_id}}
```

Exemple de réponse :

```json JSON theme={null}
{
  "first_name": "Sam",
  "code": "PROMO8F3K2",
  "discount_text": "10%",
  "expires_in_hours": 2,
  "deep_link": "https://your-domain.com/checkout?coupon=PROMO8F3K2"
}
```

<Warning>
  Sécurisez vos endpoints Data Feed. En production, envoyez une clé API dans les en-têtes de requête (par exemple `x-api-key`) et configurez cet en-tête dans **Paramètres > Data Feeds** au lieu d'intégrer des secrets dans l'URL.
</Warning>

### 3. Créer des modèles d'email

#### Email de confirmation de réservation :

**Objet :**

```text theme={null}
Vos détails de réservation
```

**Corps :**

```liquid theme={null}
Bonjour {{ data_feed.booking_data.first_name | default: "client" }},

Merci pour votre réservation ! Voici les détails de votre rendez-vous :

Service : {{ data_feed.booking_data.last_booking.service_type }}
Date : {{ data_feed.booking_data.last_booking.booking_date }}
Heure : {{ data_feed.booking_data.last_booking.booking_time }}
Prix : {{ data_feed.booking_data.last_booking.price }}€

Nous avons hâte de vous voir !
```

#### Email de récupération de réservation

**Objet :**

```text theme={null}
Complétez votre réservation et économisez
```

**Corps :**

<Tabs>
  <Tab title="Utilisant un Data Feed de Coupon">
    ```liquid theme={null}
    Bonjour {{ data_feed.coupon.first_name | default: "client" }},

    Terminez votre réservation dans les {{ data_feed.coupon.expires_in_hours }} heures suivantes et économisez
    {{ data_feed.coupon.discount_text }} avec ce code :

    {{ data_feed.coupon.code }}

    Utilisez-le ici :
    {{ data_feed.coupon.deep_link }}
    ```
  </Tab>

  <Tab title="Sans Data Feed de Coupon">
    ```text theme={null}
    Bonjour, 

    Vous n'avez pas encore terminé votre réservation ! 

    Complétez-la maintenant pour économiser sur votre prochain rendez-vous.

    Utilisez ce lien pour compléter votre réservation :
    [Insérer le lien profond ici]
    ```
  </Tab>
</Tabs>

<Note>
  Incluez toujours des filtres `default` dans Liquid pour éviter le contenu vide si un champ Data Feed est manquant.
</Note>

### 4. Construire le Journey

1. Dans OneSignal, allez à **Messages > Journeys > Créer un Journey**

2. Définissez le **Déclencheur d'Entrée** sur :
   * **Événement Personnalisé :** `booking_started`

3. Ajoutez une étape **Attendre Jusqu'à** :
   * **Condition :** Un Événement Personnalisé se produit
   * **Nom de l'événement :** `booking_complete`
   * **Temps d'attente maximum :** 10 minutes
   * Activez le chemin d'expiration

4. Configurez les branches :
   * **Terminé :** Envoyer un email de confirmation de réservation
     * **Data Feed :** `booking_data`
   * **Expiré :** Envoyer un email de récupération
     * **Data Feed :** `coupon`

<Info>
  La branche d'expiration vous permet de gérer l'abandon sans logique supplémentaire dans votre application. Voir :

  * [Paramètres des Journeys](./journeys-settings) - pour les détails sur les règles d'entrée et de sortie des Événements Personnalisés
  * [Actions des Journeys](./journeys-actions) - pour les détails sur les étapes Attendre Jusqu'à et les branches d'expiration
</Info>

### 5. Tester et vérifier

#### Vérifier les événements

Déclenchez les événements personnalisés depuis votre application ou backend et confirmez.

Dans OneSignal, allez à **Analytics > Événements Personnalisés** et confirmez que vous voyez :

* Les événements `booking_started` apparaissent pour votre ID Externe
* Les événements `booking_complete` apparaissent pour votre ID Externe

#### Vérifier les Data Feeds

Appelez manuellement vos endpoints Data Feed en utilisant un ID utilisateur connu et confirmez :

* Une réponse 200 est renvoyée
* Tous les champs attendus sont présents

#### Vérifier les emails

Envoyez des messages de test depuis l'éditeur Journey et confirmez :

* Les emails de réservation contiennent de vrais détails de réservation
* Les emails de récupération contiennent un coupon valide
* Aucune variable Liquid ne s'affiche vide

<Check>
  Si la personnalisation est manquante, confirmez que l'ID utilisateur dans la requête Data Feed correspond à l'utilisateur qui a déclenché le Journey.
</Check>

## Exemple : Implémentation Data Feed

<Accordion title="Exemples d'endpoints Data Feed Node.js">
  Cet exemple montre une implémentation Express minimale pour les Data Feeds de confirmation de réservation et de récupération. Votre langage backend, framework et source de données peuvent différer tant que la forme de réponse JSON correspond à vos modèles d'email.

  ### Exemple de Data Feed de Réservation

  ```js theme={null}
  import express from "express";

  const app = express();

  function dataFeedAuth(req, res, next) {
    if (req.headers["x-api-key"] !== process.env.DATAFEED_API_KEY) {
      return res.status(401).json({ error: "Unauthorized" });
    }
    next();
  }

  app.get("/datafeed/booking", dataFeedAuth, async (req, res) => {
    const { user_id } = req.query;

    if (!user_id) {
      return res.status(400).json({ error: "Missing user_id" });
    }

    const booking = await getLatestBookingForUser(user_id);

    if (!booking) {
      return res.status(404).json({ error: "No booking found" });
    }

    res.json({
      first_name: booking.first_name,
      last_booking: {
        service_type: booking.service_type,
        booking_date: booking.booking_date,
        booking_time: booking.booking_time,
        price: booking.price
      }
    });
  });
  ```

  ### Exemple de Data Feed de Coupon

  ```js theme={null}
  app.get("/datafeed/coupon", dataFeedAuth, async (req, res) => {
    const { user_id } = req.query;

    if (!user_id) {
      return res.status(400).json({ error: "Missing user_id" });
    }

    const coupon = await generateCouponForUser(user_id);

    res.json({
      first_name: coupon.first_name,
      code: coupon.code,
      discount_text: coupon.discount_text,
      expires_in_hours: coupon.expires_in_hours,
      deep_link: coupon.deep_link
    });
  });
  ```

  ### Directives d'implémentation

  * Gardez les réponses rapides (les Data Feeds sont appelés au moment de l'envoi)
  * Renvoyez toujours une structure JSON prévisible
  * Utilisez 404 quand aucune donnée n'existe
  * Sécurisez les endpoints avec une clé API envoyée via les en-têtes de requête
</Accordion>

## Problèmes courants

### L'email affiche des valeurs vides

* Le Data Feed a renvoyé 404
* Les noms de champs ont changé dans la réponse JSON
* Incompatibilité d'identité utilisateur

### Le Journey ne se divise pas

* L'événement `booking_complete` n'est pas suivi
* Incompatibilité de nom d'événement (sensible à la casse)
* L'événement se produit en dehors de la fenêtre d'attente

### Le Data Feed renvoie 401 ou 403

* Clé API manquante ou invalide
* En-tête non configuré dans les paramètres Data Feed

## Étapes suivantes

* Ajouter des propriétés d'événement (type de service, prix) pour des conditions Journey plus avancées
* Ajouter des étapes de récupération supplémentaires comme des rappels push ou SMS
* Utiliser les règles de sortie Journey pour éviter les messages de récupération répétés

***
