{
  "nodes": [
    {
      "id": "316ef0ee-8231-4100-a13f-485c1864739b",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -672,
        144
      ],
      "parameters": {
        "options": {},
        "formTitle": "Local Biz Search",
        "formFields": {
          "values": [
            {
              "fieldLabel": "query",
              "requiredField": true
            },
            {
              "fieldLabel": "city",
              "requiredField": true
            },
            {
              "fieldLabel": "country code"
            },
            {
              "fieldLabel": "number"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "35313607-94c3-4a7b-8bf4-f65f618db86e",
      "name": "Scrape Google Maps",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -448,
        144
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/compass~crawler-google-places/run-sync-get-dataset-items",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"city\": \"{{ $json.city }}\",\n    \"countryCode\": \"{{ $json['country code'] }}\",\n    \"locationQuery\": \"{{ $json.city }}\",\n    \"maxCrawledPlacesPerSearch\":{{ $json.number ? $json.number : 99999 }},\n    \"searchStringsArray\": [\n        \"{{ $json.query }}\"\n    ],\n    \"skipClosedPlaces\": true\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth"
      },
      "credentials": {
        "httpQueryAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9ef55da1-0d8f-4665-b702-ef66af067987",
      "name": "Get Emails",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        416,
        240
      ],
      "parameters": {
        "url": "https://api.anymailfinder.com/v5.1/find-email/company",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "=domain",
              "value": "={{ $json.domain}}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.2
    },
    {
      "id": "7a1cb6ab-20ed-4ba9-acb3-25af2b8ca995",
      "name": "Extract data",
      "type": "n8n-nodes-base.set",
      "position": [
        0,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "53d8d9b3-40ac-4a01-ae31-fb6233ba1c53",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "ecc7c3ee-20f0-43c9-a489-05467e521212",
              "name": "address",
              "type": "string",
              "value": "={{ $json.address }}"
            },
            {
              "id": "ecdea9cb-3ae7-4229-9a5b-d9dbd4ee3b35",
              "name": "neighborhood",
              "type": "string",
              "value": "={{ $json.neighborhood }}"
            },
            {
              "id": "f01a74a8-ff34-458b-900a-18da2ee41091",
              "name": "website",
              "type": "string",
              "value": "={{ $json.website }}"
            },
            {
              "id": "a1416416-e378-45a5-85d4-50eed6a6683c",
              "name": "phone",
              "type": "string",
              "value": "={{ $json.phone }}"
            },
            {
              "id": "6f0980ba-8964-40fd-a4ce-6cbb780bf10d",
              "name": "totalScore",
              "type": "number",
              "value": "={{ $json.totalScore }}"
            },
            {
              "id": "cd70afef-02bf-4bff-a9c3-1270c9c54140",
              "name": "subTitle",
              "type": "string",
              "value": "={{ $json.subTitle }}"
            },
            {
              "id": "4d9f6e00-364f-4da5-a27d-3c3c740da535",
              "name": "categories",
              "type": "string",
              "value": "={{ $json.categories.join(\",\") }}"
            },
            {
              "id": "abcc7074-dd5c-4441-8644-a4ba59844630",
              "name": "city",
              "type": "string",
              "value": "={{ $json.city }}"
            },
            {
              "id": "bba8f41d-a20e-4a50-82e9-25d00b69aef6",
              "name": "countryCode",
              "type": "string",
              "value": "={{ $json.countryCode }}"
            },
            {
              "id": "fb5f656a-a94a-44c9-8bf8-70d64e47102e",
              "name": "postalCode",
              "type": "string",
              "value": "={{ $json.postalCode }}"
            },
            {
              "id": "cbc7560f-2bef-451f-92b6-d1efeb17c49e",
              "name": "placeId",
              "type": "string",
              "value": "={{ $json.placeId }}"
            },
            {
              "id": "5c5945cd-763c-4505-b7b9-ab57f10747ba",
              "name": "date",
              "type": "string",
              "value": "={{ $json.scrapedAt.toDateTime().format('dd/LL/yyyy') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "547152fc-4375-4239-98ec-7e9df4091297",
      "name": "Extract Emails",
      "type": "n8n-nodes-base.set",
      "position": [
        576,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4eadc93e-4897-4467-965e-3d1b59b17739",
              "name": "emails",
              "type": "string",
              "value": "={{ $json.emails.join(\",\") }}"
            },
            {
              "id": "e8ac106b-19f9-4a2c-aab4-25d19a6986c5",
              "name": "email_status",
              "type": "string",
              "value": "={{ $json.email_status }}"
            },
            {
              "id": "50977992-7cca-4e8d-940e-a290ab292390",
              "name": "domain",
              "type": "string",
              "value": "={{ $json.input.domain }}"
            },
            {
              "id": "cce9c672-4cf8-4f98-8a3d-24f49ba2f13a",
              "name": "title",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.title }}"
            },
            {
              "id": "ec0c8aff-a80f-4f1c-9760-cfa23f3061f0",
              "name": "address",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.address }}"
            },
            {
              "id": "640819a4-ba76-4afd-ba17-9907a5b9992b",
              "name": "neighborhood",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.neighborhood }}"
            },
            {
              "id": "ccdc11b2-60fe-4eeb-b4f7-7895c9eeafa3",
              "name": "website",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.website }}"
            },
            {
              "id": "5108364b-fd20-4b43-9836-87ba3668b421",
              "name": "phone",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.phone }}"
            },
            {
              "id": "207d465f-0a64-4caa-ab1f-fa5baeb797f7",
              "name": "totalScore",
              "type": "number",
              "value": "={{ $('Filter items with domain').item.json.totalScore }}"
            },
            {
              "id": "a3369776-9668-4b6e-8492-7a8422f47d72",
              "name": "categories",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.categories }}"
            },
            {
              "id": "005fb833-719c-4f52-afed-3a44ab94d6cf",
              "name": "city",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.city }}"
            },
            {
              "id": "d22aa27a-a622-48a7-8e94-45d722904efd",
              "name": "countryCode",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.countryCode }}"
            },
            {
              "id": "7ae6c4d8-7fef-4857-a48a-ccc780bafcfa",
              "name": "postalCode",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.postalCode }}"
            },
            {
              "id": "1849ec06-87b0-480c-808b-b369dd6470a6",
              "name": "date",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.date }}"
            },
            {
              "id": "f88d7e6c-9d87-4994-975f-547a24621cba",
              "name": "placeId",
              "type": "string",
              "value": "={{ $('Filter items with domain').item.json.placeId }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "894a2068-3455-45c9-85ba-6e74d5ae350a",
      "name": "Clean Data",
      "type": "n8n-nodes-base.code",
      "position": [
        224,
        0
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const j = item.json || {};\n  const original = j.website || null;\n\n  let website_root = null;\n  let domain = null;\n  let domain_strategy = 'none';\n\n  if (original && typeof original === 'string') {\n    let urlStr = original.trim();\n\n    // Add protocol if missing\n    if (!/^https?:\\/\\//i.test(urlStr)) {\n      urlStr = 'https://' + urlStr;\n    }\n\n    try {\n      const urlObj = new URL(urlStr);\n      website_root = `${urlObj.protocol}//${urlObj.host}`;\n      domain = urlObj.host.toLowerCase();\n      domain_strategy = 'site_host';\n    } catch (e) {\n      // fallback if URL is malformed\n      website_root = urlStr.split('?')[0];\n      const match = website_root.match(/^https?:\\/\\/([^\\/]+)/i);\n      if (match) {\n        domain = match[1].toLowerCase();\n        domain_strategy = 'site_host_fallback';\n      }\n    }\n  }\n\n  // Remove \"www.\" prefix\n  if (domain && domain.startsWith('www.')) {\n    domain = domain.slice(4);\n  }\n\n  // Exclude social networks\n  const SOCIAL_HOSTS = [\n    'facebook.com', 'instagram.com', 'linktr.ee', 'twitter.com', 'google.com', 'youtube.com'\n  ];\n  if (domain && SOCIAL_HOSTS.some(h => domain.endsWith(h))) {\n    domain = null;\n    domain_strategy = 'social';\n  }\n\n  // Output\n  j.website_root = website_root;\n  j.domain = domain;\n  j.domain_strategy = domain_strategy;\n  if (website_root) j.website = website_root;\n\n  item.json = j;\n  return item;\n});\n\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "513cfe88-27ec-4cd1-a10e-772859d392b9",
      "name": "Avoid duplicates",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        0
      ],
      "parameters": {
        "jsCode": "const allPlaceIds = $('Get all the recorded placeIds').all().map(item => item.json.placeId);\nconst scrapedItems = $('Clean Data').all().map(item => item.json);\n\n// keep only items with a new placeId\nconst filtered = scrapedItems.filter(item => item.placeId && !allPlaceIds.includes(item.placeId));\n\n// return each as its own item\nreturn filtered.map(item => ({ json: item }));\n"
      },
      "executeOnce": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "bcbff4a5-67da-4dae-b630-64067ab8a0e9",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        736,
        416
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "5fe49b72-c966-4c71-8d0e-59f7f8e3c7c4",
      "name": "Filter items with domain",
      "type": "n8n-nodes-base.if",
      "position": [
        208,
        256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "dc9c506d-8615-4383-9fd4-8e94ed280738",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.domain }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e20270dd-cb66-4e95-b4cb-2bb837d54d92",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -224,
        144
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "a826f0ea-ab1c-4ac1-ba71-f9338a276fce",
      "name": "Get all the recorded placeIds",
      "type": "n8n-nodes-base.nocoDb",
      "position": [
        448,
        0
      ],
      "parameters": {
        "table": "m8xjj32j1tvty0z",
        "options": {
          "where": "=(placeId,eq,{{ $json.placeId }})"
        },
        "operation": "getAll",
        "projectId": "p75lcduba1trkxn",
        "returnAll": true,
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "a9e1eeb5-6e95-44fb-bee5-b637446a876b",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        288
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "490232c7-e1c3-43e6-a13c-b7e8ada04272",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.placeId }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "dbeadea9-956c-4e40-b4ce-0ae4103adfad",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -48
      ],
      "parameters": {
        "color": 4,
        "height": 352,
        "content": "## Apify Google Maps Scraper\nhttps://console.apify.com/actors/nwua9Gu5YrADL7ZDj/input"
      },
      "typeVersion": 1
    },
    {
      "id": "1ff8f9b0-da34-43b0-ae42-7c1e007bbbc9",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -208
      ],
      "parameters": {
        "color": 4,
        "height": 352,
        "content": "## Remove wrong URLs, and clean extensions"
      },
      "typeVersion": 1
    },
    {
      "id": "c2a8e787-73ef-4ad6-8981-5aac3939f14f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        416,
        -208
      ],
      "parameters": {
        "color": 4,
        "width": 352,
        "height": 352,
        "content": "## Avoid Duplicating Items from the DB"
      },
      "typeVersion": 1
    },
    {
      "id": "015b723b-8835-4106-88dc-14a877f02758",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        416
      ],
      "parameters": {
        "color": 4,
        "width": 272,
        "height": 240,
        "content": "## If the item already exists we go to the next one in the loop\n\n\n\n\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "090bd8b5-170f-4362-a3df-0db32d780760",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        400
      ],
      "parameters": {
        "color": 4,
        "width": 352,
        "height": 352,
        "content": "## If we have a domain we search the emails with anymailfinder\n- check if we have a domain\n- Yes: search for the email then merge the email with the rest of the data\n- No: Go to the merge node directly"
      },
      "typeVersion": 1
    },
    {
      "id": "4d4dd550-c34c-49de-a0f6-ace20643ed06",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        288
      ],
      "parameters": {
        "color": 4,
        "height": 352,
        "content": "## Record the item into the NocoDB and go to the next Item"
      },
      "typeVersion": 1
    },
    {
      "id": "71e493fe-1023-463f-92cd-62db77fa32de",
      "name": "Create a row",
      "type": "n8n-nodes-base.nocoDb",
      "position": [
        928,
        416
      ],
      "parameters": {
        "table": "m8xjj32j1tvty0z",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "title",
              "fieldValue": "={{ $json.title }}"
            },
            {
              "fieldName": "website",
              "fieldValue": "={{ $json.website }}"
            },
            {
              "fieldName": "phone",
              "fieldValue": "={{ $json.phone }}"
            },
            {
              "fieldName": "email",
              "fieldValue": "={{ $json.emails }}"
            },
            {
              "fieldName": "email_validation",
              "fieldValue": "={{ $json.email_status }}"
            },
            {
              "fieldName": "address",
              "fieldValue": "={{ $json.address }}"
            },
            {
              "fieldName": "neighborhood",
              "fieldValue": "={{ $json.neighborhood }}"
            },
            {
              "fieldName": "rating",
              "fieldValue": "={{ $json.totalScore }}"
            },
            {
              "fieldName": "categories",
              "fieldValue": "={{ $('Filter items with domain').item.json.categories }}"
            },
            {
              "fieldName": "city",
              "fieldValue": "={{ $('Filter items with domain').item.json.city }}"
            },
            {
              "fieldName": "country",
              "fieldValue": "={{ $('Filter items with domain').item.json.countryCode }}"
            },
            {
              "fieldName": "postal code",
              "fieldValue": "={{ $('Filter items with domain').item.json.postalCode }}"
            },
            {
              "fieldName": "domain",
              "fieldValue": "={{ $('Filter items with domain').item.json.domain }}"
            },
            {
              "fieldName": "placeId",
              "fieldValue": "={{ $json.placeId }}"
            },
            {
              "fieldName": "date",
              "fieldValue": "={{ $json.date }}"
            }
          ]
        },
        "operation": "create",
        "projectId": "p75lcduba1trkxn",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "8fff3b18-234a-44d2-9fae-8672d9259afb",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -352
      ],
      "parameters": {
        "content": "## Links \n[Anymailfinder](https://anymailfinder.com?via=alexandra)\n[Apify](https://www.apify.com?fpr=g5q0f)\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Filter items with domain",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Create a row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Data": {
      "main": [
        [
          {
            "node": "Get all the recorded placeIds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Emails": {
      "main": [
        [
          {
            "node": "Extract Emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a row": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract data": {
      "main": [
        [
          {
            "node": "Clean Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Emails": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Extract data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Avoid duplicates": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Scrape Google Maps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Google Maps": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter items with domain": {
      "main": [
        [
          {
            "node": "Get Emails",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get all the recorded placeIds": {
      "main": [
        [
          {
            "node": "Avoid duplicates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}