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énement | Déclencheur |
|---|---|
form.submitted | Un visiteur soumet un formulaire |
order.created | Nouvelle commande |
order.updated | Changement de statut de commande |
booking.created | Nouvelle réservation |
booking.cancelled | Réservation annulée |
page.created | Nouvelle page créée |
page.updated | Contenu de page modifié |
page.deleted | Page supprimée |
site.published | Site publié en production |
Bonnes pratiques
- Toujours vérifier la signature — Ne faites jamais confiance aveuglément aux requêtes entrantes
- Répondre rapidement avec 200 — Traitez le payload de manière asynchrone si c'est long
- Idempotence — Utilisez le champ
idpour détecter les doublons - Tolérant aux retries — OptimoCMS relance automatiquement les livraisons échouées (max 5x)
- Logging — Loggez chaque webhook entrant pour le débogage
Prochaines étapes
- Référence API : Webhooks — Documentation complète de l'API webhook
- Pipeline CI/CD — Automatiser les déploiements
- Créer un site de restaurant — Site exemple avec formulaires
Automatisation multi-sites
Créez et gérez des dizaines de sites de manière programmatique avec le SDK OptimoCMS. Idéal pour les franchises, agences et plateformes white-label.
Pipeline CI/CD
Automatisez les mises à jour de contenu et la publication avec GitHub Actions et le SDK OptimoCMS. Du staging à la production en un seul push.