
Sync Open House Leads from SignSnapHome to HubSpot with Automated Email Follow-up
説明
Categories
🤖 AI & Machine Learning
Nodes Used
n8n-nodes-base.ifn8n-nodes-base.setn8n-nodes-base.coden8n-nodes-base.hubspotn8n-nodes-base.webhookn8n-nodes-base.emailSendn8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
Price無料
Views0
最終更新11/28/2025
workflow.json
{
"meta": {
"instanceId": "105694f414213a0eca348284005921253960bd1b0223294a4970522d0da53055",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "8451445c-cf7f-43b3-b8e5-6fb377befcab",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-560,
-576
],
"parameters": {
"color": 4,
"width": 346,
"height": 472,
"content": "## 📋 SETUP INSTRUCTIONS\n\n**Welcome to SignSnap Home → HubSpot Integration!**\n\n### Quick Setup:\n1. Configure HubSpot OAuth2 credentials in n8n\n2. Configure SMTP credentials for email (optional)\n3. Update the \"from\" email address in Send Email node\n4. Activate this workflow\n5. Copy the webhook URL\n6. Go to **SignSnapHome.com** → Settings → Integerations\n7. Paste webhook URL and enable \"Send on each submission\"\n\n✅ Done! Open house leads will auto-sync to HubSpot!"
},
"typeVersion": 1
},
{
"id": "74585b1c-f23b-4001-b81e-a38291312481",
"name": "Webhook: SignSnap Home",
"type": "n8n-nodes-base.webhook",
"position": [
-144,
-224
],
"webhookId": "84838b43-c8d0-4eb8-a602-443fcc8a20fc",
"parameters": {
"path": "signsnap-hubspot",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "a3562394-ff96-408f-8e5f-2cfaa5e7dd08",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-192,
-656
],
"parameters": {
"color": 4,
"width": 289,
"height": 380,
"content": "## 🎯 WEBHOOK RECEIVES DATA\n\n**This webhook receives POST data from SignSnap Home**\n\nURL Format:\n`https://your-n8n.com/webhook/signsnap-hubspot`\n\nAdd this exact URL to your SignSnapHome.com automation settings and turn on auto-send.\n\n⚡ Triggers on every open house sign-in!"
},
"typeVersion": 1
},
{
"id": "7d256ab8-0b49-4638-b3a3-736fdb921c47",
"name": "Parse SignSnap Data",
"type": "n8n-nodes-base.code",
"position": [
80,
-224
],
"parameters": {
"jsCode": "// Extract and process SignSnap Home data for HubSpot\nconst items = $input.all();\nconst guestData = items[0].json.body;\n\n// Extract core contact information\nconst email = guestData.email || null;\nconst firstName = guestData.first_name || '';\nconst lastName = guestData.last_name || '';\nconst phone = guestData.phone_number || null;\n\n// Extract open house details\nconst propertyAddress = guestData.openHouseTitle || '';\nconst visitDate = guestData.submissionTimestamp || new Date().toISOString();\nconst hasAgent = guestData.are_you_currently_working_with_an_agent || 'Not specified';\n\n// Optional fields (may not exist in all forms)\nconst rating = guestData.what_did_you_rate_the_house || null;\nconst buyerAgreement = guestData.do_you_have_a_signed_buyer_agreement || null;\n\n// Separate standard fields from custom fields\nconst standardFields = [\n 'openHouseTitle', 'openHouseType', 'submissionTimestamp',\n 'guestPhotoUrl', 'first_name', 'last_name', 'phone_number',\n 'email', 'are_you_currently_working_with_an_agent',\n 'what_did_you_rate_the_house', 'do_you_have_a_signed_buyer_agreement',\n 'webhookUrl', 'executionMode'\n];\n\nconst customFields = {};\nfor (const [key, value] of Object.entries(guestData)) {\n if (!standardFields.includes(key) && value !== null && value !== undefined && value !== '') {\n customFields[key] = value;\n }\n}\n\n// Build custom fields text for notes\nconst customFieldsText = Object.entries(customFields)\n .map(([key, value]) => {\n const formattedKey = key.replace(/_/g, ' ')\n .split(' ')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n return `${formattedKey}: ${value}`;\n })\n .join('\\n');\n\n// Calculate lead score (0-100)\nlet leadScore = 50; // Base score\n\nif (hasAgent === 'No' || hasAgent === 'no') {\n leadScore += 30; // Hot lead - no agent\n}\n\nif (rating) {\n const ratingNum = parseInt(rating);\n if (ratingNum >= 4) leadScore += 20; // High rating\n else if (ratingNum <= 2) leadScore -= 20; // Low rating\n}\n\nif (buyerAgreement === 'No' || buyerAgreement === 'no') {\n leadScore += 10; // No agreement = more available\n}\n\nleadScore = Math.max(0, Math.min(100, leadScore)); // Clamp 0-100\n\n// Determine lead status\nlet leadStatus = 'OPEN';\nif (leadScore >= 70) leadStatus = 'HOT';\nelse if (leadScore >= 50) leadStatus = 'WARM';\nelse if (leadScore < 40) leadStatus = 'COLD';\n\n// Build comprehensive notes for HubSpot\nconst notes = `🏠 Open House Visit\\n\\nProperty: ${propertyAddress}\\nVisit Date: ${new Date(visitDate).toLocaleString('en-US', { dateStyle: 'full', timeStyle: 'short' })}\\nHas Agent: ${hasAgent}${rating ? `\\nProperty Rating: ${rating}/5` : ''}${buyerAgreement ? `\\nBuyer Agreement: ${buyerAgreement}` : ''}\\n\\nLead Score: ${leadScore}/100\\nLead Status: ${leadStatus}${customFieldsText ? `\\n\\n--- Additional Information ---\\n${customFieldsText}` : ''}\\n\\n📍 Source: SignSnap Home Open House Sign-In`;\n\nreturn [{\n json: {\n // HubSpot contact fields\n email: email,\n firstname: firstName,\n lastname: lastName,\n phone: phone,\n \n // Property & visit details\n propertyAddress: propertyAddress,\n visitDate: visitDate,\n hasAgent: hasAgent,\n rating: rating,\n \n // Scoring\n leadScore: leadScore,\n leadStatus: leadStatus,\n \n // Notes to add to contact\n notes: notes,\n \n // Lifecycle stage\n lifecyclestage: 'lead',\n \n // Original data for reference\n _raw: guestData\n }\n}];"
},
"typeVersion": 2
},
{
"id": "bae80e9f-b4fe-4c0e-a945-a1d2b5937e8e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
144,
-672
],
"parameters": {
"color": 4,
"width": 303,
"height": 373,
"content": "## ⚙️ DATA PROCESSING\n\n**Extracts & enriches all data:**\n\n✅ Contact info (name, email, phone)\n✅ Property & visit details\n✅ Custom form fields (automatic!)\n✅ Lead score calculation (0-100)\n✅ Lead status (HOT/WARM/COLD)\n\n**Lead Scoring:**\n- Base: 50 points\n- No agent: +30\n- Rating 4-5: +20\n- Rating 1-2: -20\n- No buyer agreement: +10"
},
"typeVersion": 1
},
{
"id": "9f28800b-f6fd-4ca8-b41f-43dcc7fde6f9",
"name": "Has Email?",
"type": "n8n-nodes-base.if",
"position": [
304,
-224
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "email-check",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1c5ca9b2-cba1-4709-a02c-9df049310f4d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
-656
],
"parameters": {
"color": 4,
"width": 262,
"height": 248,
"content": "## ✉️ EMAIL REQUIRED\n\n**HubSpot requires email to create/update contacts**\n\nIf no email:\n→ Lead logged to error output\n→ Manual follow-up needed\n\n💡 **TIP:** Make email required in SignSnap form for 100% sync rate"
},
"typeVersion": 1
},
{
"id": "fdebbdbb-0116-4f6a-92ea-3fdef2fbcded",
"name": "Create/Update HubSpot Contact",
"type": "n8n-nodes-base.hubspot",
"position": [
528,
-352
],
"parameters": {
"email": "={{ $json.email }}",
"options": {},
"authentication": "appToken",
"additionalFields": {
"lastName": "={{ $json.lastname }}",
"firstName": "={{ $json.firstname }}",
"phoneNumber": "={{ $('Parse SignSnap Data').item.json._raw.phone_number }}",
"membershipNote": "={{ $('Parse SignSnap Data').item.json.notes }}"
}
},
"credentials": {
"hubspotAppToken": {
"id": "XUCfDvhuGiD9t0za",
"name": "HubSpot account"
}
},
"typeVersion": 2.2
},
{
"id": "fbc3e0a7-97d3-4822-b57a-6c8f8b279eba",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
-496
],
"parameters": {
"color": 5,
"width": 262,
"height": 300,
"content": "## 🎯 HUBSPOT\n\nIf contact exists (by email):\n→ Updates information\n→ Adds new visit to timeline\n→ Updates lead score\n\nIf contact is new:\n→ Creates new contact\n→ Sets all properties\n→ Marks as 'Lead'\n\n✨ Prevents duplicates!"
},
"typeVersion": 1
},
{
"id": "25b03343-3dfe-46ab-8860-b36dea6fbebf",
"name": "Send Thank You Email",
"type": "n8n-nodes-base.emailSend",
"position": [
528,
-160
],
"webhookId": "de450abb-d8a5-42f3-937e-ded6115ec33f",
"parameters": {
"html": "=Hi {{ $('Parse SignSnap Data').item.json.firstname }}!\n\nThank you for visiting {{ $('Parse SignSnap Data').item.json.propertyAddress }} today.\n\n{{ $('Parse SignSnap Data').item.json.hasAgent === 'No' ? \"Our team would love to help you on your home buying journey! We specialize in this area and can provide exclusive listings and personalized service. We're here to make finding your dream home easy and stress-free.\\n\\n\" : \"\" }}If you have any questions about this property or would like to schedule another viewing, please don't hesitate to reply to this email.\n\nBest regards,\nYour Real Estate Team",
"options": {},
"subject": "=Thank You for Visiting {{ $('Parse SignSnap Data').item.json.propertyAddress }}!",
"toEmail": "={{ $('Parse SignSnap Data').item.json.email }}",
"fromEmail": "[email protected]"
},
"typeVersion": 2.1
},
{
"id": "b714c9f3-c953-4ecb-9456-3f2e346b31ef",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
208,
-48
],
"parameters": {
"color": 5,
"width": 262,
"height": 268,
"content": "## 📧 AUTO-FOLLOW UP\n\n**Sends personalized thank you email**\n\nDifferent messages:\n- **No Agent:** Offers consultation\n- **Has Agent:** Friendly follow-up\n\n🔧 **Setup:**\n1. Configure SMTP credentials\n2. Update FROM email address\n3. Customize footer"
},
"typeVersion": 1
},
{
"id": "61c0140b-7043-4f12-9498-6bf3d850c37b",
"name": "Log Missing Email",
"type": "n8n-nodes-base.set",
"position": [
528,
16
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "error-message",
"name": "error_reason",
"type": "string",
"value": "No email address provided"
},
{
"id": "guest-name",
"name": "guest_name",
"type": "string",
"value": "={{ $json.firstname }} {{ $json.lastname }}"
},
{
"id": "property",
"name": "property",
"type": "string",
"value": "={{ $json.propertyAddress }}"
},
{
"id": "phone",
"name": "phone",
"type": "string",
"value": "={{ $json.phone }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "098055b4-f2e3-4376-ad9d-cc7f2ab1ff26",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
512,
176
],
"parameters": {
"color": 6,
"width": 262,
"height": 231,
"content": "## ⚠️ NO EMAIL HANDLING\n\n**Guest didn't provide email**\n\nOptions:\n→ Connect to Google Sheets\n→ Send alert to team\n→ Manual follow-up via phone\n\n💡 Make email required in SignSnap to prevent this!"
},
"typeVersion": 1
},
{
"id": "4c31c975-05e6-4bed-8e9f-96d5e8c426c9",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-112
],
"parameters": {
"color": 3,
"width": 361,
"height": 670,
"content": "## 📊 CUSTOM HUBSPOT PROPERTIES (OPTIONAL)\n\n**Create these in HubSpot for enhanced tracking:**\n\nGo to: **Settings → Properties → Create Property**\n\n**Recommended Custom Properties:**\n\n1. `last_open_house_property` (Text)\n - Label: Last Open House Property\n\n2. `last_open_house_date` (Date)\n - Label: Last Open House Visit\n\n3. `has_real_estate_agent` (Dropdown)\n - Options: Yes, No, Not specified\n\n4. `property_interest_rating` (Number)\n - Label: Property Rating (1-5)\n\n5. `lead_score` (Number)\n - Label: Lead Score\n\n6. `lead_status` (Dropdown)\n - Options: HOT, WARM, COLD, OPEN\n\n**OR** just use standard fields + notes!\nThe workflow works either way."
},
"typeVersion": 1
},
{
"id": "3d3a1a95-f7ba-4e1d-9304-524604993896",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-544,
-16
],
"parameters": {
"color": 7,
"width": 349,
"height": 734,
"content": "## 💡 PRO TIPS & ENHANCEMENTS\n\n**Optimization Ideas:**\n\n**1. Auto-Assign to Agent**\n- Match property to agent territory\n- Auto-assign contact owner in HubSpot\n\n**2. Create Deals Automatically**\n- Create deal for HOT leads (score ≥70)\n- Link to property and contact\n- Set deal stage based on score\n\n**3. Add to Lists**\n- Create HubSpot list per property\n- Auto-segment by lead status\n- Use for targeted campaigns\n\n**4. Trigger HubSpot Workflows**\n- Send automated nurture sequence\n- Schedule follow-up tasks\n- Assign to sales rep\n\n**5. Add Photo Attachment**\n- Upload guest photo to HubSpot Files\n- Attach to contact record\n- Requires additional node\n\n**6. SMS Follow-up**\n- Add Twilio node for instant SMS\n- Parallel to email\n- Higher engagement rate"
},
"typeVersion": 1
},
{
"id": "2b6fca52-ae4b-4788-8283-4997cd4d2757",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-160,
-16
],
"parameters": {
"color": 6,
"width": 333,
"height": 702,
"content": "## 🔧 TROUBLESHOOTING\n\n**Common Issues:**\n\n🔴 **\"Invalid email\"**\n→ Check email format in SignSnap\n→ Ensure validation is enabled\n\n🔴 **\"Property doesn't exist\"**\n→ Create custom property in HubSpot\n→ Or remove from node config\n\n🔴 **\"Authentication failed\"**\n→ Reconnect HubSpot OAuth2\n→ Check token expiration\n\n🔴 **\"Contact not in HubSpot\"**\n→ Check execution history\n→ Verify email was provided\n→ Search \"All contacts\" view\n\n🔴 **\"Duplicate contacts\"**\n→ HubSpot auto-matches by email\n→ Check for typos in emails\n\n🔴 **\"Email not sending\"**\n→ Verify SMTP credentials\n→ Check FROM email is valid\n→ Test SMTP connection\n\n**Need help?**\n→ n8n community forum\n→ HubSpot API docs\n→ SignSnap support"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"Has Email?": {
"main": [
[
{
"node": "Create/Update HubSpot Contact",
"type": "main",
"index": 0
},
{
"node": "Send Thank You Email",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Missing Email",
"type": "main",
"index": 0
}
]
]
},
"Parse SignSnap Data": {
"main": [
[
{
"node": "Has Email?",
"type": "main",
"index": 0
}
]
]
},
"Webhook: SignSnap Home": {
"main": [
[
{
"node": "Parse SignSnap Data",
"type": "main",
"index": 0
}
]
]
}
}
}