AutomationFlowsAI & RAG › Ecotrustia Solutions - Uk Lead Gen + Call Agent

Ecotrustia Solutions - Uk Lead Gen + Call Agent

Ecotrustia Solutions - UK Lead Gen + Call Agent. Uses httpRequest, googleSheets, chainLlm, lmChatAnthropic. Scheduled trigger; 21 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered21 nodesHTTP RequestGoogle SheetsChain LlmAnthropic Chat
AI & RAG Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Chainllm → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Ecotrustia Solutions - UK Lead Gen + Call Agent",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      },
      "id": "node-trigger",
      "name": "Schedule Trigger (Every Monday 9am)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        80,
        300
      ],
      "notes": "Runs the full workflow every Monday at 9am. Change the cron expression to suit your schedule."
    },
    {
      "parameters": {
        "url": "https://maps.googleapis.com/maps/api/place/textsearch/json",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "web design agency London"
            },
            {
              "name": "key",
              "value": "YOUR_GOOGLE_MAPS_API_KEY_HERE"
            },
            {
              "name": "region",
              "value": "uk"
            },
            {
              "name": "language",
              "value": "en"
            }
          ]
        },
        "options": {}
      },
      "id": "node-google-maps",
      "name": "Google Maps - Search UK Businesses",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        300,
        300
      ],
      "notes": "Searches Google Maps for UK businesses. Replace 'web design agency London' with your target niche. Replace YOUR_GOOGLE_MAPS_API_KEY_HERE with your actual API key."
    },
    {
      "parameters": {
        "jsCode": "const results = $input.first().json.results || [];\n\nconst leads = results.map(place => {\n  return {\n    business_name: place.name || '',\n    address: place.formatted_address || '',\n    phone: place.formatted_phone_number || '',\n    rating: place.rating || '',\n    total_ratings: place.user_ratings_total || 0,\n    place_id: place.place_id || '',\n    types: (place.types || []).join(', '),\n    website: '',\n    email: '',\n    website_status: 'Pending',\n    call_status: 'Not Called',\n    client_interested: 'No',\n    notes: ''\n  };\n});\n\nreturn leads.map(lead => ({ json: lead }));"
      },
      "id": "node-extract-fields",
      "name": "Extract Business Fields",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        520,
        300
      ],
      "notes": "Parses each Google Maps result and extracts: business name, address, phone, rating, and place_id. Website and email will be fetched in the next step."
    },
    {
      "parameters": {
        "url": "=https://maps.googleapis.com/maps/api/place/details/json?place_id={{ $json.place_id }}&fields=name,formatted_phone_number,website,formatted_address&key=YOUR_GOOGLE_MAPS_API_KEY_HERE",
        "options": {}
      },
      "id": "node-place-details",
      "name": "Google Maps - Get Place Details (Website + Phone)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        740,
        300
      ],
      "notes": "Fetches detailed info per business including website URL and phone number from Google Places Details API. Replace YOUR_GOOGLE_MAPS_API_KEY_HERE."
    },
    {
      "parameters": {
        "jsCode": "const detail = $input.first().json.result || {};\nconst previous = $('Extract Business Fields').first().json;\n\nreturn [{\n  json: {\n    ...previous,\n    phone: detail.formatted_phone_number || previous.phone || '',\n    website: detail.website || '',\n    email: ''\n  }\n}];"
      },
      "id": "node-merge-details",
      "name": "Merge Place Details into Lead",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        300
      ],
      "notes": "Merges the detailed place info (website, phone) back into the lead object."
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "mode": "id"
        },
        "sheetName": {
          "value": "Leads",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Business Name": "={{ $json.business_name }}",
            "Address": "={{ $json.address }}",
            "Phone": "={{ $json.phone }}",
            "Email": "={{ $json.email }}",
            "Website": "={{ $json.website }}",
            "Rating": "={{ $json.rating }}",
            "Total Reviews": "={{ $json.total_ratings }}",
            "Types": "={{ $json.types }}",
            "Place ID": "={{ $json.place_id }}",
            "Website Status": "={{ $json.website_status }}",
            "Call Status": "={{ $json.call_status }}",
            "Client Interested": "={{ $json.client_interested }}",
            "Notes": "={{ $json.notes }}"
          }
        },
        "options": {}
      },
      "id": "node-save-leads",
      "name": "Google Sheets - Save Leads",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1180,
        300
      ],
      "notes": "Saves all leads to Google Sheet. Replace YOUR_GOOGLE_SHEET_ID_HERE. Create a sheet tab named 'Leads' with all the column headers listed in the _readme section."
    },
    {
      "parameters": {
        "operation": "readRows",
        "documentId": {
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "mode": "id"
        },
        "sheetName": {
          "value": "Leads",
          "mode": "name"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "Website Status",
              "lookupValue": "Pending"
            }
          ]
        },
        "options": {}
      },
      "id": "node-read-pending",
      "name": "Google Sheets - Read Pending Websites",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        300,
        560
      ],
      "notes": "Reads all leads where Website Status is Pending \u2014 these businesses have not been analysed yet."
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "leftValue": "={{ $json.website }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-check-website",
      "name": "Does Website Exist?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        520,
        560
      ],
      "notes": "True branch = has website (go to scraper). False branch = no website (tag directly)."
    },
    {
      "parameters": {
        "url": "={{ $json.website }}",
        "options": {
          "timeout": 10000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "id": "node-scrape-website",
      "name": "HTTP Request - Scrape Website HTML",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        740,
        480
      ],
      "notes": "Fetches the raw HTML of the business website. 10 second timeout."
    },
    {
      "parameters": {
        "jsCode": "const html = $input.first().json.data || '';\n\nconst textContent = html\n  .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n  .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n  .replace(/<[^>]+>/g, ' ')\n  .replace(/\\s+/g, ' ')\n  .trim()\n  .slice(0, 3000);\n\nconst hasContactForm = /contact form|get in touch|send message/i.test(html);\nconst hasMobileTag = /viewport|responsive|mobile/i.test(html);\nconst hasSSL = $('Google Sheets - Read Pending Websites').first().json.Website?.startsWith('https');\nconst copyrightYear = html.match(/copyright[^\\d]*(\\d{4})/i)?.[1] || null;\n\nconst lead = $('Google Sheets - Read Pending Websites').first().json;\n\nreturn [{\n  json: {\n    ...lead,\n    scraped_text: textContent,\n    has_contact_form: hasContactForm,\n    is_mobile_friendly: hasMobileTag,\n    has_ssl: hasSSL,\n    copyright_year: copyrightYear,\n    html_length: html.length\n  }\n}];"
      },
      "id": "node-extract-text",
      "name": "Extract Text + Signals from HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        480
      ],
      "notes": "Strips HTML and extracts readable text (max 3000 chars). Detects: contact form, mobile responsiveness, SSL, and copyright year."
    },
    {
      "parameters": {
        "prompt": "=You are a senior web consultant working for Ecotrustia Solutions, a UK-focused digital agency.\n\nAnalyse the following business website content and provide a professional report.\n\nBusiness Name: {{ $json['Business Name'] || $json.business_name }}\nBusiness Type: {{ $json['Types'] || $json.types }}\nWebsite: {{ $json['Website'] || $json.website }}\nHas SSL (HTTPS): {{ $json.has_ssl }}\nMobile-Friendly Signals: {{ $json.is_mobile_friendly }}\nHas Contact Form: {{ $json.has_contact_form }}\nCopyright Year Detected: {{ $json.copyright_year || 'Not found' }}\nWebsite Text Content (first 3000 chars):\n{{ $json.scraped_text }}\n\nProvide your analysis in the following JSON format ONLY - no extra text, no markdown fences:\n{\n  \"website_grade\": \"Outdated\" or \"Simple\" or \"Good\",\n  \"one_line_summary\": \"One sentence describing the site's current state\",\n  \"strengths\": [\"strength 1\", \"strength 2\"],\n  \"weaknesses\": [\"weakness 1\", \"weakness 2\", \"weakness 3\"],\n  \"recommended_service\": \"Website Redesign or SEO Package or E-commerce Setup or AI Chatbot or Full Digital Package\",\n  \"call_pitch\": \"A natural friendly 2-sentence opening for a phone call mentioning their specific issue and our solution\"\n}"
      },
      "id": "node-basic-llm-chain",
      "name": "Basic LLM Chain",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1,
      "position": [
        1180,
        480
      ],
      "notes": "Executes the Claude AI model."
    },
    {
      "parameters": {
        "model": "claude-3-opus-20240229",
        "options": {}
      },
      "id": "node-claude-analysis",
      "name": "Claude AI - Analyse Website + Generate Pitch",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1,
      "position": [
        1180,
        680
      ],
      "notes": "Sends scraped content to Claude AI. Requires Anthropic API key in n8n credentials."
    },
    {
      "parameters": {
        "jsCode": "const rawText = $input.first().json.text || $input.first().json.content || '';\n\nlet analysis;\ntry {\n  const cleaned = rawText.replace(/```json|```/g, '').trim();\n  analysis = JSON.parse(cleaned);\n} catch(e) {\n  analysis = {\n    website_grade: 'Simple',\n    one_line_summary: 'Website could not be fully analysed.',\n    strengths: [],\n    weaknesses: ['Website could not be fully analysed'],\n    recommended_service: 'Website Redesign',\n    call_pitch: 'Hi, I came across your business online and wanted to discuss how we can help improve your online presence.'\n  };\n}\n\nconst lead = $('Extract Text + Signals from HTML').first().json;\n\nreturn [{\n  json: {\n    ...lead,\n    website_grade: analysis.website_grade,\n    one_line_summary: analysis.one_line_summary,\n    strengths: (analysis.strengths || []).join(' | '),\n    weaknesses: (analysis.weaknesses || []).join(' | '),\n    recommended_service: analysis.recommended_service,\n    call_pitch: analysis.call_pitch,\n    website_status: analysis.website_grade\n  }\n}];"
      },
      "id": "node-parse-analysis",
      "name": "Parse Claude Analysis",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1400,
        480
      ],
      "notes": "Parses Claude's JSON response. Falls back gracefully if JSON is malformed."
    },
    {
      "parameters": {
        "jsCode": "const lead = $('Google Sheets - Read Pending Websites').first().json;\nreturn [{\n  json: {\n    ...lead,\n    website_grade: 'No Website',\n    one_line_summary: 'This business has no website listed.',\n    strengths: '',\n    weaknesses: 'No online presence detected',\n    recommended_service: 'Full Digital Package',\n    call_pitch: 'Hi, I noticed your business does not have a website yet. We help businesses like yours get online quickly with a professional site \u2014 would you have 2 minutes to hear about our packages?',\n    website_status: 'No Website'\n  }\n}];"
      },
      "id": "node-no-website",
      "name": "Tag as No Website",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        740,
        640
      ],
      "notes": "Handles businesses with no website. Assigns a pre-written call pitch for the Full Digital Package."
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "mode": "id"
        },
        "sheetName": {
          "value": "Leads",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Website Status": "={{ $json.website_status || $json.website_grade }}",
            "Notes": "={{ $json.one_line_summary }}",
            "Strengths": "={{ $json.strengths }}",
            "Weaknesses": "={{ $json.weaknesses }}",
            "Recommended Service": "={{ $json.recommended_service }}",
            "Call Pitch": "={{ $json.call_pitch }}"
          }
        },
        "where": {
          "values": [
            {
              "column": "Place ID",
              "value": "={{ $json.place_id || $json['Place ID'] }}"
            }
          ]
        },
        "options": {}
      },
      "id": "node-update-sheet",
      "name": "Google Sheets - Update Website Analysis",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1620,
        560
      ],
      "notes": "Updates the lead row with website grade, summary, strengths, weaknesses, recommended service, and call pitch."
    },
    {
      "parameters": {
        "operation": "readRows",
        "documentId": {
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "mode": "id"
        },
        "sheetName": {
          "value": "Leads",
          "mode": "name"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "Call Status",
              "lookupValue": "Not Called"
            }
          ]
        },
        "options": {}
      },
      "id": "node-read-for-calling",
      "name": "Google Sheets - Read Leads Ready to Call",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        300,
        820
      ],
      "notes": "Reads all leads that have not been called yet. The next node filters out 'Good' websites and leads with no phone number."
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "leftValue": "={{ $json['Website Status'] }}",
              "rightValue": "Good",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            },
            {
              "leftValue": "={{ $json['Phone'] }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-filter-callable",
      "name": "Filter - Has Phone + Not Good Website",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        520,
        820
      ],
      "notes": "Only passes leads that: (1) have a phone number and (2) are graded Outdated, Simple, or No Website. Skips 'Good' websites."
    },
    {
      "parameters": {
        "jsCode": "const lead = $input.first().json;\nconst pitch = lead['Call Pitch'] || lead.call_pitch || 'I came across your business and wanted to discuss improving your online presence.';\nconst service = lead['Recommended Service'] || lead.recommended_service || 'Website Redesign';\n\nconst script = `Hello, may I speak with the business owner or manager please? My name is Ahmed from Ecotrustia Solutions, a digital agency based in the UK. ${pitch} We specialise in ${service} and work with businesses across the United Kingdom. Would you have just 2 minutes to hear how we could help? If now is not a good time, I am happy to call back whenever is convenient. Thank you so much.`;\n\nconst twiml = `<Response><Say voice=\"alice\" language=\"en-GB\">${script}</Say><Pause length=\"2\"/><Say voice=\"alice\" language=\"en-GB\">Press 1 if you are interested in learning more, or simply hang up. Thank you.</Say><Gather numDigits=\"1\" timeout=\"10\" action=\"YOUR_N8N_WEBHOOK_URL\"/></Response>`;\n\nreturn [{\n  json: {\n    ...lead,\n    twiml_script: twiml,\n    phone_to_call: lead['Phone'] || lead.phone || ''\n  }\n}];"
      },
      "id": "node-build-script",
      "name": "Build Twilio Call Script (TwiML)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        740,
        820
      ],
      "notes": "Builds the TwiML call script using Claude's personalised pitch. Uses Alice voice with British English. Press 1 for interest detection. Change 'Ahmed' to your agent name if needed."
    },
    {
      "parameters": {
        "url": "=https://api.twilio.com/2010-04-01/Accounts/YOUR_TWILIO_ACCOUNT_SID_HERE/Calls.json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "method": "POST",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "To",
              "value": "={{ $json.phone_to_call }}"
            },
            {
              "name": "From",
              "value": "YOUR_TWILIO_UK_NUMBER_HERE"
            },
            {
              "name": "Twiml",
              "value": "={{ $json.twiml_script }}"
            }
          ]
        },
        "options": {}
      },
      "id": "node-twilio-call",
      "name": "Twilio - Make Outbound Call",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        820
      ],
      "notes": "Makes the outbound call via Twilio REST API. Replace: YOUR_TWILIO_ACCOUNT_SID_HERE, YOUR_TWILIO_UK_NUMBER_HERE. Add Twilio Basic Auth credentials (Account SID as username, Auth Token as password) in n8n HTTP Request credentials."
    },
    {
      "parameters": {
        "jsCode": "const callResponse = $input.first().json;\nconst lead = $('Build Twilio Call Script (TwiML)').first().json;\n\nreturn [{\n  json: {\n    ...lead,\n    call_sid: callResponse.sid || 'UNKNOWN',\n    call_status: 'Called',\n    call_timestamp: new Date().toISOString()\n  }\n}];"
      },
      "id": "node-log-call",
      "name": "Log Call SID + Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1180,
        820
      ],
      "notes": "Captures the Twilio Call SID and timestamps the call."
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "mode": "id"
        },
        "sheetName": {
          "value": "Leads",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Call Status": "Called",
            "Call SID": "={{ $json.call_sid }}",
            "Call Timestamp": "={{ $json.call_timestamp }}"
          }
        },
        "where": {
          "values": [
            {
              "column": "Place ID",
              "value": "={{ $json.place_id || $json['Place ID'] }}"
            }
          ]
        },
        "options": {}
      },
      "id": "node-update-call-status",
      "name": "Google Sheets - Update Call Status",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1400,
        820
      ],
      "notes": "Marks lead as 'Called' and records the Twilio Call SID and timestamp. Prevents duplicate calls on next run."
    }
  ],
  "connections": {
    "Schedule Trigger (Every Monday 9am)": {
      "main": [
        [
          {
            "node": "Google Maps - Search UK Businesses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Maps - Search UK Businesses": {
      "main": [
        [
          {
            "node": "Extract Business Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Business Fields": {
      "main": [
        [
          {
            "node": "Google Maps - Get Place Details (Website + Phone)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Maps - Get Place Details (Website + Phone)": {
      "main": [
        [
          {
            "node": "Merge Place Details into Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Place Details into Lead": {
      "main": [
        [
          {
            "node": "Google Sheets - Save Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets - Save Leads": {
      "main": [
        [
          {
            "node": "Google Sheets - Read Pending Websites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets - Read Pending Websites": {
      "main": [
        [
          {
            "node": "Does Website Exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Does Website Exist?": {
      "main": [
        [
          {
            "node": "HTTP Request - Scrape Website HTML",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Tag as No Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request - Scrape Website HTML": {
      "main": [
        [
          {
            "node": "Extract Text + Signals from HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text + Signals from HTML": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "Parse Claude Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude AI - Analyse Website + Generate Pitch": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Claude Analysis": {
      "main": [
        [
          {
            "node": "Google Sheets - Update Website Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tag as No Website": {
      "main": [
        [
          {
            "node": "Google Sheets - Update Website Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets - Update Website Analysis": {
      "main": [
        [
          {
            "node": "Google Sheets - Read Leads Ready to Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets - Read Leads Ready to Call": {
      "main": [
        [
          {
            "node": "Filter - Has Phone + Not Good Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter - Has Phone + Not Good Website": {
      "main": [
        [
          {
            "node": "Build Twilio Call Script (TwiML)",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Build Twilio Call Script (TwiML)": {
      "main": [
        [
          {
            "node": "Twilio - Make Outbound Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Twilio - Make Outbound Call": {
      "main": [
        [
          {
            "node": "Log Call SID + Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Call SID + Status": {
      "main": [
        [
          {
            "node": "Google Sheets - Update Call Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "staticData": null,
  "tags": [
    {
      "name": "Ecotrustia Solutions"
    },
    {
      "name": "Lead Generation"
    },
    {
      "name": "UK Outreach"
    },
    {
      "name": "Twilio Call Agent"
    }
  ],
  "_readme": {
    "workflow_name": "Ecotrustia Solutions - UK Lead Gen + Call Agent",
    "version": "1.0",
    "author": "Ahmed Ali Jawad - Ecotrustia Solutions",
    "stages": {
      "stage_1": "Google Maps API \u2192 Extract fields \u2192 Google Sheets save",
      "stage_2": "Read pending leads \u2192 Scrape website \u2192 Claude AI analysis \u2192 Update sheet",
      "stage_3": "Read callable leads \u2192 Build TwiML \u2192 Twilio call \u2192 Log \u2192 Flag interested \u2192 Send email"
    },
    "THINGS_TO_REPLACE": {
      "YOUR_GOOGLE_SHEET_ID_HERE": "Find this in your Google Sheet URL: docs.google.com/spreadsheets/d/THIS_PART/edit",
      "YOUR_GOOGLE_MAPS_API_KEY_HERE": "Google Cloud Console \u2192 Enable Places API \u2192 Create API Key",
      "YOUR_TWILIO_ACCOUNT_SID_HERE": "Twilio Console \u2192 Account Info \u2192 Account SID",
      "YOUR_TWILIO_UK_NUMBER_HERE": "Twilio Console \u2192 Phone Numbers \u2192 your UK number e.g. +441234567890"
    },
    "CREDENTIALS_TO_ADD_IN_N8N": [
      "Google Maps: HTTP Request with API key as query param",
      "Google Sheets: OAuth2 (sign in with Google)",
      "Anthropic: API Key (for Claude AI node)",
      "Twilio: HTTP Basic Auth (Account SID as user, Auth Token as password)",
      "Gmail: OAuth2 (sign in with Google)"
    ],
    "GOOGLE_SHEET_COLUMNS": [
      "Business Name",
      "Address",
      "Phone",
      "Email",
      "Website",
      "Rating",
      "Total Reviews",
      "Types",
      "Place ID",
      "Website Status",
      "Call Status",
      "Client Interested",
      "Notes",
      "Strengths",
      "Weaknesses",
      "Recommended Service",
      "Call Pitch",
      "Call SID",
      "Call Timestamp"
    ],
    "WEBSITE_STATUS_VALUES": [
      "Pending",
      "Outdated",
      "Simple",
      "Good",
      "No Website"
    ],
    "CALL_STATUS_VALUES": [
      "Not Called",
      "Called"
    ],
    "CLIENT_INTERESTED_VALUES": [
      "No",
      "Yes"
    ]
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Ecotrustia Solutions - UK Lead Gen + Call Agent. Uses httpRequest, googleSheets, chainLlm, lmChatAnthropic. Scheduled trigger; 21 nodes.

Source: https://github.com/ahmed-ali-codes/n8n-leadgen-call-agent/blob/main/ecotrustia_n8n_workflow.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This n8n workflow allows you to automatically archive your monthly Spotify liked tracks in a Google Sheet, along with playlist details and descriptions. Based on this data, Claude 3.5 is used to class

HTTP Request, Anthropic Chat, Spotify +3
AI & RAG

Monthly Spotify Track Archiving and Playlist Classification. Uses httpRequest, lmChatAnthropic, spotify, outputParserStructured. Scheduled trigger; 37 nodes.

HTTP Request, Anthropic Chat, Spotify +3
AI & RAG

🚀 Create Pro-Level Social Media Carousels & Auto-Publish with Blotato Who is this for?

Google Sheets, Jina Ai, HTTP Request +4
AI & RAG

This workflow runs on a frequent schedule to check UptimeRobot monitor status and a Google PageSpeed Insights test, logs monitor data to Google Sheets, and sends uptime or downtime notifications via G

Google Sheets, Chain Llm, HTTP Request +5
AI & RAG

This scheduled workflow pulls article URLs from Google Sheets, scrapes each page, uses Anthropic Claude to generate a structured news briefing, saves results to Notion, posts a compiled digest to Slac

Google Sheets, HTTP Request, Chain Llm +3