8
n8n 中文网amn8n.com

通过 Slack 将 RB2B 网站访客同步到 Attio CRM 并创建商机

高级

这是一个Lead Generation领域的自动化工作流,包含 16 个节点。主要使用 If, Code, Switch, HttpRequest, SlackTrigger 等节点。 通过 Slack 将 RB2B 网站访客同步到 Attio CRM 并创建商机

前置要求
  • 可能需要目标 API 的认证凭证
  • Slack Bot Token 或 Webhook URL
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "8d70623c0c9f4448eda9626cd8185192c28447e191325b0c0d94d3f40d23be3a"
  },
  "nodes": [
    {
      "id": "8c33bf1c-c341-445c-b7cc-3537a59bae1c",
      "name": "RB2B 新消息",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -120,
        180
      ],
      "webhookId": "387fbf83-8a7d-4b68-a1b1-1196fd130c1c",
      "parameters": {
        "options": {},
        "trigger": [
          "message"
        ],
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0712SMCKRN",
          "cachedResultName": "website-visitors"
        }
      },
      "credentials": {
        "slackApi": {
          "id": "gohktp5vDBf3YRob",
          "name": "Slack bot (Internal Slack)"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a725c2de-1074-4b6b-8ff5-ba76b5a5dcbb",
      "name": "清理数据",
      "type": "n8n-nodes-base.code",
      "position": [
        240,
        180
      ],
      "parameters": {
        "jsCode": "function splitName(fullName) {\n  if (!fullName || typeof fullName !== 'string') {\n    return { firstName: '', lastName: '' };\n  }\n  const parts = fullName.trim().split(/\\s+/);\n  if (parts.length === 0) {\n    return { firstName: '', lastName: '' };\n  }\n  const firstName = parts[0];\n  const lastName = parts.length > 1 ? parts.slice(1).join(' ') : '';\n  return { firstName, lastName, fullName };\n}\n\nfunction extractDataFromSlackMessage(messageData) {\n  // Get the message text\n  const messageText = messageData.text || '';\n  \n  // Initialize extracted data\n  let fullName = '';\n  let linkedin = '';\n  let title = '';\n  let company = '';\n  let email = '';\n  let location = '';\n  let urls = [];\n  \n  // Extract LinkedIn URL from rich text blocks if available\n  if (messageData.blocks && messageData.blocks.length > 0) {\n    for (const block of messageData.blocks) {\n      if (block.type === 'rich_text' && block.elements) {\n        for (const element of block.elements) {\n          if (element.type === 'rich_text_section' && element.elements) {\n            for (const richElement of element.elements) {\n              if (richElement.type === 'link' && richElement.url && richElement.url.includes('linkedin.com')) {\n                linkedin = richElement.url;\n                break;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n  \n  // Helper function to clean up Slack link format and extract display text\n  function cleanSlackLinks(text) {\n    // Replace <URL|Display_Text> with just Display_Text\n    return text.replace(/<[^|>]+\\|([^>]+)>/g, '$1')\n               .replace(/&amp;/g, '&')\n               .trim();\n  }\n  \n  // Function to extract URLs from text\n  function extractUrlsFromText(text) {\n    const urls = [];\n    // Match URLs in Slack format <URL|Display_Text> or <URL>\n    const urlMatches = text.match(/<(https?:\\/\\/[^|>]+)/g);\n    if (urlMatches) {\n      urlMatches.forEach(match => {\n        try {\n          const url = match.replace('<', '');\n          if (!urls.includes(url)) {\n            urls.push(url);\n          }\n        } catch (e) {\n          // Invalid URL, skip\n        }\n      });\n    }\n    return urls;\n  }\n  \n  // Function to extract all URLs from rich text blocks\n  function extractUrlsFromBlocks(blocks) {\n    const allUrls = [];\n    \n    if (!blocks || !Array.isArray(blocks)) return allUrls;\n    \n    for (const block of blocks) {\n      if (block.type === 'rich_text' && block.elements) {\n        for (const element of block.elements) {\n          if (element.type === 'rich_text_section' && element.elements) {\n            for (const richElement of element.elements) {\n              if (richElement.type === 'link' && richElement.url) {\n                const url = richElement.url;\n                if (!allUrls.includes(url)) {\n                  allUrls.push(url);\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n    return allUrls;\n  }\n  \n  // Parse the text content using regex patterns\n  const nameMatch = messageText.match(/\\*Name\\*:\\s*([^\\n]+)/);\n  if (nameMatch) {\n    fullName = nameMatch[1].trim();\n  }\n  \n  const titleMatch = messageText.match(/\\*Title\\*:\\s*([^\\n]+)/);\n  if (titleMatch) {\n    title = cleanSlackLinks(titleMatch[1]);\n  }\n  \n  const companyMatch = messageText.match(/\\*Company\\*:\\s*([^\\n]+)/);\n  if (companyMatch) {\n    const rawCompany = companyMatch[1];\n    company = cleanSlackLinks(rawCompany);\n    // Extract URLs from company field\n    const textUrls = extractUrlsFromText(rawCompany);\n    urls = textUrls;\n  }\n  \n  // Extract location\n  const locationMatch = messageText.match(/\\*Location\\*:\\s*([^\\n]+)/);\n  if (locationMatch) {\n    location = cleanSlackLinks(locationMatch[1]);\n  }\n  \n  // Extract email address\n  const emailMatch = messageText.match(/\\*Email\\*:\\s*([^\\n\\s]+)/);\n  if (emailMatch) {\n    email = emailMatch[1].trim();\n  }\n  \n  // Alternative email extraction patterns\n  if (!email) {\n    // Try to find email in the general text\n    const generalEmailMatch = messageText.match(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})/);\n    if (generalEmailMatch) {\n      email = generalEmailMatch[1];\n    }\n  }\n  \n  // Extract all URLs from rich text blocks\n  const blockUrls = extractUrlsFromBlocks(messageData.blocks);\n  \n  // Combine all URLs\n  const allUrls = [...new Set([...urls, ...blockUrls])];\n  \n  // If LinkedIn not found in blocks, try to extract from text\n  if (!linkedin) {\n    const linkedinMatch = messageText.match(/\\*LinkedIn\\*:\\s*<([^>]+)>/);\n    if (linkedinMatch) {\n      linkedin = linkedinMatch[1];\n    }\n  }\n  \n  return {\n    fullName,\n    linkedin,\n    title,\n    company,\n    email,\n    location,\n    urls: allUrls\n  };\n}\n\nfunction extractDomainsFromUrls(urls) {\n  console.log('URLs received:', urls);\n  \n  if (!urls || !Array.isArray(urls)) {\n    console.log('No URLs or not an array');\n    return [];\n  }\n  \n  const domains = [];\n  \n  urls.forEach(url => {\n    console.log('Processing URL:', url);\n    \n    // Skip LinkedIn URLs\n    if (url.includes('linkedin.com')) {\n      console.log('Skipping LinkedIn URL:', url);\n      return;\n    }\n    \n    try {\n      // Simple regex approach as backup\n      const domainMatch = url.match(/https?:\\/\\/(www\\.)?([^\\/]+)/);\n      if (domainMatch && domainMatch[2]) {\n        let domain = domainMatch[2];\n        console.log('Domain extracted via regex:', domain);\n        \n        if (domain && !domains.includes(domain)) {\n          domains.push(domain);\n          console.log('Added domain:', domain);\n        }\n      } else {\n        console.log('No domain match found for:', url);\n      }\n    } catch (e) {\n      console.log(`Error processing URL: ${url}`, e.message);\n    }\n  });\n  \n  console.log('Final domains:', domains);\n  return domains;\n}\n\n// Main execution\nconst inputData = $input.first().json;\nconst extractedData = extractDataFromSlackMessage(inputData);\nconst names = splitName(extractedData.fullName);\n\n// Extract domains from URLs for Attio\nconst domains = extractDomainsFromUrls(extractedData.urls);\n\nreturn [\n  {\n    json: {\n      full_name: names.fullName,\n      first_name: names.firstName,\n      last_name: names.lastName,\n      linkedin: extractedData.linkedin,\n      title: extractedData.title,\n      company: extractedData.company,\n      email: extractedData.email,\n      location: extractedData.location,\n      urls: extractedData.urls,\n      domains: domains,\n      primary_domain: domains.length > 0 ? domains[0] : null\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "d69f2ede-b405-42ed-8075-805e14a0d1a3",
      "name": "获取人员信息",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        620,
        180
      ],
      "parameters": {
        "url": "https://api.attio.com/v2/objects/people/records/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"filter\": {\n    \"email_addresses\": {\n      \"$contains\": \"{{ $('Cleanup Data').first().json.email }}\"\n    }\n  },\n  \"page\": {\n    \"size\": 1\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType"
      },
      "credentials": {
        "httpCustomAuth": {
          "id": "96nijytJtWzgxZbl",
          "name": "Attio Headers"
        },
        "httpHeaderAuth": {
          "id": "Pt7T2rgQXTpeIgCk",
          "name": "Anna Attio"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "5adc0ad5-b286-40ff-8dec-e52b3b3d71b4",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -900,
        -120
      ],
      "parameters": {
        "width": 640,
        "height": 900,
        "content": "## 🎯 将 RB2B 网站访客同步至 Attio CRM 并创建交易"
      },
      "typeVersion": 1
    },
    {
      "id": "f58703c3-833d-4c70-b4ed-1b4d74700bbe",
      "name": "创建人员",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1300,
        380
      ],
      "parameters": {
        "url": "https://api.attio.com/v2/objects/people/records",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"data\": {\n    \"values\": {\n      \"name\": [\n        {\n          \"first_name\": \"{{ $('Cleanup Data').item.json.first_name }}\",\n          \"last_name\": \"{{ $('Cleanup Data').item.json.last_name }}\",\n          \"full_name\": \"{{ $('Cleanup Data').item.json.full_name }}\"\n        }\n      ],\n      \"email_addresses\": [\"{{ $('Cleanup Data').item.json.email }}\"]\n    }\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType"
      },
      "credentials": {
        "httpCustomAuth": {
          "id": "96nijytJtWzgxZbl",
          "name": "Attio Headers"
        },
        "httpHeaderAuth": {
          "id": "Pt7T2rgQXTpeIgCk",
          "name": "Anna Attio"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d4822bab-4756-4663-90af-2f8cbb6a5aef",
      "name": "创建交易",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1520,
        380
      ],
      "parameters": {
        "url": "https://api.attio.com/v2/objects/deals/records",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"data\": {\n    \"values\": {\n      \"name\": \"Deal with {{ $json.data.values.name[0].full_name }}\",\n      \"stage\": \"RB2B Website Visitor\",\n      \"value\": 0,\n      \"owner\": \"yourname@emaildomain.com\",\n      \"associated_people\": [\n        {\n          \"target_object\": \"people\",\n          \"target_record_id\": \"{{ $json.data.id.record_id }}\"\n        }\n      ]\n    }\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "Pt7T2rgQXTpeIgCk",
          "name": "Anna Attio"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0c325d8d-5258-4d0e-8f78-74b9581e8ab2",
      "name": "创建关联交易",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1620,
        200
      ],
      "parameters": {
        "url": "https://api.attio.com/v2/objects/deals/records",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"data\": {\n    \"values\": {\n      \"name\": \"Deal with {{ $('Get Person').item.json.data[0].values.name[0].full_name }}\",\n      \"stage\": \"RB2B Website Visitor\",\n      \"value\": 0,\n      \"owner\": \"yourname@emaildomain.com\",\n      \"associated_people\": [\n        {\n          \"target_object\": \"people\",\n          \"target_record_id\": \"{{ $('Get Person').item.json.data[0].id.record_id }}\"\n        }\n      ]\n    }\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "Pt7T2rgQXTpeIgCk",
          "name": "Anna Attio"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c4f2d0b7-f32c-4f0d-9b55-7ca011b2e828",
      "name": "更新交易阶段",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1480,
        0
      ],
      "parameters": {
        "url": "=https://api.attio.com/v2/objects/deals/records/{{ $('Get Person').item.json.data[0].values.associated_deals[0].target_record_id }}",
        "method": "PATCH",
        "options": {},
        "jsonBody": "{\n  \"data\": {\n    \"values\": {\n      \"stage\": \"RB2B Website Visitor\"\n    }\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "Pt7T2rgQXTpeIgCk",
          "name": "Anna Attio"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "cf2fd591-a51b-4334-ade2-6dc5b10c8b6e",
      "name": "人员是否存在?",
      "type": "n8n-nodes-base.if",
      "position": [
        940,
        180
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d838154e-4857-4180-b2d4-30e021e95e39",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.data && $json.data.length > 0 }}",
              "rightValue": "0"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4db29d8f-f712-4f9a-95b9-6396d05a4819",
      "name": "切换",
      "type": "n8n-nodes-base.switch",
      "position": [
        1260,
        100
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Already has associated deal",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "d99a0062-cfe0-45bf-9475-7d250786ac00",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.data[0].values.associated_deals.length > 0 }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "No associated deal",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "07564302-add4-4389-9c8b-0a1d8e3b90a1",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.data[0].values.associated_deals.length === 0 }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {},
        "looseTypeValidation": true
      },
      "typeVersion": 3.2
    },
    {
      "id": "7b9b7d43-ac35-40bd-b2e7-1db00250ce60",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -180,
        -100
      ],
      "parameters": {
        "color": 7,
        "width": 300,
        "height": 240,
        "content": "## 1. RB2B Slack 触发器"
      },
      "typeVersion": 1
    },
    {
      "id": "da56bb42-8627-48a2-9067-6c798f728b1e",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        180,
        -100
      ],
      "parameters": {
        "color": 7,
        "width": 300,
        "height": 240,
        "content": "## 2. 解析 RB2B 访客数据"
      },
      "typeVersion": 1
    },
    {
      "id": "5a5d5ea1-4d5c-42c5-a5d9-1090e2769c93",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        540,
        -100
      ],
      "parameters": {
        "color": 7,
        "width": 300,
        "height": 240,
        "content": "## 3. 检查人员是否存在于 Attio 中"
      },
      "typeVersion": 1
    },
    {
      "id": "66b73760-9085-49e1-b4f6-11397177ba2d",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        840,
        360
      ],
      "parameters": {
        "color": 7,
        "width": 300,
        "height": 300,
        "content": "## 4. 智能交易管理"
      },
      "typeVersion": 1
    },
    {
      "id": "6eda464a-2a2f-49e5-91bd-a2abe92c537c",
      "name": "便签5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "height": 180,
        "content": "## 5. 创建/更新 Attio 记录"
      },
      "typeVersion": 1
    },
    {
      "id": "3192726d-1b78-4ab5-9193-06fb1a28e20f",
      "name": "便签6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        440
      ],
      "parameters": {
        "color": 3,
        "width": 460,
        "height": 260,
        "content": "### 需要设置!"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {
    "Cleanup Data": [
      {
        "urls": [
          "https://www.linkedin.com/in/john-smith-dev",
          "https://www.techcorp.com/"
        ],
        "email": "john.smith@example.com",
        "title": "Senior Developer",
        "company": "TechCorp Industries",
        "domains": [
          "techcorp.com"
        ],
        "linkedin": "https://www.linkedin.com/in/john-smith-dev",
        "location": "San Francisco, CA",
        "full_name": "John Smith",
        "last_name": "Smith",
        "first_name": "John",
        "primary_domain": "techcorp.com"
      }
    ],
    "RB2B New Message": [
      {
        "ts": "1748900000.123456",
        "team": "T02EXAMPLE789",
        "text": "*Name*: John Smith\n*Title*: Senior Developer\n*Company*: TechCorp Industries\n*Email*: john.smith@example.com\n*LinkedIn*: <https://www.linkedin.com/in/john-smith-dev>\n*Location*: San Francisco, CA\n\nFirst identified visiting *<https://www.techcorp.com/>* on *August 5, 2025 at 10:30AM PST*",
        "type": "message",
        "user": "U02DUMMY456",
        "blocks": [
          {
            "type": "rich_text",
            "block_id": "Xy9Zw",
            "elements": [
              {
                "type": "rich_text_section",
                "elements": [
                  {
                    "text": "Name",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": John Smith\n",
                    "type": "text"
                  },
                  {
                    "text": "Title",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": Senior Developer\n",
                    "type": "text"
                  },
                  {
                    "text": "Company",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": TechCorp Industries\n",
                    "type": "text"
                  },
                  {
                    "text": "Email",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": john.smith@example.com\n",
                    "type": "text"
                  },
                  {
                    "text": "LinkedIn",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": ",
                    "type": "text"
                  },
                  {
                    "url": "https://www.linkedin.com/in/john-smith-dev",
                    "type": "link"
                  },
                  {
                    "text": "\n",
                    "type": "text"
                  },
                  {
                    "text": "Location",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": ": San Francisco, CA\n\nFirst identified visiting ",
                    "type": "text"
                  },
                  {
                    "url": "https://www.techcorp.com/",
                    "text": "https://www.techcorp.com/",
                    "type": "link",
                    "style": {
                      "bold": true
                    }
                  },
                  {
                    "text": " on ",
                    "type": "text"
                  },
                  {
                    "text": "August 5, 2025 at 10:30AM PST",
                    "type": "text",
                    "style": {
                      "bold": true
                    }
                  }
                ]
              }
            ]
          }
        ],
        "channel": "C09DUMMY123",
        "event_ts": "1748900000.123456",
        "channel_type": "channel",
        "client_msg_id": "f9e8d7c6-b5a4-3210-9876-54321fedcba0"
      }
    ]
  },
  "connections": {
    "Switch": {
      "main": [
        [
          {
            "node": "Update Deal Stage",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Associated Deal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Person": {
      "main": [
        [
          {
            "node": "Person Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cleanup Data": {
      "main": [
        [
          {
            "node": "Get Person",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Person": {
      "main": [
        [
          {
            "node": "Create Deal",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Person Exists?": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Person",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RB2B New Message": {
      "main": [
        [
          {
            "node": "Cleanup Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

高级 - 潜在客户开发

需要付费吗?

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

工作流信息
难度等级
高级
节点数量16
分类1
节点类型6
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流