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

Blocs Gutenberg

Un bloc et HubSpot : synchroniser sans dépendre d’un webhook fragile

Architecture de synchronisation bidirectionnelle entre un bloc de formulaire et HubSpot, basée sur une file d'attente plutôt que sur des webhooks directs peu fiables.

Par Clément Hadrot • 15 mars 2026 • 4 min de lecture • Aucun commentaire
Un bloc et HubSpot : synchroniser sans dépendre d'un webhook fragile

Un webhook HubSpot qui échoue silencieusement pendant une maintenance de l’API, un formulaire soumis pendant cette fenêtre, et la donnée du prospect qui disparaît sans que personne ne s’en aperçoive avant plusieurs semaines : ce scénario, vécu sur un projet de génération de leads, a conduit à repenser entièrement l’architecture de synchronisation entre un bloc de formulaire et HubSpot.

Cette architecture ne couvre pas la configuration du CRM HubSpot lui-même (pipelines, propriétés personnalisées déjà en place) ni les workflows marketing qui exploitent ensuite ces données, uniquement le mécanisme de synchronisation entre le bloc et l’API HubSpot.

Pourquoi un appel direct synchrone est fragile

L’architecture initiale appelait l’API HubSpot directement au moment de la soumission du formulaire, dans le même cycle de requête que la réponse envoyée au visiteur. Toute latence ou indisponibilité côté HubSpot se répercutait directement sur l’expérience du visiteur, qui patientait sur un écran de chargement, et toute erreur silencieuse (timeout réseau, quota d’API dépassé) faisait disparaître la donnée sans trace exploitable.

La file d’attente locale comme tampon

La nouvelle architecture introduit une table personnalisée, wp_hubspot_file_synchronisation, qui enregistre chaque soumission de formulaire avant tout appel à l’API HubSpot. Le visiteur reçoit une confirmation immédiate dès l’écriture en base locale, sans attendre la réponse de HubSpot :

function contact_bloc_enregistrer_soumission( array $donnees ) {
    global $wpdb;

    $wpdb->insert(
        $wpdb->prefix . 'hubspot_file_synchronisation',
        array(
            'donnees'       => wp_json_encode( $donnees ),
            'statut'        => 'en_attente',
            'tentatives'    => 0,
            'date_creation' => current_time( 'mysql' ),
        )
    );

    return true; // Confirmation immédiate, indépendante de HubSpot.
}

Le traitement différé via wp-cron

Un événement wp-cron planifié toutes les cinq minutes traite les entrées en attente, par lots limités pour ne pas saturer les quotas d’appels de l’API HubSpot :

function contact_traiter_file_hubspot() {
    global $wpdb;

    $lignes = $wpdb->get_results(
        "SELECT * FROM {$wpdb->prefix}hubspot_file_synchronisation
         WHERE statut = 'en_attente' AND tentatives < 3
         ORDER BY date_creation ASC
         LIMIT 20"
    );

    foreach ( $lignes as $ligne ) {
        contact_tenter_synchronisation_hubspot( $ligne );
    }
}
add_action( 'contact_synchronisation_hubspot', 'contact_traiter_file_hubspot' );
L'essentiel à retenir : File d'attente locale absorbant les échecs temporaires de l'API HubSpot ; Traitement différé via wp-cron plutôt qu'un appel synchrone bloquant ; Rejeu automatique des tentatives échouées avec recul exponentiel

Le recul exponentiel entre les tentatives

Chaque échec incrémente le compteur de tentatives et calcule un délai avant la prochaine tentative, croissant à chaque échec plutôt que fixe, pour éviter de marteler une API HubSpot déjà en difficulté :

function contact_tenter_synchronisation_hubspot( $ligne ) {
    global $wpdb;

    $reponse = wp_remote_post( HUBSPOT_ENDPOINT_CONTACTS, array(
        'headers' => array( 'Authorization' => 'Bearer ' . HUBSPOT_TOKEN ),
        'body'    => $ligne->donnees,
        'timeout' => 10,
    ) );

    if ( is_wp_error( $reponse ) || 200 !== wp_remote_retrieve_response_code( $reponse ) ) {
        $delai_minutes = pow( 5, $ligne->tentatives + 1 ); // 5, 25, 125 minutes
        $wpdb->update(
            $wpdb->prefix . 'hubspot_file_synchronisation',
            array(
                'tentatives'      => $ligne->tentatives + 1,
                'prochaine_tentative' => date( 'Y-m-d H:i:s', strtotime( "+{$delai_minutes} minutes" ) ),
            ),
            array( 'id' => $ligne->id )
        );
        return;
    }

    $wpdb->update(
        $wpdb->prefix . 'hubspot_file_synchronisation',
        array( 'statut' => 'synchronise' ),
        array( 'id' => $ligne->id )
    );
}

Ce que ça change concrètement

  • Le visiteur ne subit plus jamais la latence ou l'indisponibilité de l'API HubSpot.
  • Chaque échec reste visible et rejouable, plutôt que silencieusement perdu.
  • Après trois tentatives échouées, la ligne passe en statut « échec définitif » et déclenche une alerte à l'équipe.
ApprocheImpact visiteur en cas d'incident HubSpotTraçabilité des échecs
Appel synchrone directÉcran de chargement, parfois erreur visibleAucune, donnée perdue
File d'attente + wp-cronAucun, confirmation immédiateComplète, rejouable

Un webhook qui fonctionne neuf fois sur dix n'est pas fiable : il est simplement invisible dans son échec la dixième fois, jusqu'à ce que quelqu'un s'en aperçoive trop tard.

En résumé

Découpler la soumission du formulaire de l'appel réel à l'API HubSpot, via une file d'attente locale traitée par wp-cron avec recul exponentiel, élimine le principal point de fragilité observé sur l'architecture initiale. Le coût est modeste (une table supplémentaire, une tâche planifiée), le gain en fiabilité largement supérieur à ce coût sur un flux de génération de leads où chaque contact perdu a une valeur commerciale réelle.

Partager :

À propos de l'auteur

Clément Hadrot

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

Voir tous ses articles

Dans la même veine

À lire aussi