AutomationFlowsAI & RAG › Restaurant Lead Generation From Google Maps with Apify, Airtable & AI Newsletter

Restaurant Lead Generation From Google Maps with Apify, Airtable & AI Newsletter

ByPramod Rathoure @prathoure on n8n.io

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Event trigger★★★★☆ complexityAI-powered21 nodes@Apify/N8N Nodes ApifyOpenAI ChatGmailForm TriggerAgentOutput Parser StructuredAirtable
AI & RAG Trigger: Event Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #7877 — we link there as the canonical source.

This workflow follows the Agent → Airtable 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
{
  "id": "SmZMmSHj4zgfFxLd",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "My workflow 2",
  "tags": [],
  "nodes": [
    {
      "id": "47d0ec85-60df-40f4-bb4d-2c8409a4475e",
      "name": "Run an Actor",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        -940,
        580
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "nwua9Gu5YrADL7ZDj",
          "cachedResultUrl": "https://console.apify.com/actors/nwua9Gu5YrADL7ZDj/input",
          "cachedResultName": "Google Maps Scraper (compass/crawler-google-places)"
        },
        "customBody": "={\n    \"includeWebResults\": false,\n    \"language\": \"en\",\n    \"locationQuery\": \"{{ $json.Location }}\",\n    \"maxCrawledPlacesPerSearch\":{{ $json['Number of Items to be Scraped'] }} ,\n    \"maxImages\": 0,\n    \"maximumLeadsEnrichmentRecords\": 0,\n    \"scrapeContacts\": true,\n    \"scrapeDirectories\": true,\n    \"scrapeImageAuthors\": false,\n    \"scrapePlaceDetailPage\": true,\n    \"scrapeReviewsPersonalData\": true,\n    \"scrapeTableReservationProvider\": true,\n    \"searchStringsArray\": [\n        \"{{ $json['What to Scrape'] }}\"\n    ],\n    \"skipClosedPlaces\": true\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "49cc3b8a-c690-41a7-8d7c-f43fdaae7a5b",
      "name": "Get dataset items",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        -460,
        500
      ],
      "parameters": {
        "resource": "Datasets",
        "datasetId": "={{ $json.defaultDatasetId }}"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "88d53e9c-9bb4-4fbb-a5ff-f4c01de9c558",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -740,
        580
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7147dfa1-335a-46a4-b257-3cebbeb40956",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "=SUCCEEDED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1b2c0bec-5e07-4912-b9c6-340bc5dbe989",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -360,
        760
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "1586395a-9c66-4a8f-a51b-b019e3f771f3",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        480,
        380
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "Restaurant_Data"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ad264dc3-eb93-42a3-9c0b-7275257a32fd",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        640,
        640
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "47e9b471-1cd5-4ead-ac1a-51ffa13a2b51",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1000,
        380
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.output.Body }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $json.output.Subject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d3c55f8b-ff7d-4d16-a833-fb80f67542b9",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1160,
        580
      ],
      "parameters": {
        "options": {
          "buttonLabel": "Submit"
        },
        "formTitle": "Select Location",
        "formFields": {
          "values": [
            {
              "fieldType": "dropdown",
              "fieldLabel": "Location",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Bangkok, Thailand"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "What to Scrape",
              "placeholder": "Restaurants etc..",
              "requiredField": true
            },
            {
              "fieldType": "number",
              "fieldLabel": "Number of Items to be Scraped",
              "placeholder": "50",
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e5be4ac3-6e12-4059-a7f5-27dd267c9766",
      "name": "Extract Essentials",
      "type": "n8n-nodes-base.set",
      "position": [
        -240,
        500
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cdcdbe98-2ad6-4c79-8a1e-01ad5f2ace89",
              "name": "title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "a6361af2-4f5c-4407-bf32-b2c0e457466e",
              "name": "categoryName",
              "type": "string",
              "value": "={{ $json.categoryName }}"
            },
            {
              "id": "521a1095-18d1-47cc-b113-7ecee83c26ab",
              "name": "Average Price",
              "type": "string",
              "value": "={{ $json.price }}"
            },
            {
              "id": "d047d620-4102-467a-9eab-fb097c8f1cc3",
              "name": "rating",
              "type": "number",
              "value": "={{ $json.totalScore }}"
            },
            {
              "id": "4e30e3a2-1564-457c-8e84-b55d6f0b11e4",
              "name": "reviewsCount",
              "type": "number",
              "value": "={{ $json.reviewsCount }}"
            },
            {
              "id": "d0aa5224-af7a-4a50-aad1-ec3bde6c6941",
              "name": "address",
              "type": "string",
              "value": "={{ $json.city }}{{ $json.address }}, {{ $json.street }}, {{ $json.postalCode }}"
            },
            {
              "id": "d86d5474-05a4-40cb-8a16-b5c14636f5ae",
              "name": "phone",
              "type": "string",
              "value": "={{ $json.phone || $json.phones[0]}}"
            },
            {
              "id": "3cfa770c-626e-4920-a8bf-a1a41b5c7308",
              "name": "url",
              "type": "string",
              "value": "={{ $json.url }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "99952b60-c7ea-4498-8199-850f2a810c7f",
      "name": "Sort by Review Count and Rating",
      "type": "n8n-nodes-base.sort",
      "position": [
        -80,
        500
      ],
      "parameters": {
        "options": {},
        "sortFieldsUi": {
          "sortField": [
            {
              "order": "descending",
              "fieldName": "reviewsCount"
            },
            {
              "order": "descending",
              "fieldName": "rating"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e2bfc98e-ef3b-4a60-8bfd-9875f1ca6435",
      "name": "Group Essentials",
      "type": "n8n-nodes-base.set",
      "position": [
        320,
        380
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e742dad3-8b1c-4001-bb2f-98c8a34203df",
              "name": "Restaurant_Data",
              "type": "string",
              "value": "=Name: {{ $json.title }}\nCategory: {{ $json.categoryName || '' }}\nPrice Range: {{ $json['Average Price'] || '' }}\nRating: {{ $json.rating }}\nTotal Reviews: {{ $json.reviewsCount }}\nAddress: {{ $json.address.toString() }}\nPhone: {{ $json.phone.toString() }}\nGoogle Map Location: {{ $json.url.toString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "15d812b2-04ab-4cde-8b31-ac1aabdfa37b",
      "name": "Reviews > 500",
      "type": "n8n-nodes-base.if",
      "position": [
        160,
        500
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4ff04126-679d-4a07-b15a-9dade66e8766",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.reviewsCount }}",
              "rightValue": 500
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9808152c-cb40-4040-a030-355cd53fc025",
      "name": "AI Agent1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        660,
        380
      ],
      "parameters": {
        "options": {},
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "a1578675-1189-4d47-9810-7b75ca9ac690",
      "name": "Structured Output Parser1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        880,
        680
      ],
      "parameters": {},
      "typeVersion": 1.2
    },
    {
      "id": "70346840-9e1c-4dc2-9ac7-0758a639ba0f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1180,
        360
      ],
      "parameters": {
        "width": 540,
        "content": "## Run an APIfy Google Map Actor\n- Submit form with the place to scrape\n- The actor gets executed and scrape google maps.\n- If the job succeeds move to next item to get the dataset.\n- Else do nothing"
      },
      "typeVersion": 1
    },
    {
      "id": "f5506c41-4918-4945-96bc-e7272abd2809",
      "name": "Lead Creator",
      "type": "n8n-nodes-base.airtable",
      "position": [
        160,
        220
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appgqYxjdpsWWuk3p",
          "cachedResultUrl": "https://airtable.com/appgqYxjdpsWWuk3p",
          "cachedResultName": "n8n_Airtable"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblyPsVMcVtWtBXNp",
          "cachedResultUrl": "https://airtable.com/appgqYxjdpsWWuk3p/tblyPsVMcVtWtBXNp",
          "cachedResultName": "Google Map Leads - Restaurants"
        },
        "columns": {
          "value": {
            "Phone": "={{ $json.phone }}",
            "Title": "={{ $json.title }}",
            "Rating": "={{ $json.rating }}",
            "Address": "={{ $json.address }}",
            "Category": "={{ $json.categoryName }}",
            "Location": "={{ $json.url }}",
            "Review Count": "={{ $json.reviewsCount }}",
            "Average_Price_Range": "={{ $json['Average Price'] }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Average_Price_Range",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Average_Price_Range",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rating",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Rating",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Review Count",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Review Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Address",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Location",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1cacca8f-d583-407d-983a-a3e2c39d8d54",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -540,
        380
      ],
      "parameters": {
        "color": 3,
        "width": 220,
        "height": 280,
        "content": "## Extract data from Dataset\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7737a847-9106-4f03-a89a-99fd481660dc",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -260,
        340
      ],
      "parameters": {
        "color": 6,
        "width": 340,
        "height": 320,
        "content": "## Extract only Essentials\n- Extract only the leads\n- Sort them with review count and rating. "
      },
      "typeVersion": 1
    },
    {
      "id": "f393a9b0-b0e8-4903-afd8-23d91f375c69",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        140,
        140
      ],
      "parameters": {
        "width": 360,
        "height": 240,
        "content": "## Make an entry to Airtable"
      },
      "typeVersion": 1
    },
    {
      "id": "1d509ea6-5ffd-4e3e-a013-44db228adb33",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        660
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "content": "## Aggregate for the Newletter\n- Extract items having review count greater than 500.\n- Group and Aggregate them and pass as a single input to AI Agent to Create a News Letter. "
      },
      "typeVersion": 1
    },
    {
      "id": "715ebbb3-26c6-4a8c-966d-d41efcf210b2",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        200
      ],
      "parameters": {
        "color": 4,
        "width": 440,
        "content": "## Prepare and Send Email\n- AI Agent will prepare the New letter based on the lead greater than 500\n- Send the newsletter via GMAIL."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "0516cb5a-b582-4389-855b-78f33d6b3496",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Get dataset items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run an Actor": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reviews > 500": {
      "main": [
        [
          {
            "node": "Group Essentials",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group Essentials": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get dataset items": {
      "main": [
        [
          {
            "node": "Extract Essentials",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract Essentials": {
      "main": [
        [
          {
            "node": "Sort by Review Count and Rating",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Run an Actor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Sort by Review Count and Rating": {
      "main": [
        [
          {
            "node": "Reviews > 500",
            "type": "main",
            "index": 0
          },
          {
            "node": "Lead Creator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Source: https://n8n.io/workflows/7877/ — 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

Transform your manual hiring process into an intelligent evaluation system that saves 15-20 minutes per candidate! This workflow automates the entire candidate assessment pipeline - from CSV/XLSX uplo

Form Trigger, Google Sheets, Google Drive +8
AI & RAG

This workflow is ideal for:

Airtable, OpenAI Chat, Output Parser Structured +4
AI & RAG

This workflow turns your website form into a fully automated AI Lead Qualification system. Whenever a new lead submits your form, the workflow: Receives the submission through a Webhook Cleans and nor

Form Trigger, Agent, OpenAI Chat +7
AI & RAG

Typeform IA - YT. Uses typeformTrigger, agent, lmChatOpenAi, toolWorkflow. Event-driven trigger; 75 nodes.

Typeform Trigger, Agent, OpenAI Chat +7
AI & RAG

This workflow generates comprehensive B2B leads, from a selected Business type in ANY CITY IN THE WORLD, including: Company name; Website; Email (enriched with AI Agent); Phone number; Address; Main L

Output Parser Structured, Memory Buffer Window, Agent +8