This workflow corresponds to n8n.io template #16672 — we link there as the canonical source.
This workflow follows the Agent → Gmail recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "uxoEBRsuVf5Ocqhy",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Open House Sign-In to Qualified Follow-Up",
"tags": [],
"nodes": [
{
"id": "a9efc993-07d1-448c-9ee4-6085efd4c856",
"name": "Google Sheets Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
-736,
-16
],
"parameters": {
"event": "rowAdded",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": ""
},
"documentId": {
"__rl": true,
"mode": "url",
"value": ""
}
},
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "fa8ef370-96a0-4875-bb5d-87f3a0c6b2f2",
"name": "Extract Visitor Details",
"type": "n8n-nodes-base.set",
"position": [
-528,
-16
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "03e714c5-db7e-4d40-958e-636df02ff02f",
"name": "visitorName",
"type": "string",
"value": "={{ $json['Full Name'] }}"
},
{
"id": "46463909-61ce-4352-80a7-f8f753e9d969",
"name": "visitorEmail",
"type": "string",
"value": "={{ $json['Email Address'] }}"
},
{
"id": "a1de33b6-58b7-4c25-9c6d-1f1a5239debe",
"name": "visitorPhone",
"type": "string",
"value": "={{ $json['Phone Number'] }}"
},
{
"id": "072db1a0-5a08-48f7-b9b8-17ce855f9b6f",
"name": "propertyAddress",
"type": "string",
"value": "={{ $json['Which property are you interested in?'] }}"
},
{
"id": "bd4a94f6-54ca-4296-9e11-bff67d994071",
"name": "budget",
"type": "string",
"value": "={{ $json['What is your budget range?'] }}"
},
{
"id": "c845b0a0-f442-40fc-b2a3-a2f4b4206ad6",
"name": "timeline",
"type": "string",
"value": "={{ $json['What is your buying timeline?'] }}"
},
{
"id": "c8bd4a83-48dd-4b24-bbc4-dd0c34e40e0d",
"name": "buyingIntent",
"type": "string",
"value": "={{ $json['How would you describe your buying intent?'] }}"
},
{
"id": "1e093ffa-0e7a-40d2-a500-e10e39412320",
"name": "submittedAt",
"type": "string",
"value": "={{ $json.Timestamp }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "d18d659a-ec00-4579-8100-bc071f6f4736",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
-224,
256
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "7bee3e92-33c0-40d0-ba73-9cd0bcdd329b",
"name": "Qualify & Draft Follow-Up",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-320,
-16
],
"parameters": {
"text": "=Visitor name: {{ $json.visitorName }}\nProperty they visited: {{ $json.propertyAddress }}\nBudget: {{ $json.budget }}\nBuying timeline: {{ $json.timeline }}\nBuying intent: {{ $json.buyingIntent }}",
"options": {
"systemMessage": "You are a real estate lead qualification and follow-up assistant.\n\nDo two things in one response:\n1. Score this open house visitor as Hot, Warm, or Cold based on their \n budget, timeline, and buying intent.\n2. Write a short, warm follow-up email tailored to their score:\n Hot = enthusiastic, action-oriented, suggest a private viewing\n Warm = friendly, informative, share more about the property\n Cold = light-touch, no pressure, leave the door open\n\nFormat the email_body as two parts separated by a literal \\n\\n:\n Part 1: greeting line only e.g. \"Hi {name},\"\n Part 2: message body as a single paragraph\n\nOutput ONLY valid JSON with no preamble or markdown backticks:\n{\n \"score\": \"Hot | Warm | Cold\",\n \"reasoning\": \"one sentence explanation\",\n \"email_subject\": \"short subject line\",\n \"email_body\": \"Hi {name},\\n\\nMessage body here.\"\n}"
},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "1bde0413-ebff-4fd2-a139-b6ec37f06307",
"name": "Parse AI Output",
"type": "n8n-nodes-base.code",
"position": [
32,
-16
],
"parameters": {
"jsCode": "const raw = $input.first().json.output;\nlet parsed;\n\ntry {\n parsed = JSON.parse(raw);\n} catch (e) {\n parsed = {\n score: \"Warm\",\n reasoning: \"AI parsing failed \u2014 manual review recommended.\",\n email_subject: \"Thanks for visiting the open house!\",\n email_body: `Hi ${$('Extract Visitor Details').first().json.visitorName},\\n\\nThank you for visiting the open house today. We would love to help you find the right property \u2014 please feel free to reach out at any time.`\n };\n}\n\nconst visitorData = $('Extract Visitor Details').first().json;\n\nfunction escapeHtml(text) {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction formatEmailHtml(text) {\n const paragraphs = text\n .split(/\\n\\s*\\n/)\n .map(p => p.replace(/\\s+/g, ' ').trim())\n .filter(Boolean);\n return paragraphs.map(p => `<p>${escapeHtml(p)}</p>`).join('');\n}\n\nreturn [{\n json: {\n ...visitorData,\n score: parsed.score,\n reasoning: parsed.reasoning,\n email_subject: parsed.email_subject,\n email_body: formatEmailHtml(parsed.email_body),\n recordId: `${visitorData.visitorEmail}-${Date.now()}`\n }\n}];"
},
"typeVersion": 2
},
{
"id": "b3500855-73f8-4623-9009-de7e195a1eee",
"name": "Send Visitor Follow-Up Email",
"type": "n8n-nodes-base.gmail",
"position": [
240,
-16
],
"parameters": {
"sendTo": "={{ $json.visitorEmail }}",
"message": "={{ $json.email_body }}",
"options": {
"appendAttribution": false
},
"subject": "={{ $json.email_subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "88658316-3d7f-4462-8b13-ff3860a04bf4",
"name": "Log to Open House Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
448,
-16
],
"parameters": {
"columns": {
"value": {
"Email": "={{ $('Parse AI Output').item.json.visitorEmail }}",
"Phone": "={{ $('Parse AI Output').item.json.visitorPhone }}",
"Budget": "={{ $('Parse AI Output').item.json.budget }}",
"Timeline": "={{ $('Parse AI Output').item.json.timeline }}",
"recordId": "={{ $('Parse AI Output').item.json.recordId }}",
"Timestamp": "={{ $('Parse AI Output').item.json.submittedAt }}",
"Lead Score": "={{ $('Parse AI Output').item.json.score }}",
"Visitor Name": "={{ $('Parse AI Output').item.json.visitorName }}",
"Buying Intent": "={{ $('Parse AI Output').item.json.buyingIntent }}",
"Email Subject": "={{ $('Parse AI Output').item.json.email_subject }}",
"Agent Notified": "false",
"Score Reasoning": "={{ $('Parse AI Output').item.json.reasoning }}",
"Property Address": "={{ $('Parse AI Output').item.json.propertyAddress }}"
},
"schema": [
{
"id": "recordId",
"type": "string",
"display": true,
"required": false,
"displayName": "recordId",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Visitor Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Visitor Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Property Address",
"type": "string",
"display": true,
"required": false,
"displayName": "Property Address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Budget",
"type": "string",
"display": true,
"required": false,
"displayName": "Budget",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Timeline",
"type": "string",
"display": true,
"required": false,
"displayName": "Timeline",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Buying Intent",
"type": "string",
"display": true,
"required": false,
"displayName": "Buying Intent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Score",
"type": "string",
"display": true,
"required": false,
"displayName": "Lead Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Score Reasoning",
"type": "string",
"display": true,
"required": false,
"displayName": "Score Reasoning",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Subject",
"type": "string",
"display": true,
"required": false,
"displayName": "Email Subject",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Agent Notified",
"type": "string",
"display": true,
"required": false,
"displayName": "Agent Notified",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kbvVHhCrG5My6Z4WOLW4ETgNIC6fKZWtHZszKg9DDQc/edit#gid=0",
"cachedResultName": "Leads"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": ""
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "bb3e2488-c46c-4bd5-a911-11e018da1ddc",
"name": "Is Lead Hot?",
"type": "n8n-nodes-base.if",
"position": [
656,
-16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f4dd0a51-14d3-49e3-b88f-93cc61c34fdb",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json['Lead Score'] }}",
"rightValue": "Hot"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "7085c4fb-04dd-4702-81da-a3579cbe5146",
"name": "Notify Agent \u2014 Hot Lead",
"type": "n8n-nodes-base.gmail",
"position": [
944,
-224
],
"parameters": {
"sendTo": "=youremail@gmail.com",
"message": "=<p><strong>New Hot Lead from Open House</strong></p> <p><strong>Name:</strong> {{ $json['Visitor Name'] }} <br> <strong>Email:</strong> {{ $json.Email }} <br> <strong>Phone:</strong> {{ $json.Phone }} <br> <strong>Property:</strong> {{ $json['Property Address'] }} <br> <strong>Budget:</strong> {{ $json.Budget }}<br> <strong>Timeline:</strong> {{ $json.Timeline }} <br> <strong>Intent:</strong> {{ $json['Buying Intent'] }} </p> <p><strong>AI Score:</strong> {{ $json['Lead Score'] }} <br> <strong>Reasoning:</strong> {{ $json['Score Reasoning'] }}</p>",
"options": {
"appendAttribution": false
},
"subject": "=\ud83d\udd25 Hot Lead at {{ $json['Property Address'] }} \u2014 {{ $json['Visitor Name'] }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "a05c5102-b757-4c83-8f81-78f804d06e60",
"name": "Notify Agent via Slack",
"type": "n8n-nodes-base.slack",
"position": [
960,
240
],
"parameters": {
"text": "=\ud83d\udd25 *Hot Lead \u2014 {{ $json['Property Address'] }} * *Name:* {{ $json['Visitor Name'] }} *Email:* {{ $json.Email }} *Budget:* {{ $json.Budget }} | *Timeline:* {{ $json.Timeline }} *AI Reasoning:* {{ $json['Score Reasoning'] }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "name",
"value": "#hot-leads"
},
"otherOptions": {}
},
"typeVersion": 2.4
},
{
"id": "1e0758c1-5350-4dc5-a292-6b3b28154640",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1456,
-336
],
"parameters": {
"width": 544,
"height": 752,
"content": "## Open House Sign-In to Qualified Follow-Up\n\nWhen a visitor signs in at your open house, this workflow automatically \nqualifies their buying intent, sends them a personalized follow-up email, \nand alerts you immediately if they're a hot lead \u2014 so no opportunity slips \nthrough after a busy open house day.\n\n### How it works\nA Google Form captures visitor details at sign-in. AI (Gemini) scores each \nvisitor as **Hot**, **Warm**, or **Cold** based on their budget, timeline, \nand buying intent \u2014 and drafts a tailored follow-up email in the same step. \nThe email sends immediately via Gmail. Every visitor is logged to Google \nSheets with their score and message. If a lead scores Hot, the agent receives \nan instant notification email so they can prioritize personal outreach.\n\n### Setup\n1. Connect **Google Sheets**, **Gmail**, and **Gemini API** credentials.\n2. Copy the *Open House Sign-In Log* sheet template and link it to the \n Sheets node.\n3. Set up your **Google Form** with the required sign-in fields (name, \n email, phone, property, budget, timeline, intent) and link it to a \n Google Sheet response tab.\n4. Point the trigger to the form's linked response sheet.\n5. Update the agent notification email address in the \n \"Notify Agent \u2014 Hot Lead\" node.\n6. **Slack is optional** \u2014 add your Slack credential to the Slack node \n if you want a second notification channel for hot leads. \n Disable it if not needed.\n\n### Customization\n- Edit the AI prompt to adjust scoring criteria or tone.\n- Add Warm lead agent notifications by duplicating the Hot lead branch.\n- Extend the form with additional qualification questions."
},
"typeVersion": 1
},
{
"id": "fa7addd7-e420-4874-9b45-37a7fe4df7c5",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-864,
-208
],
"parameters": {
"color": "#FCFCFC",
"width": 272,
"height": 416,
"content": "## New Open House Sign-In\nWatches the Google Form response sheet for new submissions.\nFires once per visitor sign-in during or after the open house."
},
"typeVersion": 1
},
{
"id": "dd3bd926-9176-4ea5-abe9-0824a92a5afe",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-336,
-336
],
"parameters": {
"color": "#FCFCFC",
"width": 528,
"height": 752,
"content": "## Qualify & Draft Follow-Up\nOne Gemini AI call scores the lead (Hot / Warm / Cold) and drafts a personalized follow-up email in a single step.\nA second node parses and formats the AI output for use downstream."
},
"typeVersion": 1
},
{
"id": "64f51780-4243-46ed-8579-842131d6e02d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
208,
-336
],
"parameters": {
"color": "#FCFCFC",
"width": 928,
"height": 752,
"content": "## Email, Log & Agent Alert\nSends the personalized follow-up to the visitor, logs every sign-in to Google Sheets, \nand notifies the agent instantly for Hot leads only. Slack alert is optional alongside \nthe email notification."
},
"typeVersion": 1
},
{
"id": "3a7e5a6f-04cd-4e2d-97ae-fe825b702503",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-576,
-208
],
"parameters": {
"color": "#FCFCFC",
"width": 224,
"height": 416,
"content": "## Extract Visitor Details\nMaps raw form field names to clean, readable variable names\nused by all downstream nodes."
},
"typeVersion": 1
},
{
"id": "efaefa0a-1832-4386-8d6b-f021968a952a",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-336
],
"parameters": {
"color": 3,
"width": 560,
"height": 336,
"content": "## Update Agent Email Address\nReplace the placeholder email in this node with the agent's real email address before going live. Notifications will fail silently if this is left as the default."
},
"typeVersion": 1
},
{
"id": "4d051f0e-c15f-41eb-b7ee-19d9b8677607",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
16
],
"parameters": {
"color": 3,
"width": 560,
"height": 400,
"content": "## Slack is Optional\nThis node only runs if you add your Slack OAuth2 credential.\nTo use:\n- Set the correct channel name (e.g. #hot-leads)\n- Make sure your Slack app has permission to post to that channel\nIf you don't need Slack, leave this node disconnected \u2014 the email notification will still fire for Hot leads."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "dc75884d-9604-4d48-aa48-1db63ae27bcc",
"connections": {
"Is Lead Hot?": {
"main": [
[
{
"node": "Notify Agent via Slack",
"type": "main",
"index": 0
},
{
"node": "Notify Agent \u2014 Hot Lead",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Output": {
"main": [
[
{
"node": "Send Visitor Follow-Up Email",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets Trigger": {
"main": [
[
{
"node": "Extract Visitor Details",
"type": "main",
"index": 0
}
]
]
},
"Notify Agent via Slack": {
"main": [
[]
]
},
"Extract Visitor Details": {
"main": [
[
{
"node": "Qualify & Draft Follow-Up",
"type": "main",
"index": 0
}
]
]
},
"Log to Open House Sheet": {
"main": [
[
{
"node": "Is Lead Hot?",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Qualify & Draft Follow-Up",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Qualify & Draft Follow-Up": {
"main": [
[
{
"node": "Parse AI Output",
"type": "main",
"index": 0
}
]
]
},
"Send Visitor Follow-Up Email": {
"main": [
[
{
"node": "Log to Open House Sheet",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googlePalmApigoogleSheetsOAuth2ApigoogleSheetsTriggerOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
When a visitor signs in at your open house, this workflow instantly scores their buying intent using Gemini AI, sends a personalized follow-up email via Gmail, logs every visitor to Google Sheets, and alerts the agent for hot leads only. A visitor signs in via your Google Form…
Source: https://n8n.io/workflows/16672/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automatically monitors a Google Sheet for failed trades, analyzes each failure using AI and updates the sheet with a probable root cause, confidence level and actionable next steps. It a
This n8n workflow automates the transition from raw financial trade data to professional client communication. It monitors a Google Sheet for portfolio changes, uses Gemini AI to draft a personalized,
Youtube Video: https://youtu.be/42-oHh9w9Eo This workflow listens for Slack @mentions, uses Google Gemini to classify the request and extract invoice details, then reads and updates Google Sheets, gen
Automate end-to-end vendor onboarding workflows with an AI-powered autonomous agent built in n8n 🤖. This workflow uses advanced MCTS (Monte Carlo Tree Search) reasoning to intelligently map procuremen
Youtube Video: https://youtu.be/ehsagyRmri4