{
  "nodes": [
    {
      "parameters": {
        "content": "# Case Study: IT-Dienstleister automatisiert Outreach und gewinnt 8 Neukunden in 90 Tagen\n\n**Quelle:** https://vis2lead.org/case-study-it-dienstleister-outreach-automation-8-neukunden/\n**Slug:** case-study-it-dienstleister-outreach-automation-8-neukunden\n**Post-ID:** 2493\n\n## Was macht dieser Workflow?\nDiese n8n-Vorlage ist auf das Thema des Blogartikels zugeschnitten und liefert einen Starter-Workflow zur Umsetzung.\n\n## Erste Schritte\n1. Workflow in n8n importieren (Workflows -> Import from File)\n2. Credentials konfigurieren (Google Places, OpenAI, Google Sheets)\n3. Im Node *1. Set Search Parameters* die Suchparameter auf das Thema des Blogartikels anpassen\n4. Manuell testen, dann produktiv schalten\n\n## Anpassung an den Use-Case\nDer mitgelieferte Lead-Gen-Flow ist generisch. Tausche die Datenquelle (Google Places) gegen eine spezifische API/Quelle aus, die zum Use-Case des Blogartikels passt. Die nachgelagerten Nodes (Parsing, Scoring, Filter, Sheet-Append) bleiben wiederverwendbar.\n\n**Bereitgestellt von vis2lead.org -- DSGVO-konforme B2B-Sales-Automation.**",
        "height": 520,
        "width": 480,
        "color": 5
      },
      "id": "v2l-sticky-header",
      "name": "V2L Vorlage: Case Study: IT-Dienstleister automatisiert Outreach und gewi",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -380,
        -260
      ]
    },
    {
      "id": "1a608370-405e-4601-b65d-7a336fa0ae82",
      "name": "Generate Report",
      "type": "n8n-nodes-base.function",
      "parameters": {
        "functionCode": "const duplicates = [];\nconst lowQuality = [];\n\nfor (const item of $input.all()) {\n  if (item.json.leadScore <= 50) {\n    lowQuality.push(item.json.businessName);\n  }\n}\n\nreturn [{\n  json: {\n    totalProcessed: $input.all().length,\n    lowQualityLeads: lowQuality.length,\n    lowQualityNames: lowQuality,\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 1
    },
    {
      "id": "af642ea6-17a4-4fd2-a6e7-b26f9bdff825",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "credential-id",
          "name": "openAiApi Credential"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2f801af9-c230-4910-97db-8adf7a8ac650",
      "name": "1. Set Search Parameters",
      "type": "n8n-nodes-base.set",
      "parameters": {
        "values": {
          "string": [
            {
              "name": "searchCategory",
              "value": "dentist"
            },
            {
              "name": "locationName",
              "value": "Istanbul, Turkey"
            },
            {
              "name": "latitude",
              "value": "41.0082"
            },
            {
              "name": "longitude",
              "value": "28.9784"
            },
            {
              "name": "radius",
              "value": "5000"
            },
            {
              "name": "maxResults",
              "value": "20"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "3ecdbef5-6df9-4f62-a9f9-44fa94ad32bc",
      "name": "2. Find Businesses (Google Places)",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://places.googleapis.com/v1/places:searchNearby",
        "method": "POST",
        "options": {
          "timeout": 30000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "jsonBody": "={\"includedTypes\":[\"{{$json[\"searchCategory\"]}}\"],\"maxResultCount\":{{$json[\"maxResults\"]}},\"locationRestriction\":{\"circle\":{\"center\":{\"latitude\":{{$json[\"latitude\"]}},\"longitude\":{{$json[\"longitude\"]}}},\"radius\":{{$json[\"radius\"]}}}}}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Goog-FieldMask",
              "value": "places.id,places.displayName,places.formattedAddress,places.nationalPhoneNumber,places.websiteUri,places.rating,places.businessStatus,places.primaryType,places.location"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "credential-id",
          "name": "httpHeaderAuth Credential"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "3a046790-67dd-4db5-9254-25e2c5b30027",
      "name": "3. Parse & Score Leads",
      "type": "n8n-nodes-base.function",
      "parameters": {
        "functionCode": "const items = [];\nconst places = $input.first().json.places || [];\nconst searchParams = $node[\"1. Set Search Parameters\"].json;\n\nfor (const place of places) {\n  const item = {\n    id: place.id || '',\n    businessName: place.displayName?.text || 'N/A',\n    address: place.formattedAddress || 'N/A',\n    phone: place.nationalPhoneNumber || 'N/A',\n    website: place.websiteUri || 'N/A',\n    rating: place.rating || 0,\n    businessStatus: place.businessStatus || 'UNKNOWN',\n    primaryType: place.primaryType || searchParams.searchCategory,\n    latitude: place.location?.latitude || 0,\n    longitude: place.location?.longitude || 0,\n    searchLocation: searchParams.locationName,\n    searchCategory: searchParams.searchCategory,\n    createdAt: new Date().toISOString(),\n    leadScore: 0,\n    status: 'New Lead'\n  };\n  \n  // Calculate lead score\n  let score = 0;\n  if (item.rating >= 4.5) score += 30;\n  else if (item.rating >= 4.0) score += 20;\n  else if (item.rating >= 3.5) score += 10;\n  \n  if (item.website !== 'N/A') score += 25;\n  if (item.phone !== 'N/A') score += 20;\n  if (item.businessStatus === 'OPERATIONAL') score += 25;\n  \n  item.leadScore = score;\n  \n  items.push({ json: item });\n}\n\nreturn items;"
      },
      "typeVersion": 1
    },
    {
      "id": "4f946456d-53fa-4b03-8521-406b2b6b14ca",
      "name": "4. Filter High-Quality Leads",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json[\"leadScore\"]}}",
              "value2": 50,
              "operation": "larger"
            }
          ],
          "string": [
            {
              "value1": "={{$json[\"businessName\"]}}",
              "value2": "N/A",
              "operation": "notEqual"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5f58958e08-90c8-4f7d-8922-21dd84b80406",
      "name": "5. Loop Through Each Lead",
      "type": "n8n-nodes-base.splitInBatches",
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "6a58958e08-90c8-4f7d-8922-21dd84b80406",
      "name": "6a. Scrape Website with Scrape.do",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "parameters": {
        "url": "http://api.scrape.do/",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $json.website }}"
            },
            {
              "name": "token",
              "value": "{{$env[\"SCRAPE_DO_API_KEY\"]}}"
            }
          ]
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "6b58958e08-90c8-4f7d-8922-21dd84b80406",
      "name": "6b. Check if Scrape Was Successful",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "076a0652-9f88-4992-b111-791aa327e571",
              "operator": {
                "type": "number",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.error.status }}",
              "rightValue": 400
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6c58958e08-90c8-4f7d-8922-21dd84b80406",
      "name": "6c. Extract Footer from HTML",
      "type": "n8n-nodes-base.html",
      "parameters": {
        "options": {},
        "operation": "extractHtmlContent",
        "extractionValues": {
          "values": [
            {
              "key": "footer",
              "cssSelector": "footer"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6d58958e08-90c8-4f7d-8922-21dd84b80406",
      "name": "6d. Extract Contact Info with AI",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "parameters": {
        "text": "=Analyze the following HTML snippet, which comes from a website's footer section. Your task is to extract all available contact information and populate the structured format as requested.\n\n1.  **Extract Social Media URLs:** Scan the HTML for links to specific social media platforms. Find the unique URL for each platform and place it in the corresponding field within the `social` object (e.g., the Facebook URL goes into `social.facebook`). If a link for a platform is not found, leave its field as an empty string.\n\n2.  **Extract Contact Info:** Find all email addresses (`mailto:` links) for `contact.emails`. Find all phone numbers (`tel:` links) for `contact.phones`.\n\n3.  **Extract Location:** Find the physical address and populate `location.full_address`, `location.city`, and `location.country`.\n\n4.  **Extract Other Methods:** Find links to contact forms or WhatsApp (`wa.me/`) and add them to the `other_contact_methods` array.\n\nHTML Content:\n{{ $json.footer }}",
        "options": {
          "systemMessage": "You are a highly efficient and accurate data extraction AI. Your sole purpose is to parse raw HTML content and extract specific information into a structured JSON format as requested. You must only respond with the structured data. Do not add any extra text, comments, or explanations."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "7. Save Enriched Lead to Google Sheets",
      "name": "7. Save Enriched Lead to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "options": {},
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "BusinessName",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.businessName }}"
            },
            {
              "fieldId": "Address",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.address }}"
            },
            {
              "fieldId": "Phone",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.phone }}"
            },
            {
              "fieldId": "website",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.website }}"
            },
            {
              "fieldId": "emails",
              "fieldValue": "={{ $json.output.contact.emails[0] }}"
            },
            {
              "fieldId": "Facebook",
              "fieldValue": "={{ $json.output.social.facebook }}"
            },
            {
              "fieldId": "Instagram",
              "fieldValue": "={{ $json.output.social.instagram }}"
            },
            {
              "fieldId": "Youtube",
              "fieldValue": "={{ $json.output.social.youtube }}"
            },
            {
              "fieldId": "Linkedin",
              "fieldValue": "={{ $json.output.social.linkedin }}"
            },
            {
              "fieldId": "Pinterest",
              "fieldValue": "={{ $json.output.social.pinterest }}"
            },
            {
              "fieldId": "Other",
              "fieldValue": "={{ $json.output.other_contact_methods[0].url }}"
            },
            {
              "fieldId": "rating",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.rating }}"
            },
            {
              "fieldId": "businessStatus",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.businessStatus }}"
            },
            {
              "fieldId": "primaryType",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.primaryType }}"
            },
            {
              "fieldId": "Lantitude",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.latitude }}"
            },
            {
              "fieldId": "Longitude",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.longitude }}"
            },
            {
              "fieldId": "searchLocation",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.searchLocation }}"
            },
            {
              "fieldId": "SearchCategory",
              "fieldValue": "={{ $('5. Loop Through Each Lead').item.json.searchCategory }}"
            }
          ]
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1I9uFYn0q-yBmaGwmN24w6L_1-qjqEVaQj0FwN5RfoFY"
        },
        "credentials": {
          "googleSheetsOAuth2Api": {
            "id": "credential-id",
            "name": "googleSheetsOAuth2Api Credential"
          }
        }
      },
      "typeVersion": 3
    }
  ],
  "connections": {
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "6d. Extract Contact Info with AI",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "3. Parse & Score Leads": {
      "main": [
        [
          {
            "node": "4. Filter High-Quality Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Set Search Parameters": {
      "main": [
        [
          {
            "node": "2. Find Businesses (Google Places)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5. Loop Through Each Lead": {
      "main": [
        [],
        [
          {
            "node": "6a. Scrape Website with Scrape.do",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Filter High-Quality Leads": {
      "main": [
        [
          {
            "node": "5. Loop Through Each Lead",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Report",
            "type": "main",
            "index": 0
          },
          {
            "node": "Error Logging",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6c. Extract Footer from HTML": {
      "main": [
        [
          {
            "node": "6d. Extract Contact Info with AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6d. Extract Contact Info with AI": {
      "main": [
        [
          {
            "node": "7. Save Enriched Lead to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6a. Scrape Website with Scrape.do": {
      "main": [
        [
          {
            "node": "6b. Check if Scrape Was Successful",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2. Find Businesses (Google Places)": {
      "main": [
        [
          {
            "node": "3. Parse & Score Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6b. Check if Scrape Was Successful": {
      "main": [
        [
          {
            "node": "6c. Extract Footer from HTML",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "1. Set Search Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. Save Enriched Lead to Google Sheets": {
      "main": [
        [
          {
            "node": "5. Loop Through Each Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}