Overview
Lead capture automation is one of the highest-ROI applications of email-to-webhook processing. Many lead sources — website contact forms, ad platforms, partner referral systems — deliver new lead notifications via email. Without automation, those emails sit in a mailbox until someone manually copies the data into the CRM, introducing delay and risk of missed leads.
With JsonHook, every lead notification email is:
- Received at your JsonHook inbound address within seconds of the form submission
- Parsed into structured JSON (from, subject, body, headers)
- Delivered to your webhook handler
- Extracted and pushed to your CRM API or database
- The lead is in your CRM before the sales rep even sees the email
This pattern works for any CRM: HubSpot, Salesforce, Pipedrive, Airtable, a custom database, or all of the above simultaneously.
Prerequisites
Requirements for automated lead capture:
- A JsonHook inbound address to receive lead notification emails
- Sample lead notification emails from each source (examine them to understand the data format)
- CRM API credentials and documentation (HubSpot API key, Salesforce Connected App OAuth token, etc.)
- A webhook handler application (Express, FastAPI, Rails, etc.) or a no-code tool (Zapier, Make, n8n)
Automate Lead Capture in Your CRM
Lead email arrives. CRM record created. Sales notified. All automatically.
Get Free API KeyStep-by-Step Instructions
Build a lead capture pipeline:
- Collect sample lead emails. Gather 5-10 real lead notification emails from each source. Examine their structure to identify how to extract: name, email, phone, company, message, and any source-specific fields.
- Create a JsonHook address for lead emails, pointing at your lead capture webhook.
- Configure lead sources to send notifications to your JsonHook address (or forward existing notifications).
- Write extraction functions for each lead source format.
- Call your CRM API to create or update the contact record.
- Notify your sales team via Slack or email with the new lead details.
- Monitor extraction accuracy — log all extraction results and alert when required fields are missing.
Code Example
Lead capture handler that creates a HubSpot contact:
import express from "express";
import crypto from "crypto";
import fetch from "node-fetch";
const app = express();
app.use(express.raw({ type: "application/json" }));
function extractLeadFromEmail(email: any) {
const text = email.textBody ?? "";
const html = email.htmlBody ?? "";
// Try to extract fields from structured notification format
const emailMatch = text.match(/Email[:s]+([^s
]+@[^s
]+)/i);
const nameMatch = text.match(/Name[:s]+([^
]+)/i);
const phoneMatch = text.match(/Phone[:s]+([+ds-()]{7,20})/i);
const companyMatch = text.match(/Company[:s]+([^
]+)/i);
const msgMatch = text.match(/Message[:s]+([sS]{10,500})/i);
return {
email: emailMatch?.[1]?.trim() ?? email.from.match(/[w.+%-]+@[w.-]+/)?.[0],
name: nameMatch?.[1]?.trim() ?? null,
phone: phoneMatch?.[1]?.trim() ?? null,
company: companyMatch?.[1]?.trim() ?? null,
message: msgMatch?.[1]?.trim() ?? text.slice(0, 300),
source: email.from,
};
}
async function createHubSpotContact(lead: any) {
const res = await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HUBSPOT_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
properties: {
email: lead.email,
firstname: lead.name?.split(" ")[0] ?? "",
lastname: lead.name?.split(" ").slice(1).join(" ") ?? "",
phone: lead.phone ?? "",
company: lead.company ?? "",
message: lead.message ?? "",
hs_lead_status: "NEW",
},
}),
});
return res.json();
}
app.post("/webhooks/leads", async (req, res) => {
// ... verify HMAC ...
const { email, deliveryId } = JSON.parse(req.body.toString());
const lead = extractLeadFromEmail(email);
if (!lead.email) {
console.warn(`No email found in lead payload ${deliveryId}`);
return res.sendStatus(200);
}
const contact = await createHubSpotContact(lead);
console.log(`Created HubSpot contact: ${contact.id} for ${lead.email}`);
res.sendStatus(200);
});
app.listen(3000);Common Pitfalls
Lead capture automation pitfalls:
- Creating duplicate contacts. Check if the lead's email already exists in your CRM before creating a new record. Most CRM APIs support an upsert operation — create if not exists, update if exists — which prevents duplicates automatically.
- Not handling multiple lead source formats. If leads come from multiple forms or platforms, each may have a different email format. Write separate extraction functions per source and route based on the sender address or a custom email header.
- Missing leads due to extraction failures. If your regex fails to extract the lead's email from the notification body, the lead is lost. Log extraction failures prominently and send a fallback alert to your team with the raw email content.
- CRM API rate limits. For high-volume lead capture (hundreds per minute), CRM API rate limits can cause failures. Buffer leads in your database first, then sync to the CRM at a rate-limited pace using a queue with rate limiting configured.
- Not capturing the lead source. Store which JsonHook address / email sender the lead came from. This attribution data is valuable for measuring which lead sources are most productive.