8
n8n 中文网amn8n.com

使用SignSnapHome、Discord和Twilio自动化开放日潜在客户管理

中级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 13 个节点。主要使用 If, Code, Twilio, Webhook, EmailSend 等节点。 使用SignSnapHome、Discord和Twilio自动化开放日潜在客户管理

前置要求
  • HTTP Webhook 端点(n8n 会自动生成)
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "105694f414213a0eca348284005921253960bd1b0223294a4970522d0da53055",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "655b90b2-0e86-4bef-adfd-0a5f1525c3ee",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        0,
        0
      ],
      "webhookId": "7c58ab04-b71f-4d81-82a1-ff0b08782b54",
      "parameters": {
        "path": "signsnaphome-sign-in-trigger",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "5e350a04-18b9-4dc0-b201-c0ac2022f0e3",
      "name": "解析和丰富数据",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        0
      ],
      "parameters": {
        "jsCode": "// Extract webhook data from body\nconst items = $input.all();\nconst webhookData = items[0].json.body;\n\n// Standard fields that might exist\nconst standardFields = [\n  'openHouseTitle',\n  'openHouseType', \n  'submissionTimestamp',\n  'guestPhotoUrl',\n  'first_name',\n  'last_name',\n  'phone_number',\n  'email',\n  'are_you_currently_working_with_an_agent',\n  'what_did_you_rate_the_house',\n  'do_you_have_a_signed_buyer_agreement',\n  'webhookUrl',\n  'executionMode'\n];\n\n// Separate standard and custom fields\nconst standardData = {};\nconst customFields = {};\n\nfor (const [key, value] of Object.entries(webhookData)) {\n  if (standardFields.includes(key)) {\n    standardData[key] = value;\n  } else {\n    customFields[key] = value;\n  }\n}\n\n// Format timestamp\nconst timestamp = standardData.submissionTimestamp ? \n  new Date(standardData.submissionTimestamp).toLocaleString('en-US', {\n    dateStyle: 'full',\n    timeStyle: 'short'\n  }) : 'Not provided';\n\n// Check if rating field exists\nconst hasRating = standardData.what_did_you_rate_the_house !== undefined && \n                  standardData.what_did_you_rate_the_house !== null &&\n                  standardData.what_did_you_rate_the_house !== '';\n\nconst rating = hasRating ? parseInt(standardData.what_did_you_rate_the_house) : null;\n\n// Determine lead priority based on agent status and rating (if available)\nlet leadPriority = 'MEDIUM';\nlet embedColor = 0xFFA500; // Orange for medium\n\nconst hasAgent = standardData.are_you_currently_working_with_an_agent?.toLowerCase();\nconst hasBuyerAgreement = standardData.do_you_have_a_signed_buyer_agreement?.toLowerCase();\n\n// HOT lead: No agent and high rating (or no rating field but no agent)\nif (hasAgent === 'no' && (!hasRating || rating >= 4)) {\n  leadPriority = 'HOT';\n  embedColor = 0xFF0000; // Red for hot\n} \n// COLD lead: Has agent with agreement OR low rating\nelse if ((hasAgent === 'yes' && hasBuyerAgreement === 'yes') || (hasRating && rating <= 2)) {\n  leadPriority = 'COLD';\n  embedColor = 0x0099FF; // Blue for cold\n}\n// WARM lead: Has agent but no agreement\nelse if (hasAgent === 'yes' && hasBuyerAgreement === 'no') {\n  leadPriority = 'WARM';\n  embedColor = 0xFFA500; // Orange for warm\n}\n\n// Process base64 image\nlet imageBase64 = null;\nlet hasPhoto = false;\nlet imageMimeType = 'image/jpeg';\n\nif (standardData.guestPhotoUrl && standardData.guestPhotoUrl.startsWith('data:image')) {\n  try {\n    // Extract mime type\n    const mimeMatch = standardData.guestPhotoUrl.match(/data:(image\\/[a-zA-Z]+);base64,/);\n    if (mimeMatch) {\n      imageMimeType = mimeMatch[1];\n    }\n    \n    // Extract base64 data\n    const base64Data = standardData.guestPhotoUrl.split(',')[1];\n    imageBase64 = base64Data;\n    hasPhoto = true;\n  } catch (error) {\n    console.log('Error processing image:', error.message);\n  }\n}\n\n// Build custom fields display\nconst customFieldsArray = Object.entries(customFields)\n  .filter(([key, value]) => value !== null && value !== undefined && value !== '')\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 { name: formattedKey, value: String(value), inline: true };\n  });\n\nreturn [{\n  json: {\n    // Core guest data\n    firstName: standardData.first_name || 'Not provided',\n    lastName: standardData.last_name || 'Not provided',\n    fullName: `${standardData.first_name || ''} ${standardData.last_name || ''}`.trim() || 'Anonymous Guest',\n    email: standardData.email || null,\n    phone: standardData.phone_number || null,\n    \n    // Property info\n    propertyAddress: standardData.openHouseTitle || 'Unknown Property',\n    openHouseType: standardData.openHouseType || 'open-house',\n    \n    // Engagement data\n    hasRating: hasRating,\n    rating: rating,\n    ratingDisplay: hasRating ? `${rating}/5` : 'Not rated',\n    hasAgent: standardData.are_you_currently_working_with_an_agent || 'Not specified',\n    hasBuyerAgreement: standardData.do_you_have_a_signed_buyer_agreement || null,\n    timestamp: timestamp,\n    rawTimestamp: standardData.submissionTimestamp,\n    \n    // Lead scoring\n    leadPriority: leadPriority,\n    embedColor: embedColor,\n    \n    // Image data\n    hasPhoto: hasPhoto,\n    imageBase64: imageBase64,\n    imageMimeType: imageMimeType,\n    \n    // Custom fields\n    customFields: customFieldsArray,\n    hasCustomFields: customFieldsArray.length > 0,\n    \n    // Contact preferences\n    hasEmail: !!standardData.email,\n    hasPhone: !!standardData.phone_number,\n    \n    // Raw data for reference\n    rawData: webhookData\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "51e8b880-f380-4539-b1c9-980e2260454d",
      "name": "将图像转换为二进制",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [
        400,
        0
      ],
      "parameters": {
        "mode": "jsonToBinary",
        "options": {
          "encoding": "base64",
          "fileName": "={{ $json.fullName.replace(/ /g, '_') }}_photo.jpg",
          "mimeType": "={{ $json.imageMimeType }}"
        },
        "sourceKey": "imageBase64",
        "convertAllData": false,
        "destinationKey": "photo"
      },
      "typeVersion": 1.1
    },
    {
      "id": "78954bf0-f3d9-4af5-bddc-dbcb1a77e8c9",
      "name": "Discord 通知",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Sends to Discord with photo thumbnail",
      "position": [
        624,
        0
      ],
      "parameters": {
        "url": "YOUR_WEBHOOK_URL_HERE",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "name": "payload_json",
              "value": "={{ \n  (function() {\n    // Build fields array\n    const fields = [\n      {\n        \"name\": \"👤 Name\",\n        \"value\": $json.fullName,\n        \"inline\": true\n      },\n      {\n        \"name\": \"🏢 Has Agent?\",\n        \"value\": $json.hasAgent,\n        \"inline\": true\n      }\n    ];\n    \n    // Add rating field only if it exists\n    if ($json.hasRating) {\n      fields.push({\n        \"name\": \"⭐ Rating\",\n        \"value\": $json.ratingDisplay,\n        \"inline\": true\n      });\n    }\n    \n    // Add buyer agreement if available\n    if ($json.hasBuyerAgreement) {\n      fields.push({\n        \"name\": \"📝 Buyer Agreement\",\n        \"value\": $json.hasBuyerAgreement,\n        \"inline\": true\n      });\n    }\n    \n    // Add contact info\n    fields.push(\n      {\n        \"name\": \"📧 Email\",\n        \"value\": $json.email || 'Not provided',\n        \"inline\": true\n      },\n      {\n        \"name\": \"📱 Phone\",\n        \"value\": $json.phone || 'Not provided',\n        \"inline\": true\n      },\n      {\n        \"name\": \"🕒 Visit Time\",\n        \"value\": $json.timestamp,\n        \"inline\": false\n      }\n    );\n    \n    // Add custom fields if any\n    if ($json.customFields && $json.customFields.length > 0) {\n      fields.push(...$json.customFields);\n    }\n    \n    const payload = {\n      \"embeds\": [\n        {\n          \"title\": \"🏠 New Open House Visitor - \" + $json.leadPriority + \" LEAD\",\n          \"description\": \"**\" + $json.fullName + \"** visited **\" + $json.propertyAddress + \"**\",\n          \"color\": $json.embedColor,\n          \"fields\": fields,\n          \"footer\": {\n            \"text\": \"SignSnap Home | Lead Priority: \" + $json.leadPriority\n          },\n          \"timestamp\": $json.rawTimestamp\n        }\n      ]\n    };\n    \n    // Add thumbnail if photo exists (will use attachment)\n    if ($json.hasPhoto) {\n      payload.embeds[0].thumbnail = {\n        \"url\": \"attachment://\" + $json.fullName.replace(/ /g, '_') + \"_photo.jpg\"\n      };\n    }\n    \n    return JSON.stringify(payload);\n  })()\n}}"
            },
            {
              "name": "files[0]",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "photo"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "36952b83-ea4c-4001-a53b-a179c5dea94e",
      "name": "有电话号码吗?",
      "type": "n8n-nodes-base.if",
      "position": [
        848,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "phone-check",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $('Parse & Enrich Data').item.json.hasPhone }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c2e72a81-eb01-4ebc-bade-f1aa0735c1d9",
      "name": "发送短信 (Twilio)",
      "type": "n8n-nodes-base.twilio",
      "notes": "Configure Twilio credentials in n8n",
      "position": [
        1056,
        -112
      ],
      "parameters": {
        "to": "={{ $('Parse & Enrich Data').item.json.phone }}",
        "from": "={{ $credentials.twilioPhoneNumber }}",
        "message": "=Hi {{ $('Parse & Enrich Data').item.json.firstName }}! Thank you for visiting {{ $('Parse & Enrich Data').item.json.propertyAddress }} today. {{ $json.embeds[0].fields[1].value === 'No' ? \"We'd love to help you find your perfect home! Our experienced team can provide exclusive listings and personalized service. Reply to schedule a private consultation!\" : \"Hope you enjoy the property! Feel free to reach out if you have any additional questions.\" }}",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "4c73efc1-4cc0-4eaa-8f5c-09b59b9a4958",
      "name": "有电子邮件吗?",
      "type": "n8n-nodes-base.if",
      "position": [
        1056,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "email-check",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $('Parse & Enrich Data').item.json.hasEmail }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c02d15c4-0254-4dff-82a8-603eeda2982d",
      "name": "发送欢迎邮件",
      "type": "n8n-nodes-base.emailSend",
      "notes": "Configure SMTP credentials in n8n",
      "position": [
        1280,
        96
      ],
      "webhookId": "0119fc19-8eb0-4108-954b-8ca510416c78",
      "parameters": {
        "html": "=Hi {{ $('Parse & Enrich Data').item.json.firstName }}!\n\nThank you for visiting {{ $('Parse & Enrich Data').item.json.propertyAddress }} today. \n{{ $json.embeds[0].fields[1].value === 'No' ? \"We'd love to help you find your perfect home! Our experienced team can provide exclusive listings and personalized service. Reply to schedule a private consultation!\" : \"Hope you enjoy the property! Feel free to reach out if you have any additional questions.\" }}\n\n{SET YOUR TEAM OR PERSONAL FOOTER HERE}",
        "options": {},
        "subject": "=Thank You for Visiting {{ $('Parse & Enrich Data').item.json.propertyAddress }}!",
        "toEmail": "={{ $('Parse & Enrich Data').item.json.email }}",
        "fromEmail": "YOUR_EMAIL_HERE"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2f817a77-00c0-48ca-b640-800559834b2c",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -304
      ],
      "parameters": {
        "height": 256,
        "content": "## 从 Sign Snap Home 接收登录数据"
      },
      "typeVersion": 1
    },
    {
      "id": "a3a41519-d806-4582-ad58-2d6834c1a663",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        -192
      ],
      "parameters": {
        "width": 160,
        "height": 128,
        "content": "## 检查和丰富登录数据"
      },
      "typeVersion": 1
    },
    {
      "id": "d5fc183c-7fdd-4f6e-8856-43bb21b834c8",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        -160
      ],
      "parameters": {
        "width": 150,
        "height": 96,
        "content": "将访客照片从 Base64 转换为二进制以便在 Discord 发送"
      },
      "typeVersion": 1
    },
    {
      "id": "7aa663fa-1756-4f0e-bb98-d4defecd8481",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -336
      ],
      "parameters": {
        "width": 150,
        "height": 272,
        "content": "## 发送到 Discord"
      },
      "typeVersion": 1
    },
    {
      "id": "39a19190-f7cb-43bb-8c78-475e86d1c7d0",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -384
      ],
      "parameters": {
        "width": 624,
        "height": 192,
        "content": "## 检查是否提供了电话"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Parse & Enrich Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Email?": {
      "main": [
        [
          {
            "node": "Send Welcome Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Phone Number?": {
      "main": [
        [
          {
            "node": "Send SMS (Twilio)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Has Email?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse & Enrich Data": {
      "main": [
        [
          {
            "node": "Convert Image to Binary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Discord Notification": {
      "main": [
        [
          {
            "node": "Has Phone Number?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Image to Binary": {
      "main": [
        [
          {
            "node": "Discord Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

中级 - 内容创作, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
中级
节点数量13
分类2
节点类型8
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

作者
Kaden Reese

Kaden Reese

@kadenreese

I started automating with Python in 2020 and still use it in workflows when needed, but I’ve recently leaned into n8n for client-facing solutions. Lately I’ve focused on real estate automations, though I also build workflows for email, scraping, and other use cases. Currently Building 👇🏻

外部链接
在 n8n.io 查看

分享此工作流