AutomationFlowsWeb Scraping › Aw-1: Demo Build Trigger (phase 1 - Manual)

Aw-1: Demo Build Trigger (phase 1 - Manual)

AW-1: Demo Build Trigger (Phase 1 - Manual). Uses httpRequest. Webhook trigger; 10 nodes.

Webhook trigger★★★★☆ complexity10 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 10 Complexity: ★★★★☆ Added:

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": "AW-1: Demo Build Trigger (Phase 1 - Manual)",
  "nodes": [
    {
      "id": "webhook-trigger",
      "name": "Webhook: Close Lead Updated",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "aw-demo-trigger",
        "options": {}
      }
    },
    {
      "id": "filter-and-build",
      "name": "Code: Filter + Build Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        300
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 Phase 1 manual trigger (idempotent) \u2500\u2500\n//   Fire if ALL of:\n//   - Demo Send field was in this update's changed_fields\n//   - Current Demo Send is \"True\"\n//   - cf_demo_sent_at is empty (OR Rebuild is \"Yes\")\n//   This avoids the Close-batching edge case where rapid False\u2192True\n//   gets de-duped into previous=current=True.\n\nvar webhookBody = $('Webhook: Close Lead Updated').first().json.body || {};\nvar event = webhookBody.event || webhookBody;\nvar webhookData = event.data || {};\nvar changedFields = event.changed_fields || [];\n\nvar lead = $('Close: Get Full Lead').first().json || {};\nvar cf = lead.custom || {};\n\nvar KEY_SEND = 'custom.cf_MuBbV1mNj2o47xuMYhTyVYaqwaqaban5s8wxkeYdvZf';\n\n// 1. Demo Send must have been touched in this update\nvar demoSendTouched = changedFields.indexOf(KEY_SEND) >= 0;\nif (!demoSendTouched) return [];\n\n// 2. Current value must be \"True\" (read from fresh lead, by NAME)\nif (cf['Website Demo - Send'] !== 'True') return [];\n\n// 3. Skip if already sent (unless explicit rebuild)\nvar alreadySent = !!cf['Website Demo - Sent At'];\nvar isRebuild = (cf['Website Demo - Rebuild'] === 'Yes');\nif (alreadySent && !isRebuild) return [];\n\n// 4. Niche normalization \u2014 Google Places categories often use verbose names.\n// Order = MOST SPECIFIC FIRST. \"road construction company\" must be caught\n// before generic \"construction\", and \"dock builder\" before \"deck\" (they\n// share no letters but both are contractor types).\nvar rawNiche = String(cf['Niche'] || '').toLowerCase();\nvar niche = 'plumbing';\n\n// Compound / disambiguating matches (must run before generic ones)\nif (rawNiche.indexOf('road construction') >= 0) niche = 'paving';\nelse if (rawNiche.indexOf('dock builder') >= 0) niche = 'deck-builder';\nelse if (rawNiche.indexOf('excavat') >= 0) niche = 'foundation-repair';\nelse if (rawNiche.indexOf('bathroom remodel') >= 0) niche = 'remodeling';\n\n// Original substring matches\nelse if (rawNiche.indexOf('roof') >= 0) niche = 'roofing';\nelse if (rawNiche.indexOf('hvac') >= 0) niche = 'hvac';\nelse if (rawNiche.indexOf('electric') >= 0) niche = 'electrician';\nelse if (rawNiche.indexOf('landscap') >= 0) niche = 'landscaping';\nelse if (rawNiche.indexOf('tree') >= 0) niche = 'tree-service';\nelse if (rawNiche.indexOf('pool') >= 0) niche = 'pool-installation';\nelse if (rawNiche.indexOf('fenc') >= 0) niche = 'fencing';\nelse if (rawNiche.indexOf('deck') >= 0) niche = 'deck-builder';\nelse if (rawNiche.indexOf('garage') >= 0) niche = 'garage-door';\nelse if (rawNiche.indexOf('septic') >= 0) niche = 'septic-service';\nelse if (rawNiche.indexOf('concrete') >= 0) niche = 'concrete';\nelse if (rawNiche.indexOf('foundation') >= 0) niche = 'foundation-repair';\nelse if (rawNiche.indexOf('pav') >= 0) niche = 'paving';\nelse if (rawNiche.indexOf('press') >= 0) niche = 'pressure-washing';\nelse if (rawNiche.indexOf('junk') >= 0 || rawNiche.indexOf('haul') >= 0) niche = 'junk-removal';\nelse if (rawNiche.indexOf('remodel') >= 0 || rawNiche.indexOf('renov') >= 0) niche = 'remodeling';\nelse if (rawNiche.indexOf('contractor') >= 0) niche = 'general-contractor';\nelse if (rawNiche.indexOf('construction') >= 0) niche = 'general-contractor';  // catches \"Construction company\", \"General Construction\"\nelse if (rawNiche.indexOf('plumb') >= 0) niche = 'plumbing';\n\n// 5. Phone from contacts (lead's real phone)\nvar phone = '';\nif (lead.contacts && lead.contacts.length > 0) {\n  for (var i = 0; i < lead.contacts.length; i++) {\n    var c = lead.contacts[i];\n    if (c.phones && c.phones.length > 0 && c.phones[0].phone) {\n      phone = c.phones[0].phone;\n      break;\n    }\n  }\n}\nif (!phone) phone = cf['Send Number'] || '';\nif (!phone) return [];\n\n// 6. City/State/ZIP \u2014 parse Address as fallback\nvar city = cf['City'] || '';\nvar state = cf['State'] || '';\nvar zipCode = cf['ZIP'] || '';\nvar street = '';\nvar fullAddr = String(cf['Address'] || '').trim();\nif ((!city || !state || !zipCode) && fullAddr) {\n  var m = fullAddr.match(/^(?:(.+?),\\s*)?([A-Za-z][A-Za-z .'-]+?),\\s*([A-Z]{2})\\s+(\\d{5}(?:-\\d{4})?)/);\n  if (m) {\n    street  = street  || m[1] || '';\n    city    = city    || m[2] || '';\n    state   = state   || m[3] || '';\n    zipCode = zipCode || m[4] || '';\n  } else {\n    var loose = fullAddr.match(/^([A-Za-z][A-Za-z .'-]+?),\\s*([A-Z]{2})\\s+(\\d{5})/);\n    if (loose) {\n      city    = city    || loose[1] || '';\n      state   = state   || loose[2] || '';\n      zipCode = zipCode || loose[3] || '';\n    }\n  }\n}\nif (!city) return [];\n\nreturn [{\n  json: {\n    leadId: lead.id,\n    niche: niche,\n    businessInfo: {\n      name: lead.display_name || lead.name,\n      phone: phone,\n      address: street || fullAddr,\n      city: city,\n      state: state || 'US',\n      zip: zipCode,\n      services: [],\n      rating: cf['Google Rating'] ? parseFloat(cf['Google Rating']) : undefined,\n      reviewCount: cf['Google Reviews'] ? parseInt(cf['Google Reviews']) : undefined\n    }\n  }\n}];"
      }
    },
    {
      "id": "call-build-api",
      "name": "HTTP: Build Demo API",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://YOUR_APP_HOST/api/build-demo",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json) }}",
        "options": {
          "timeout": 30000
        }
      }
    },
    {
      "id": "if-success",
      "name": "IF: Build Success?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "cond-success",
              "leftValue": "={{ $json.success }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "send-demo-sms",
      "name": "Close: Send Demo SMS",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1320,
        200
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.close.com/api/v1/activity/sms/",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic YOUR_BASIC_AUTH"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"lead_id\": \"{{ $('Code: Filter + Build Payload').first().json.leadId }}\",\n  \"local_phone\": \"{{ ($('Close: Get Last Outbound SMS').first().json.data && $('Close: Get Last Outbound SMS').first().json.data.length > 0) ? $('Close: Get Last Outbound SMS').first().json.data[0].local_phone : '+15555550100' }}\",\n  \"remote_phone\": \"{{ $('Code: Filter + Build Payload').first().json.businessInfo.phone }}\",\n  \"text\": \"More leads More creditability\\n\\n{{ $('HTTP: Build Demo API').first().json.demoUrl }}\\n\\nOnline presence is more important than ever!\\n\\nRemeber this is a demo any text you want changed we can do it!\\n\\nWhat do you think?\",\n  \"status\": \"outbox\"\n}"
      },
      "disabled": false
    },
    {
      "id": "mark-sent",
      "name": "Close: Mark Demo Sent",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        200
      ],
      "parameters": {
        "method": "PUT",
        "url": "=https://api.close.com/api/v1/lead/{{ $('Code: Filter + Build Payload').first().json.leadId }}/",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic YOUR_BASIC_AUTH"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"custom.cf_RJaIZqW4kmINDhKvOWUSRe9IZ87VBPFkdGYyzwLSh6w\": \"{{ $now.toISO() }}\",\n  \"custom.cf_CLBEEeGPX116lRecdaQX3Zht4Ex0XiCNkLT7BPJlu0Q\": \"{{ $('HTTP: Build Demo API').first().json.slug }}\",\n  \"custom.cf_PtpuFWgtGXpYyV5jjv5HOcPIPRulMAKjSgGwwZ4din5\": \"No\",\n  \"custom.cf_JJr3nY7RiBitSqZ3ARqmKGGXCH8517mcnL2D8QLKMIn\": \"No\"\n}"
      },
      "disabled": false
    },
    {
      "id": "log-error",
      "name": "NoOp: Log Failure",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1120,
        400
      ],
      "parameters": {}
    },
    {
      "id": "get-last-sms",
      "name": "Close: Get Last Outbound SMS",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1100,
        200
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.close.com/api/v1/activity/sms/?lead_id={{ $('Code: Filter + Build Payload').first().json.leadId }}&direction=outbound&_order_by=-date_created&_limit=1&_fields=id,local_phone,date_created",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic YOUR_BASIC_AUTH"
            }
          ]
        },
        "options": {
          "timeout": 15000
        }
      }
    },
    {
      "id": "get-full-lead",
      "name": "Close: Get Full Lead",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        380,
        300
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.close.com/api/v1/lead/{{ $('Webhook: Close Lead Updated').first().json.body.event.lead_id }}/",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic YOUR_BASIC_AUTH"
            }
          ]
        },
        "options": {
          "timeout": 15000
        }
      }
    },
    {
      "id": "mark-sms-sent",
      "name": "Convex: Mark SMS Sent",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1760,
        200
      ],
      "parameters": {
        "method": "POST",
        "url": "https://YOUR_APP_HOST/api/mark-sms-sent",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_API_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"slug\": \"{{ $('HTTP: Build Demo API').first().json.slug }}\",\n  \"smsSentAt\": {{ $now.toMillis() }},\n  \"remotePhone\": \"{{ $('Code: Filter + Build Payload').first().json.businessInfo.phone }}\",\n  \"localPhone\": \"{{ ($('Close: Get Last Outbound SMS').first().json.data && $('Close: Get Last Outbound SMS').first().json.data.length > 0) ? $('Close: Get Last Outbound SMS').first().json.data[0].local_phone : '+15555550100' }}\"\n}",
        "options": {
          "timeout": 15000
        }
      }
    }
  ],
  "connections": {
    "Webhook: Close Lead Updated": {
      "main": [
        [
          {
            "node": "Close: Get Full Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Close: Get Full Lead": {
      "main": [
        [
          {
            "node": "Code: Filter + Build Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Filter + Build Payload": {
      "main": [
        [
          {
            "node": "HTTP: Build Demo API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: Build Demo API": {
      "main": [
        [
          {
            "node": "IF: Build Success?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF: Build Success?": {
      "main": [
        [
          {
            "node": "Close: Get Last Outbound SMS",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "NoOp: Log Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Close: Get Last Outbound SMS": {
      "main": [
        [
          {
            "node": "Close: Send Demo SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Close: Send Demo SMS": {
      "main": [
        [
          {
            "node": "Convex: Mark SMS Sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convex: Mark SMS Sent": {
      "main": [
        [
          {
            "node": "Close: Mark Demo Sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "active": false
}
Pro

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

About this workflow

AW-1: Demo Build Trigger (Phase 1 - Manual). Uses httpRequest. Webhook trigger; 10 nodes.

Source: https://github.com/rafiulislam4246/auto-website-sell-workflows/blob/main/workflows/01-demo-build-trigger.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.

HTTP Request
Web Scraping

This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia

HTTP Request
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request