Le WordPress d'aujourd'hui, décodé pour les développeurs

Blocs Gutenberg

Un bloc et HubSpot : synchroniser un lead sans passer par un webhook externe

Un bloc formulaire peut créer un contact HubSpot en appelant directement l'API CRM, sans middleware ni service tiers, à condition de gérer proprement les erreurs.

Par WordPress Développement • 3 février 2023 • 4 min de lecture • Aucun commentaire
Un bloc et HubSpot : synchroniser un lead sans passer par un webhook externe

« Pourquoi passer par Zapier pour créer un contact HubSpot quand une seule requête HTTP suffit ? » C’est la question posée par un développeur en train de simplifier un tunnel de formulaires trop dépendant d’outils tiers payants. La réponse tient dans un bloc dynamique de formulaire qui appelle directement l’API CRM de HubSpot au moment de la soumission, sans webhook intermédiaire ni service d’automatisation externe.

Ce choix a un coût : le code du bloc doit gérer lui-même l’authentification, la structure de la requête et surtout les erreurs renvoyées par HubSpot (contact déjà existant, propriété invalide, quota dépassé). C’est plus de travail qu’un simple webhook Zapier, mais c’est aussi plus rapide à l’exécution et beaucoup moins coûteux à l’usage.

Créer une application privée HubSpot

Depuis 2022, HubSpot recommande les applications privées plutôt que les anciennes clés API globales, désormais dépréciées. Une application privée génère un jeton d’accès (pat-…) scoppé à des permissions précises — ici, la portée crm.objects.contacts.write suffit. Ce jeton est stocké côté WordPress dans une constante définie hors du répertoire public :

define( 'ACME_HUBSPOT_TOKEN', 'pat-eu1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' );

Le rendu du bloc formulaire

Le bloc est dynamique, avec un render_callback qui affiche un formulaire HTML classique (nom, e-mail, source de contact) posté vers un point de terminaison REST maison plutôt que directement vers HubSpot — cela évite d’exposer le jeton d’application côté navigateur.

add_action( 'rest_api_init', function() {
    register_rest_route( 'acme/v1', '/lead', [
        'methods'  => 'POST',
        'callback' => 'acme_create_hubspot_contact',
        'permission_callback' => '__return_true',
    ] );
} );
L'essentiel à retenir : Un jeton d'application privée suffit, pas de webhook ; L'appel API se fait côté serveur WordPress ; Les erreurs HubSpot doivent remonter jusqu'au visiteur

L’appel à l’API CRM et la gestion des erreurs

La fonction de rappel construit la requête vers https://api.hubapi.com/crm/v3/objects/contacts avec wp_remote_post(), en interprétant systématiquement le code de statut retourné :

function acme_create_hubspot_contact( WP_REST_Request $request ) {
    $email = sanitize_email( $request->get_param( 'email' ) );

    if ( empty( $email ) || ! is_email( $email ) ) {
        return new WP_Error( 'invalid_email', 'Adresse e-mail invalide.', [ 'status' => 400 ] );
    }

    $response = wp_remote_post( 'https://api.hubapi.com/crm/v3/objects/contacts', [
        'headers' => [
            'Authorization' => 'Bearer ' . ACME_HUBSPOT_TOKEN,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode( [
            'properties' => [
                'email'     => $email,
                'firstname' => sanitize_text_field( $request->get_param( 'firstname' ) ),
                'lead_source' => 'bloc-formulaire-site',
            ],
        ] ),
        'timeout' => 8,
    ] );

    if ( is_wp_error( $response ) ) {
        return new WP_Error( 'hubspot_unreachable', 'Service CRM injoignable.', [ 'status' => 502 ] );
    }

    $code = wp_remote_retrieve_response_code( $response );

    if ( 409 === $code ) {
        return rest_ensure_response( [ 'status' => 'already_exists' ] );
    }

    if ( $code >= 400 ) {
        return new WP_Error( 'hubspot_rejected', 'Le CRM a refusé la création du contact.', [ 'status' => $code ] );
    }

    return rest_ensure_response( [ 'status' => 'created' ] );
}

Le code 409 mérite une attention particulière : HubSpot le renvoie quand un contact possède déjà cette adresse e-mail. Ce n’est pas une erreur au sens métier — le bloc doit alors afficher un message de confirmation plutôt qu’un message d’échec, sans quoi un visiteur récurrent recevrait toujours un message d’erreur trompeur.

Limites de quota et robustesse

Une application privée HubSpot sur un compte standard dispose d’un quota de 100 000 appels par jour, largement suffisant pour un formulaire de contact classique, mais un pic de trafic (campagne publicitaire, passage sur un plateau télé) peut ponctuellement s’en approcher. Le code doit prévoir le cas d’un code 429 (too many requests) et informer le visiteur que sa demande a été mise en attente plutôt que de la perdre silencieusement.

  • Stocker chaque tentative en base locale avant l’appel API, pour pouvoir rejouer les échecs.
  • Ne jamais bloquer l’interface du visiteur pendant l’appel réseau sans limite de temps (timeout explicite).
  • Prévoir une file d’attente (table dédiée ou wp_schedule_single_event()) pour les cas de code 429 ou 502.

Je recommande de toujours conserver une copie locale du lead avant l’appel HubSpot : en cas d’incident réseau côté CRM, la donnée n’est jamais perdue et peut être resynchronisée après coup.

Pour aller plus loin

Cette intégration directe convient à un flux de contact simple. Dès que la logique se complexifie — scoring multi-étapes, séquences d’e-mails conditionnelles, affectation automatique à un commercial — les workflows HubSpot natifs redeviennent pertinents, et il vaut mieux laisser le bloc se contenter de créer le contact, en confiant la suite à l’outil prévu pour cela.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi