# HubSpot et un front headless : éviter les leads dupliqués

> Un snippet de déduplication des soumissions transmises à HubSpot depuis un front découplé sujet aux doubles clics et aux nouvelles tentatives réseau.

- Auteur : WordPress Développement
- Publié le : 2024-02-28
- Mis à jour le : 2024-02-28
- Catégorie : Headless &amp; API
- URL : https://www.wpmoderne.fr/headless/hubspot-front-headless-eviter-leads-dupliques/

## L’essentiel

- Un double clic ou une nouvelle tentative réseau peut créer deux contacts HubSpot pour une seule soumission réelle
- Un identifiant d'idempotence généré côté client permet de détecter une soumission déjà traitée
- L'API HubSpot upsert par e-mail évite la création de doublons sans nécessiter de logique de déduplication complexe côté serveur

4,7 % des soumissions du formulaire de démonstration produit d'un site SaaS headless créaient un second contact HubSpot strictement identique au premier, quelques secondes seulement après la soumission initiale. Ce taux, mesuré sur un mois de données, correspondait presque exactement au taux de doubles clics observé sur le bouton d'envoi lors des tests utilisateurs, combiné à quelques cas de nouvelles tentatives automatiques déclenchées par un intercepteur réseau du navigateur en cas de coupure momentanée.

Le problème ne se situait pas côté HubSpot, dont l'API se contente de créer ce qu'on lui demande de créer, mais dans l'absence de tout mécanisme empêchant deux requêtes identiques d'aboutir à deux créations distinctes côté endpoint WordPress relayant vers HubSpot.

## D'où viennent les doubles soumissions

Trois scénarios expliquaient la quasi-totalité des doublons observés :

- Un double clic rapide sur le bouton d'envoi, avant que l'interface n'ait eu le temps de le désactiver visuellement
- Une nouvelle tentative automatique déclenchée par le navigateur lors d'une coupure réseau de quelques centaines de millisecondes
- Un retour arrière du navigateur suivi d'une nouvelle soumission du même formulaire déjà rempli

## Première ligne de défense : upsert par e-mail côté HubSpot

> L'essentiel à retenir : Un double clic ou une nouvelle tentative réseau peut créer deux contacts HubSpot pour une seule soumission réelle ; Un identifiant d'idempotence généré côté client permet de détecter une soumission déjà traitée ; L'API HubSpot upsert par e-mail évite la création de doublons sans nécessiter de logique de déduplication complexe côté serveur

L'API HubSpot propose une opération de type upsert basée sur l'adresse e-mail, qui met à jour un contact existant plutôt que d'en créer un nouveau si l'adresse est déjà connue :

```
const reponse = await fetch(
  'https://api.hubapi.com/crm/v3/objects/contacts/' + encodeURIComponent(email) + '?idProperty=email',
  {
    method: 'PATCH',
    headers: { Authorization: `Bearer ${process.env.HUBSPOT_TOKEN}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ properties: { email, source_demande: 'demo' } }),
  }
);
```

Ce mécanisme couvre déjà une grande partie des cas de doublons liés à l'adresse e-mail. Il ne suffit cependant pas seul quand la logique métier associée à chaque soumission (envoi de notification interne, création d'une tâche de suivi commercial) ne doit, elle, s'exécuter qu'une seule fois par soumission réelle.

## Deuxième ligne de défense : un identifiant d'idempotence

Un identifiant unique, généré côté client au moment où le formulaire s'affiche, est transmis avec la soumission et vérifié côté serveur avant tout traitement :

```
// Côté client, à l'affichage du formulaire
const idIdempotence = crypto.randomUUID();

// Côté endpoint WordPress
add_action('rest_api_init', function () {
    register_rest_route('leads/v1', '/demo', [
        'methods' => 'POST',
        'callback' => 'traiter_demande_demo',
        'permission_callback' => '__return_true',
    ]);
});

function traiter_demande_demo(WP_REST_Request $request) {
    $id_idempotence = sanitize_text_field($request->get_param('id_idempotence'));

    if (get_transient('demo_' . $id_idempotence)) {
        return new WP_REST_Response(['statut' => 'deja_traite'], 200);
    }

    set_transient('demo_' . $id_idempotence, true, 15 * MINUTE_IN_SECONDS);

    // traitement réel : envoi vers HubSpot, notification interne, etc.

    return new WP_REST_Response(['statut' => 'ok'], 200);
}
```

Ce mécanisme couvre le cas du double clic et de la nouvelle tentative réseau automatique, puisque les deux requêtes portent le même identifiant d'idempotence généré une seule fois à l'affichage du formulaire, indépendamment de la valeur de l'e-mail saisi.

## Désactiver visuellement le bouton dès le premier clic

Un correctif complémentaire, purement côté interface, désactive immédiatement le bouton d'envoi dès la première interaction, avant même que la requête réseau ne parte, réduisant mécaniquement la fenêtre de double clic à quasiment zéro :

```
const [envoiEnCours, setEnvoiEnCours] = useState(false);

async function soumettre(e) {
  e.preventDefault();
  if (envoiEnCours) return;
  setEnvoiEnCours(true);
  // ... envoi de la requête
}
```

## Résultat après correction

Après déploiement des deux mécanismes combinés (upsert HubSpot et identifiant d'idempotence côté serveur), le taux de doublons mesuré est retombé à 0,1 % sur le mois suivant, ce résidu correspondant essentiellement à des cas où deux personnes différentes du même foyer partageaient temporairement une même adresse e-mail générique.

## En résumé

La déduplication des leads transmis à HubSpot depuis un front headless se joue à trois niveaux complémentaires : l'upsert natif par e-mail côté HubSpot, un identifiant d'idempotence généré côté client et vérifié côté serveur, et une désactivation immédiate de l'interface au premier clic. Aucun de ces trois mécanismes pris isolément ne couvre l'ensemble des cas observés en production.
