Wire Mailtarget Delivery Events to Your CRM
Stream Mailtarget webhook events into your CRM so customer-facing teams see email engagement alongside other contact activity. Sales sees who opened the proposal. Support sees who got the order confirmation.
Who this is for
Developers integrating Mailtarget with Salesforce, HubSpot, Zendesk, or a custom CRM.
The Mailtarget surface
| Component | Used for |
|---|---|
| Webhooks | Event source |
| Webhook security policies | HMAC signature verification |
metadata on send requests | Carry CRM correlation IDs (contact ID, deal ID) |
Execution
Step 1: Add CRM IDs to send metadata
Every send carries a metadata object that echoes into webhook events. Include the CRM identifiers you want to correlate.
await fetch("https://transmission.mailtarget.co/v1/layang/transmissions", {
method: "POST",
headers: { ... },
body: JSON.stringify({
subject: "Your proposal is ready",
from: { email: "sales@your-domain.com" },
to: [{ email: contact.email }],
bodyHtml: proposalBody,
metadata: {
crm_contact_id: contact.id,
crm_deal_id: deal.id,
crm_owner: "alice@yourcompany.com"
}
})
});
Step 2: Register a webhook in the dashboard
URL: https://your-app.com/webhooks/mailtarget
Events: delivery, open, click, bounce, complaint, unsubscribe
Secret: <generate a long random string, store in your secrets manager>
Step 3: Verify and forward
Your webhook handler:
- Verifies the signature using constant-time comparison.
- Acknowledges receipt with
200 OKimmediately. - Forwards the event payload to your CRM asynchronously.
import hmac, hashlib
def handle_webhook(request):
signature = request.headers.get("X-Mailtarget-Signature")
body_bytes = request.body
expected = hmac.new(SECRET.encode(), body_bytes, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
return Response(status=401)
# Acknowledge fast
enqueue_for_crm_sync(request.json)
return Response(status=200)
The enqueue_for_crm_sync handler picks up the event from a queue and writes to the CRM. This decouples webhook acknowledgement from CRM API latency and rate limits.
Step 4: Map Mailtarget events to CRM activity
| Mailtarget event | CRM activity |
|---|---|
delivery | Set "email delivered" timestamp on the contact |
open | Log "email opened" activity. Increment open count |
click | Log "email clicked" activity with the URL |
bounce | Mark email as undeliverable. Trigger re-validation flow |
complaint | Mark contact as do-not-contact. Notify owner |
unsubscribe | Set "marketing opt-out" on the contact. Trigger compliance log |
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Webhook handler timing out | Synchronous CRM API call inside the handler | Acknowledge fast, forward async |
| Duplicate CRM activity entries | Mailtarget retried the webhook before CRM idempotency caught up | Dedupe on transmissionId + event + timestamp |
| CRM rate limited | Burst of events on campaign launch | Queue and drain at the CRM rate limit |
| Signature verification fails intermittently | Wrong header read or stripped by reverse proxy | Log raw header for diagnosis. Some proxies lowercase header names |
Outcome to track
- Webhook acknowledgement latency under 200 ms p95. Above this, retry storms during campaign launches.
- CRM sync latency under 30 seconds p95 for non-burst traffic.
- Event drop rate zero. If events are missing, audit the queue and CRM error log.
- CRM data freshness match the Mailtarget delivery log within 1 minute for the most recent campaign.
Related
- Webhooks for the event catalog and signature verification.
- Transmission API for
metadatafield semantics. - Webhook Reliability for production retry budgets.