{
  "id": "I4JZs4ZoF6uGWA6K",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Slack Lead Enricher",
  "tags": [],
  "nodes": [
    {
      "id": "867c1363-367b-4d53-b3ed-7412ae958851",
      "name": "New Message Catcher",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -260,
        80
      ],
      "parameters": {
        "options": {},
        "trigger": [
          "message"
        ],
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "36520fc6-6b17-4b6b-a3cb-71e08285ca7c",
      "name": "Send Company Details",
      "type": "n8n-nodes-base.slack",
      "position": [
        2000,
        80
      ],
      "parameters": {
        "text": "=*Company Name:* {{$node[\"Format Slack Company Card\"].json.name}}\n*Website:* <{{$node[\"Format Slack Company Card\"].json.website}}|{{$node[\"Format Slack Company Card\"].json.website}}>\n*LinkedIn:* <{{$node[\"Format Slack Company Card\"].json.linkedin}}|{{$node[\"Format Slack Company Card\"].json.linkedin}}>\n*Number of Employees:* {{$node[\"Format Slack Company Card\"].json.employees}}\n*Industry:* {{$node[\"Format Slack Company Card\"].json.industry}}\n*Recent News:*\n{{$node[\"Format Slack Company Card\"].json.recentNews}}\n\n*Key People:*\n{{$node[\"Format Slack Company Card\"].json.keyPeople}}\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C095SRQQL73",
          "cachedResultName": "all-test-workspace"
        },
        "otherOptions": {
          "thread_ts": {
            "replyValues": {
              "thread_ts": "={{$node[\"New Message Catcher\"].json[\"ts\"]}}\n"
            }
          },
          "unfurl_links": false,
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "01e11aa6-7afc-4234-a32e-284bff6f2f59",
      "name": "Extract Company Name Input",
      "type": "n8n-nodes-base.code",
      "position": [
        180,
        80
      ],
      "parameters": {
        "jsCode": "return items\n  .map(item => {\n    const data = $node[\"New Message Catcher\"].json;\n    const text = data.text || \"\";\n\n    // Ignore thread replies: skip if thread_ts exists and differs from ts\n    if (data.thread_ts && data.thread_ts !== data.ts) {\n      return null;\n    }\n\n    const emailRegex = /[a-zA-Z0-9._%+-]+@([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})/;\n    let match = text.match(emailRegex);\n    let domain = null;\n    if (match) {\n      domain = match[1].toLowerCase();\n    } else {\n      const domainRegex = /\\b([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})\\b/;\n      match = text.match(domainRegex);\n      if (match) {\n        domain = match[1].toLowerCase();\n      }\n    }\n\n    if (!domain) {\n      return null;\n    }\n\n    // Blacklist common generic email domains\n    const blacklist = [\n      \"gmail.com\", \"icloud.com\", \"yahoo.com\", \"outlook.com\",\n      \"hotmail.com\", \"aol.com\", \"msn.com\"\n    ];\n    if (blacklist.includes(domain)) {\n      return null;\n    }\n\n    return { json: { companyDomain: domain } };\n  })\n  .filter(item => item !== null);"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "559066c3-be7f-4311-be3a-a77e17ab4b53",
      "name": "Company Name Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        400,
        75
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b78ac018-0287-42fc-8cfc-3a706c490473",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.companyDomain}}",
              "rightValue": "=[null]"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "614729f3-3bda-4ca9-b117-a6c73c0aefa5",
      "name": "Start Company Enrichment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        620,
        75
      ],
      "parameters": {
        "url": "=https://api.extruct.ai/v1/tables/{{ $node[\"Set Extruct Table ID\"].json.EXTRUCT_TABLE_ID }}/rows\n",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"rows\": [\n    {\n      \"data\": {\n        \"input\": \"{{ $node[\"Extract Company Name Input\"].json.companyDomain }}\"\n      }\n    }\n  ],\n  \"run\": true\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "4a7f16f7-8ee5-4fa4-8694-cf1169de224a",
      "name": "Hold for API Processing",
      "type": "n8n-nodes-base.wait",
      "position": [
        840,
        75
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "e7fb5432-fcb9-42b3-b100-21e4cb217fbc",
      "name": "Check Enrichment Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1060,
        0
      ],
      "parameters": {
        "url": "=https://api.extruct.ai/v1/tables/{{ $('Set Extruct Table ID').item.json.EXTRUCT_TABLE_ID }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "5d2efdd1-870b-49c0-a152-2f28e3b7f56b",
      "name": "Is Company Info Ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        1280,
        75
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f8432dca-c337-4644-8163-fa83f12e5ded",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status.run_status }}",
              "rightValue": "=running"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b54128ff-f67e-45d3-8fcf-4dba739c2839",
      "name": "Get Company Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1500,
        75
      ],
      "parameters": {
        "url": "=https://api.extruct.ai/v1/tables/{{ $('Set Extruct Table ID').item.json.EXTRUCT_TABLE_ID }}/data",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "802f9558-1232-4785-9751-6807bf601256",
      "name": "Format Slack Company Card",
      "type": "n8n-nodes-base.code",
      "position": [
        1720,
        75
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const rows = item.json.rows;\n  if (!Array.isArray(rows) || rows.length === 0) {\n    throw new Error('No rows available in response');\n  }\n  const lastRow = rows[rows.length - 1].data;\n  return {\n    json: {\n      name:       lastRow.company_name.value.answer,\n      website:    lastRow.company_website.value.answer,\n      linkedin:   lastRow.linkedin_profile.value.answer,\n      employees:  lastRow.company_num_employees.value.answer,\n      industry:   lastRow.company_industry.value.answer,\n      recentNews: lastRow.recent_news.value.answer,\n      keyPeople:  lastRow.key_people.value.answer,\n    }\n  };\n});"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "39512e99-4ddf-461d-8d78-f0c69c0f667f",
      "name": "Set Extruct Table ID",
      "type": "n8n-nodes-base.set",
      "position": [
        -40,
        75
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9eb02d95-b83d-4f14-b8bf-3a65383b20f2",
              "name": "=EXTRUCT_TABLE_ID",
              "type": "string",
              "value": "YOUR_EXTRUCT_TABLE_ID"
            }
          ]
        }
      },
      "typeVersion": 3.4,
      "alwaysOutputData": true
    },
    {
      "id": "787593a2-7e1e-4a8e-8e47-e35682c6976b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1220,
        -100
      ],
      "parameters": {
        "width": 880,
        "height": 1400,
        "content": "# Quickstart: Slack Lead Enricher in n8n \n\nAutomatic lead enrichment in Slack: monitors your Slack channel for new lead emails posted there, extracts each company\u2019s name or domain, sends it to the Extruct API for data enrichment, then posts back a structured Slack card with company name, website, LinkedIn profile, number of employees, industry, recent news, and key contacts.\n\n## 1. Sign up for Extruct\n* **Free 1,000-credit trial** at [https://www.extruct.ai/](https://www.extruct.ai/)\n\n---\n\n## 2. Prepare Your Extruct Table\n1. Open this Extruct table template: https://app.extruct.ai/tables/shared/wZ6FxspNc5ctrB55\n2. Copy the **table ID** from the browser URL.\n\n![Screenshot](https://images.weserv.nl/?url=raw.githubusercontent.com/zodackwand/extruct_screenshots/main/table_id_from_link.png&w=500)\n\n3. In n8n you\u2019ll paste that into the **Set Extruct Table ID** node.\n\n---\n\n## 3. Configure Slack\n### A. Create & Install Your App\n\n1. Go to [https://api.slack.com/apps](https://api.slack.com/apps) \u2192 **Create New App** \u2192 **From scratch**.\n2. Name it (e.g. `n8n Lead Enricher`) and pick your workspace.\n3. **OAuth & Permissions** \u2192 **Bot Token Scopes** \u2192 add:\n\n   * `channels:read`\n   * `channels:history`\n   * `chat:write`\n\n4. Click **Install to Workspace**, authorize, then save the **Bot User OAuth Token** (`xoxb-\u2026`).\n\n### B. Enable Events\n1. In your Slack app settings \u2192 **Event Subscriptions** \u2192 **Enable Events** = On.\n2. **Request URL** \u2192 paste the **Production** Webhook URL from your n8n **New Message Catcher** node.\n3. Under **Subscribe to Bot Events** \u2192 add `message.channels`\n4. Click **Reinstall to Workspace** to pick up your new scopes & event hook.\n\n---\n\n## 4. Set Up n8n Credentials & Variables\n1. In each Slack node, choose or create a **Slack OAuth2 API** credential and paste your Bot User OAuth Token (`xoxb-\u2026`); and set channel to watch to the Slack channel where your lead emails are posted.\n2. In every HTTP Request node, choose or create a **Generic Credential (Bearer YOUR_TOKEN_HERE)** and paste your Extruct API token.\n\n---\n\n## 5. Activate & Use\n1. In Slack, invite your bot to the channel:\n\n   ```\n   /invite @bot_name\n   ```\n2. Toggle **Active** on in the top-right of the n8n editor.\n3. This workflow monitors your Slack channel for **new lead emails posted there and extracts the company name** from each message.\n4. The bot will reply with a formatted company profile."
      },
      "typeVersion": 1
    },
    {
      "id": "dbeafe18-c0bf-4386-baf6-e532534f45bb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -100
      ],
      "parameters": {
        "color": 2,
        "width": 420,
        "height": 360,
        "content": "## Trigger & Initialization:\nMonitors Slack for new messages and assigns the Extruct table ID for enrichment."
      },
      "typeVersion": 1
    },
    {
      "id": "713d96c7-a697-46a0-bd21-66d0c6124461",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        120,
        -100
      ],
      "parameters": {
        "color": 3,
        "width": 440,
        "height": 360,
        "content": "## Lead Extraction:\nParses each message for a company domain or name and filters out invalid entries."
      },
      "typeVersion": 1
    },
    {
      "id": "03b330c8-2b53-4db9-9475-f6f6bef8c891",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -100
      ],
      "parameters": {
        "color": 4,
        "width": 860,
        "height": 360,
        "content": "## Enrichment Request Flow:\nSends the domain to Extruct API and polls until the enrichment run completes."
      },
      "typeVersion": 1
    },
    {
      "id": "cbe81611-57c5-4499-b2eb-07edab80129d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1460,
        -100
      ],
      "parameters": {
        "color": 5,
        "width": 420,
        "height": 360,
        "content": "## Data Retrieval & Formatting:\nRetrieves the enriched company details and builds a structured Slack card."
      },
      "typeVersion": 1
    },
    {
      "id": "37f297eb-c779-4d3f-9fd2-604c1164242c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1900,
        -100
      ],
      "parameters": {
        "color": 6,
        "width": 300,
        "height": 360,
        "content": "## Slack Publishing:\nPosts the formatted company profile (name, website, LinkedIn, headcount, industry, recent news, key contacts) back into the original Slack thread."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ab044bfc-1128-4ca0-90ab-70b904644d79",
  "connections": {
    "Get Company Data": {
      "main": [
        [
          {
            "node": "Format Slack Company Card",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Message Catcher": {
      "main": [
        [
          {
            "node": "Set Extruct Table ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Company Name Exists?": {
      "main": [
        [
          {
            "node": "Start Company Enrichment",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Set Extruct Table ID": {
      "main": [
        [
          {
            "node": "Extract Company Name Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Company Info Ready?": {
      "main": [
        [
          {
            "node": "Hold for API Processing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Company Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Enrichment Status": {
      "main": [
        [
          {
            "node": "Is Company Info Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hold for API Processing": {
      "main": [
        [
          {
            "node": "Check Enrichment Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Company Enrichment": {
      "main": [
        [
          {
            "node": "Hold for API Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Slack Company Card": {
      "main": [
        [
          {
            "node": "Send Company Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Company Name Input": {
      "main": [
        [
          {
            "node": "Company Name Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}