OptimoCMSDocs
Guides

Sync webhook avec CRM

Gardez votre CRM automatiquement synchronisé avec OptimoCMS via les webhooks. Apprenez à configurer les webhooks, traiter les payloads et vérifier les signatures.

Sync webhook avec votre CRM

Les webhooks envoient des notifications en temps réel à votre serveur lorsque quelque chose se passe dans OptimoCMS — un formulaire est soumis, une commande est passée ou une page est publiée.

Dans ce tutoriel :

  • Créer un webhook via le SDK
  • Construire un serveur Express pour recevoir les payloads
  • Vérification cryptographique des signatures
  • Traiter les payloads et les transmettre à un CRM

Prérequis

  • Node.js 18+
  • npm install @optimocms/sdk express
  • Un endpoint publiquement accessible (utilisez ngrok pour les tests locaux)

Étape 1 — Créer un webhook

SDK

import { OptimoCMS } from '@optimocms/sdk';

const client = new OptimoCMS({
  apiKey: process.env.OPTIMOCMS_API_KEY!,
});

const webhook = await client.webhooks.create('site_abc123', {
  url: 'https://votre-serveur.fr/webhooks/optimocms',
  events: ['form.submitted', 'order.created', 'booking.created'],
});

console.log(`Webhook créé : ${webhook.id}`);
console.log(`Secret : ${webhook.secret}`);

REST

curl -X POST https://api.optimocms.com/v1/sites/$SITE_ID/webhooks \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://votre-serveur.fr/webhooks/optimocms",
    "events": ["form.submitted", "order.created", "booking.created"]
  }'

Étape 2 — Construire un endpoint webhook

Créez un serveur Express qui reçoit et traite les payloads webhook :

import express from 'express';
import crypto from 'node:crypto';

const app = express();
const WEBHOOK_SECRET = process.env.OPTIMOCMS_WEBHOOK_SECRET!;

app.post(
  '/webhooks/optimocms',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.headers['x-optimocms-signature'] as string;
    const timestamp = req.headers['x-optimocms-timestamp'] as string;

    if (!verifySignature(req.body, signature, timestamp)) {
      console.error('Signature webhook invalide');
      return res.status(401).json({ error: 'Invalid signature' });
    }

    const event = JSON.parse(req.body.toString());

    switch (event.type) {
      case 'form.submitted':
        handleFormSubmission(event.data);
        break;
      case 'order.created':
        handleNewOrder(event.data);
        break;
      case 'booking.created':
        handleNewBooking(event.data);
        break;
      default:
        console.log(`Type d'événement inconnu : ${event.type}`);
    }

    res.status(200).json({ received: true });
  }
);

app.listen(3000, () => {
  console.log('Serveur webhook en écoute sur le port 3000');
});

Étape 3 — Vérification des signatures

OptimoCMS signe chaque webhook avec HMAC-SHA256. Vérifiez toujours avant le traitement :

function verifySignature(
  body: Buffer,
  signature: string,
  timestamp: string
): boolean {
  if (!signature || !timestamp) return false;

  const timestampMs = parseInt(timestamp, 10);
  const ageMs = Date.now() - timestampMs;
  if (ageMs > 5 * 60 * 1000) {
    console.error(`Webhook trop ancien : ${ageMs}ms`);
    return false;
  }

  const payload = `${timestamp}.${body.toString()}`;
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');

  const expectedBuffer = Buffer.from(expected, 'hex');
  const receivedBuffer = Buffer.from(signature, 'hex');

  if (expectedBuffer.length !== receivedBuffer.length) return false;

  return crypto.timingSafeEqual(expectedBuffer, receivedBuffer);
}

Étape 4 — Transmettre les payloads au CRM

Exemple : transmettre les données de formulaire à HubSpot CRM :

interface FormSubmission {
  formId: string;
  siteId: string;
  fields: Record<string, string>;
  submittedAt: string;
}

async function handleFormSubmission(data: FormSubmission): Promise<void> {
  const { fields } = data;

  const response = await fetch('https://api.hubapi.com/crm/v3/objects/contacts', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.HUBSPOT_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      properties: {
        firstname: fields.firstName || fields.name?.split(' ')[0] || '',
        lastname: fields.lastName || fields.name?.split(' ').slice(1).join(' ') || '',
        email: fields.email,
        phone: fields.phone || '',
        company: fields.company || '',
        hs_lead_status: 'NEW',
        source: `OptimoCMS form: ${data.formId}`,
      },
    }),
  });

  if (!response.ok) {
    const error = await response.text();
    console.error(`Sync HubSpot échouée : ${error}`);
    throw new Error(`CRM sync failed: ${response.status}`);
  }

  console.log(`✓ Contact créé dans HubSpot pour ${fields.email}`);
}

Événements webhook disponibles

ÉvénementDéclencheur
form.submittedUn visiteur soumet un formulaire
order.createdNouvelle commande
order.updatedChangement de statut de commande
booking.createdNouvelle réservation
booking.cancelledRéservation annulée
page.createdNouvelle page créée
page.updatedContenu de page modifié
page.deletedPage supprimée
site.publishedSite publié en production

Bonnes pratiques

  1. Toujours vérifier la signature — Ne faites jamais confiance aveuglément aux requêtes entrantes
  2. Répondre rapidement avec 200 — Traitez le payload de manière asynchrone si c'est long
  3. Idempotence — Utilisez le champ id pour détecter les doublons
  4. Tolérant aux retries — OptimoCMS relance automatiquement les livraisons échouées (max 5x)
  5. Logging — Loggez chaque webhook entrant pour le débogage

Prochaines étapes

On this page