Weekend n8n Build: Gmail to Notion CRM Auto-Logger for Inbound Leads
Build an n8n flow that catches labelled Gmail leads, parses the sender, dedupes against your Notion CRM, and writes a clean row with an owner. ~12 nodes, one weekend.
Hrishikesh Baidya
May 3, 202512 min read
0%
Inbound leads land in a shared inbox and die there. Someone means to log them in the CRM, then a fire starts and the email scrolls away. We built an n8n flow for a 14-person Pune SaaS reseller that catches any email labelled "Lead", parses the sender, checks it isn't already in Notion, and writes a clean CRM row with an assigned owner — in under 8 seconds, with zero human touch. Around 12 nodes, self-hosted on a ₹740/month Hetzner box. Here's the full build you can copy this weekend.
~12
n8n nodes in the finished flow
8 sec
Label to logged CRM row
₹740
/mo Hetzner CX22 to self-host n8n
0
Manual data entry per lead
## How do you auto-log Gmail leads into a Notion CRM?
Use an n8n Gmail Trigger watching a single label like "Lead". When an email arrives, parse the sender's name, email, and domain, then query your Notion database to check the email doesn't already exist. If it's new, create a Notion page with the lead's details and a round-robin owner; if it exists, log a note instead. The whole flow is about 12 nodes and runs in under 10 seconds per lead.
## Why this matters now (May 2026)
Shared inboxes don't scale past two salespeople. The official n8n Gmail-and-Notion integration makes this trivial to wire up, and self-hosting n8n means unlimited executions for the price of a small VPS — no per-task Zapier bill. For a small Indian sales team, the alternative is a ₹2,000+/month connector or a CRM seat for an "ops" person who copy-pastes emails. With n8n's free, self-hostable core, you own the whole pipeline. We covered the broader pattern in our roundup of the 9 n8n workflows we ran most in 2025 — this is the cleanest entry point.
The deeper reason to fix lead intake first is that it's the cheapest stage to lose money at. A lead that never gets logged costs you the entire acquisition spend that brought it in — the ad click, the SEO work, the referral — for zero return. Every other CRM improvement (better follow-up cadence, sharper qualification) only matters for leads that made it into the system. Plug the intake leak and every downstream effort gets more leads to work with. That's why we build this flow before any fancier automation: it's the foundation the rest sits on.
It also removes a quiet source of team friction. When leads live in a shared inbox, "who was supposed to call this person?" has no answer, so nobody owns the miss and everybody feels vaguely guilty. Round-robin assignment at the moment of capture turns a fuzzy collective duty into a named individual task. The CRM stops being a graveyard people distrust and becomes the one place a rep checks first thing in the morning.
## What you'll need before you start
Gather these first. The whole build assumes self-hosted n8n, but n8n Cloud works identically for the node logic.
🖥️
n8n v1.6x, self-hosted
A ₹740/month Hetzner CX22 (2 vCPU, 4 GB) running n8n via Docker handles thousands of executions a month. n8n Cloud Starter also works.
📧
Gmail OAuth2 credential
Create an OAuth2 client in Google Cloud Console, enable the Gmail API, and connect it in n8n. You'll need the label ID for "Lead".
🗂️
A Notion CRM database
Columns: Name, Email, Company, Source, Owner, Status, Date. Create a Notion internal integration token and share the database with it.
🏷️
A Gmail label + filter
Make a "Lead" label. Optionally auto-apply it with a Gmail filter (e.g. emails to sales@ or matching a contact-form sender). Manual labelling works too.
Notion auth gotcha: The n8n Notion node uses an internal integration token, not OAuth. Create the integration at notion.so/my-integrations, copy the secret, then open your database, click the three-dot menu, and add the connection. Skip that share step and every Notion node returns "object not found."
## The build, node by node
This is the full flow. Around 12 nodes including the branch. Each step has a verification so you can test as you go rather than debugging the whole chain at the end.
1
Gmail Trigger — watch the "Lead" label
Add a Gmail Trigger node, event "Message Received", and set the label filter to your "Lead" label ID. Poll every 1 minute. Verification: label a test email, wait a minute, and confirm the trigger fires with the email JSON in the output.
2
Set node — extract clean fields
Map the raw email into tidy variables: sender name, sender email, subject, and a snippet. Use expressions like {{ $json.from.value[0].address }} for the email and {{ $json.from.value[0].name }} for the name. Verification: the Set node outputs four clean fields, no nested junk.
3
Code node — derive company from domain
A tiny JS node that splits the email domain, drops free providers (gmail, outlook, yahoo), and title-cases the rest into a company guess. Free-mail senders get "Individual". Verification: feed it ravi@acmecorp.com and check it returns "Acmecorp"; feed it a gmail address and check it returns "Individual".
4
Notion node — query database for the email
Add a Notion node, operation "Get Many" (database query), with a filter where the Email property equals the parsed sender email. This is your dedupe check. Verification: run it against an email you know exists in Notion and confirm it returns one row; run an unknown email and confirm zero rows.
5
IF node — new lead or existing?
Branch on whether the previous node returned any items. {{ $json.length }} equals 0 means new lead (true branch); anything else means existing (false branch). Verification: both branches light up correctly when you test with a known vs unknown sender.
A Notion "Create a Database Page" node mapping Name, Email, Company, Source ("Inbound Email"), Status ("New"), and Date. For Owner, use a small Code or Set node doing round-robin across your reps (modulo on a counter). Verification: a brand-new lead creates exactly one Notion row with an assigned owner.
7
False branch: append a note, don't duplicate
For an existing lead, append a Notion block to the existing page ("Replied again on {{date}}") instead of creating a duplicate row. Verification: emailing twice from the same address creates one row plus one appended note, not two rows.
8
Slack/Gmail node — alert the owner
On the new-lead branch, post a Slack message (or send an email) to the assigned owner: "New lead: {{name}} from {{company}} — logged in CRM." Verification: the right rep gets pinged within seconds of the email being labelled.
9
Gmail node — remove the "Lead" label
Optionally remove the "Lead" label and apply a "Logged" label so the same email never re-triggers. Verification: a processed email loses "Lead", gains "Logged", and does not fire the trigger again on the next poll.
If you'd rather we just build this for you, we ship it as a fixed-scope 7-day engagement. You hand over Gmail and Notion access; we hand back a tested, documented flow on your own infra.
## The 4 mistakes that break this flow
We've debugged each of these in production. They all look like "n8n is broken" and are all configuration.
1. No dedupe = a duplicate row every reply. Skip the Notion query + IF branch and every follow-up email from a lead creates a fresh CRM row. Within a week your sales team distrusts the CRM. The dedupe check (steps 4–5) is not optional. 2. Polling too aggressively. A 1-second Gmail poll burns API quota and risks rate limits; 1 minute is plenty for leads. 3. Forgetting to share the database with the Notion integration. The token alone isn't enough — the integration must be connected to that specific database. 4. Free-mail companies. Without the domain filter (step 3), every Gmail lead logs "Gmail" as the company. Strip free providers explicitly.
## Self-hosted vs Cloud: what running this actually costs
Three honest options, with real monthly numbers for a small team processing a few thousand leads a month.
## Real example: where this saved a real team
The 14-person Pune SaaS reseller was logging maybe 60% of inbound leads — the rest scrolled away in a shared inbox. After this flow went live, logging hit 100% and first-response time dropped from "whenever someone notices" to under 10 minutes, because the owner gets pinged instantly. As Hrishikesh, our CTO, frames it: the value isn't the automation, it's that a lead can no longer fall through a crack.
The number that convinced their founder wasn't response time — it was that the team finally trusted the CRM. Before the flow, reps kept a private list of "real" leads in their own notes because the shared system was unreliable, which meant management had no honest pipeline view. Once every lead landed automatically with an owner attached, the side-lists disappeared and the CRM became the single source of truth. That second-order effect — accurate forecasting — turned out to matter more to the founder than the leads the bot caught directly. We've run the same dedupe-and-route pattern at larger scale building Radiant Finance's lead pipeline, where missing a single inbound enquiry had a real rupee cost. If you'd rather start with sales-call prep instead of intake, our n8n + HubSpot auto-brief workflow pairs naturally with this one. The whole thing is what our AI and automation team ships as a starter engagement.
Weekend build checklist
n8n running (self-hosted Hetzner or Cloud)
Gmail OAuth2 credential connected + "Lead" label ID copied
Notion CRM database built + integration token shared to it
Gmail Trigger fires on the label
Sender parsed into clean Name/Email/Company fields
Notion query + IF branch dedupes correctly
New leads create one row with a round-robin owner
Owner gets a Slack/email alert; label flips to "Logged"
## Frequently asked questions
### Do I need to self-host n8n for this lead-logger?
No. The node logic is identical on n8n Cloud and self-hosted. Self-hosting on a ₹740/month Hetzner box gives you unlimited executions and full data control; n8n Cloud Starter (~₹2,000/month) is faster to start if you don't want to manage a server.
### How does the dedupe step actually work?
Before creating a row, an n8n Notion node queries your database filtering where the Email property equals the incoming sender. An IF node then branches: zero matches means a new lead gets created, any match means a note is appended to the existing page instead of a duplicate row.
### Can I use this with Airtable or Google Sheets instead of Notion?
Yes. Swap the Notion nodes for Airtable or Google Sheets nodes — the Gmail Trigger, parsing, dedupe-query, and IF logic stay the same. Notion is just a popular lightweight CRM for small teams; the pattern is storage-agnostic.
### Will every reply from a lead create a new entry?
Not if you include the dedupe check. The Notion query plus IF branch ensures a known email appends a note to the existing page rather than creating a second row. Skipping that branch is the most common reason teams end up with duplicate CRM entries.
### How do I assign leads to different salespeople automatically?
Use a round-robin counter: a small Code or Set node that increments a stored value and uses modulo to pick the next rep from a list. You can also branch on the parsed company domain or lead source to route enterprise leads to a senior rep.
### How long does this take to build the first time?
A weekend for someone new to n8n — most of the time goes into the Gmail and Notion credential setup, not the nodes. Once you've done it once, rebuilding a variant takes under two hours.
Want this Gmail-to-Notion lead flow built and running?
We ship a working, tested version on your own n8n instance in 7 working days, including dedupe, round-robin owner assignment, and Slack alerts. Typical project: ₹35k–₹60k. Suitable if inbound leads keep slipping through a shared inbox.