Webhooks
Real-time event notifications
Overview
Webhooks let you receive real-time HTTP notifications when events occur in your Loamly workspace. Use webhooks to:
- Sync data to your CRM when a visitor converts
- Trigger Slack notifications for high-intent visitors
- Update your database when new AI mentions are detected
- Build custom integrations with your internal tools
Setting up webhooks
- Go to your dashboard → Settings → Webhooks
- Click Add Webhook
- Enter your endpoint URL (must be HTTPS)
- Select the events you want to receive
- Click Create Webhook
- Copy the signing secret for verification
HTTPS required
Webhook endpoints must use HTTPS. We do not send webhooks to HTTP URLs for security reasons.
Available events
| Event | Description |
|---|---|
visitor.created | A new visitor arrived on your site |
visitor.converted | A visitor submitted a form or completed a conversion goal |
visitor.identified | A visitor's email was captured |
mention.created | A new AI mention of your brand was detected |
mention.attributed | An AI mention was linked to a website visit |
payment.received | A Stripe payment was attributed (requires Stripe integration) |
Webhook payload
All webhooks are sent as POST requests with a JSON body:
{
"id": "evt_abc123xyz",
"type": "visitor.converted",
"created_at": "2024-12-18T14:30:00Z",
"data": {
"visitor_id": "vis_xyz789",
"source": "chatgpt",
"intent": "active_purchase_intent",
"email": "user@example.com",
"form_name": "Contact Form",
"page_url": "https://example.com/pricing",
"conversion_value": null
}
}Event-specific payloads
visitor.created
{
"id": "evt_...",
"type": "visitor.created",
"data": {
"visitor_id": "vis_...",
"source": "perplexity",
"referrer": "https://perplexity.ai/...",
"landing_page": "/",
"country": "US",
"city": "New York",
"device": "desktop",
"browser": "Chrome"
}
}mention.created
{
"id": "evt_...",
"type": "mention.created",
"data": {
"mention_id": "mnt_...",
"platform": "chatgpt",
"query": "best SaaS analytics tools",
"position": 3,
"sentiment": "positive",
"competitors": ["Mixpanel", "Amplitude"]
}
}Verifying webhooks
Every webhook includes a signature header for verification. Always verify signatures to ensure requests come from Loamly.
Signature header
X-Loamly-Signature: t=1703001234,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdVerification steps
- Extract the timestamp and signature from the header
- Prepare the signed payload (timestamp + "." + request body)
- Compute HMAC-SHA256 with your signing secret
- Compare the computed signature with the received signature
- Check that the timestamp is within 5 minutes of current time
Example: Node.js
import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const [timestampPart, signaturePart] = signature.split(',');
const timestamp = timestampPart.split('=')[1];
const expectedSig = signaturePart.split('=')[1];
// Check timestamp is recent (5 min tolerance)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
throw new Error('Webhook timestamp too old');
}
// Compute expected signature
const signedPayload = `${timestamp}.${payload}`;
const hmac = crypto.createHmac('sha256', secret);
hmac.update(signedPayload);
const computedSig = hmac.digest('hex');
// Compare signatures (timing-safe)
if (!crypto.timingSafeEqual(
Buffer.from(expectedSig),
Buffer.from(computedSig)
)) {
throw new Error('Invalid webhook signature');
}
return JSON.parse(payload);
}Always verify signatures
Never trust webhook payloads without verifying the signature. Attackers could send fake webhooks to your endpoint.
Retry behavior
If your endpoint returns a non-2xx status code or times out, Loamly retries the webhook with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts, the webhook is marked as failed and no longer retried.
Best practices
- Return 200 quickly. Process webhooks asynchronously after acknowledging receipt.
- Handle duplicates. Use the event ID to deduplicate in case of retries.
- Log failed webhooks. Check the Webhooks page in Settings for delivery history.