Workflow: Manualtrigger Workflow
Integrations: code, filter, googleSheets, httpRequest, if, itemLists, manualTrigger, scheduleTrigger, set, stickyNote

{"meta": {"instanceId": "workflow-28ea6af6", "versionId": "1.0.0", "createdAt": "2025-09-29T07:07:42.466461", "updatedAt": "2025-09-29T07:07:42.466489", "owner": "n8n-user", "license": "MIT", "category": "automation", "status": "active", "priority": "high", "environment": "production"}, "nodes": [{"id": "edef59f6-0197-408e-a819-141c1ca8dedd", "name": "When clicking \"Execute Workflow\"", "type": "n8n-nodes-base.manualTrigger", "position": [-1820, 780], "parameters": {}, "typeVersion": 1, "notes": "This manualTrigger node performs automated tasks as part of the workflow."}, {"id": "d56deaf5-1ad8-45a2-bbf0-3b71560f8036", "name": "Extract next start value", "type": "n8n-nodes-base.code", "position": [-640, 480], "parameters": {"mode": "runOnceForEachItem", "jsCode": "let nextUrl\n\nif ($json && $json[\"serpapi_pagination\"] && $json[\"serpapi_pagination\"][\"next\"]) {\n    nextUrl = $json[\"serpapi_pagination\"][\"next\"];\n\n$input.item.json.start = nextUrl.split('&').find(param => param.startsWith('start=')).split('=')[1];\n}\n\n\nreturn $input.item;"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "6562c236-c957-437b-91a9-15e98af09858", "name": "Merge all values from SERPAPI", "type": "n8n-nodes-base.code", "position": [-140, 680], "parameters": {"jsCode": "const allData = []\n\nlet counter = 0;\ndo {\n  try {\n    const items = $items(\"SERPAPI - Scrape Google Maps URL\", 0, counter).map(item => item.json.local_results);\n    allData.push.apply(allData, items);\n  } catch (error) {\n    return [{json: {allData}}];  \n  }\n\n  counter++;\n} while(true);\nreturn $input.all();"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "357e8a57-dbb5-4241-b9c2-863b3ae3fd96", "name": "Transform data in the right format", "type": "n8n-nodes-base.code", "position": [380, 680], "parameters": {"jsCode": "console.log($input.all())\n\n\nconst data = $input.all()\n\nconsole.log(\"error\",data)\n\nfunction mergeData(data) {\n    let merged = [];\n    data.forEach(entry => {\n        for (const key in entry.json) {\n            merged.push(entry.json[key]);\n        }\n    });\n    return merged;\n}\n\nconst mergedData = mergeData(data);\nconsole.log(mergedData);\n\n\nreturn mergedData.filter(item => item !== null);"}, "typeVersion": 2, "notes": "This code node performs automated tasks as part of the workflow."}, {"id": "4e8e9ae9-f5e3-4bfd-b0d4-9403a1c38d39", "name": "Add rows in Google Sheets", "type": "n8n-nodes-base.googleSheets", "position": [760, 680], "parameters": {"columns": {"value": {}, "schema": [{"id": "position", "type": "string", "display": true, "required": false, "displayName": "position", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "title", "type": "string", "display": true, "required": false, "displayName": "title", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "phone", "type": "string", "display": true, "required": false, "displayName": "phone", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "website", "type": "string", "display": true, "required": false, "displayName": "website", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "rating", "type": "string", "display": true, "required": false, "displayName": "rating", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "reviews", "type": "string", "display": true, "required": false, "displayName": "reviews", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "place_id", "type": "string", "display": true, "removed": false, "required": false, "displayName": "place_id", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "data_id", "type": "string", "display": true, "required": false, "displayName": "data_id", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "data_cid", "type": "string", "display": true, "required": false, "displayName": "data_cid", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "reviews_link", "type": "string", "display": true, "required": false, "displayName": "reviews_link", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "photos_link", "type": "string", "display": true, "required": false, "displayName": "photos_link", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "gps_coordinates", "type": "string", "display": true, "required": false, "displayName": "gps_coordinates", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "place_id_search", "type": "string", "display": true, "required": false, "displayName": "place_id_search", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "provider_id", "type": "string", "display": true, "required": false, "displayName": "provider_id", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "price", "type": "string", "display": true, "required": false, "displayName": "price", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "type", "type": "string", "display": true, "required": false, "displayName": "type", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "types", "type": "string", "display": true, "required": false, "displayName": "types", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "address", "type": "string", "display": true, "required": false, "displayName": "address", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "open_state", "type": "string", "display": true, "required": false, "displayName": "open_state", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "hours", "type": "string", "display": true, "required": false, "displayName": "hours", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "operating_hours", "type": "string", "display": true, "required": false, "displayName": "operating_hours", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "description", "type": "string", "display": true, "required": false, "displayName": "description", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "service_options", "type": "string", "display": true, "required": false, "displayName": "service_options", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "order_online", "type": "string", "display": true, "required": false, "displayName": "order_online", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "thumbnail", "type": "string", "display": true, "required": false, "displayName": "thumbnail", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "editorial_reviews", "type": "string", "display": true, "required": false, "displayName": "editorial_reviews", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "unclaimed_listing", "type": "string", "display": true, "required": false, "displayName": "unclaimed_listing", "defaultMatch": false, "canBeUsedToMatch": true}], "mappingMode": "autoMapInputData", "matchingColumns": ["place_id"]}, "options": {"cellFormat": "RAW"}, "operation": "appendOrUpdate", "sheetName": {"__rl": true, "mode": "list", "value": 2023033319, "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Results"}, "documentId": {"__rl": true, "mode": "url", "value": "{{ $env.WEBHOOK_URL }}"}}, "credentials": {"googleSheetsOAuth2Api": {"id": "{{ $credentials.googleSheetsOAuth2Api.id }}", "name": "Google Sheets account lucas"}}, "typeVersion": 4.2, "notes": "This googleSheets node performs automated tasks as part of the workflow."}, {"id": "90194aa3-5960-47bd-9e0e-efee827004c4", "name": "SERPAPI - Scrape Google Maps URL", "type": "n8n-nodes-base.httpRequest", "onError": "continueErrorOutput", "position": [-920, 500], "parameters": {"url": "{{ $env.API_BASE_URL }}", "options": {}, "sendQuery": true, "authentication": "{{ $credentials.predefinedCredentialType }}", "queryParameters": {"parameters": [{"name": "engine", "value": "google_maps"}, {"name": "q", "value": "={{$json?.search_parameters?.q || $json.keyword }} "}, {"name": "ll", "value": "={{ $json?.search_parameters?.ll|| $json.geo }}"}, {"name": "type", "value": "search"}, {"name": "start", "value": "={{ $json.start|| 0 }}"}]}, "nodeCredentialType": "YOUR_CREDENTIAL_HERE"}, "credentials": {"serpApi": {"id": "MP9W6wBcEfhc6ofn", "name": "SerpAPI account"}}, "typeVersion": 4.1, "notes": "This httpRequest node performs automated tasks as part of the workflow."}, {"id": "9cfd1e76-2d7c-4618-86d6-e1f3c7729044", "name": "Remove duplicate items", "type": "n8n-nodes-base.itemLists", "position": [580, 680], "parameters": {"compare": "selectedFields", "options": {}, "operation": "removeDuplicates", "fieldsToCompare": "place_id"}, "typeVersion": 3.1, "notes": "This itemLists node performs automated tasks as part of the workflow."}, {"id": "e47dfa17-fc84-4694-950d-165302a9075f", "name": "Split out items", "type": "n8n-nodes-base.itemLists", "position": [40, 680], "parameters": {"options": {}, "fieldToSplitOut": "allData"}, "typeVersion": 3.1, "notes": "This itemLists node performs automated tasks as part of the workflow."}, {"id": "decc89ee-f836-4ec2-9a1a-0371a8889ef5", "name": "Remove empty values", "type": "n8n-nodes-base.filter", "position": [200, 680], "parameters": {"conditions": {"string": [{"value1": "={{ $json[0] }}", "operation": "isNotEmpty"}]}}, "typeVersion": 1, "notes": "This filter node performs automated tasks as part of the workflow."}, {"id": "bd7ca3a5-2697-4653-abf6-372088d925e6", "name": "Google Sheets - Get searches  to scrap", "type": "n8n-nodes-base.googleSheets", "position": [-1380, 500], "parameters": {"options": {}, "filtersUI": {"values": [{"lookupColumn": "Status"}]}, "sheetName": {"__rl": true, "mode": "list", "value": "gid=0", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Add your search here"}, "documentId": {"__rl": true, "mode": "url", "value": "{{ $env.WEBHOOK_URL }}"}}, "credentials": {"googleSheetsOAuth2Api": {"id": "{{ $credentials.googleSheetsOAuth2Api.id }}", "name": "Google Sheets account lucas"}}, "typeVersion": 4.2, "notes": "This googleSheets node performs automated tasks as part of the workflow."}, {"id": "6d0be482-b1ad-4fa0-8d2e-bef9a4414924", "name": "Extract keyword and location from URL", "type": "n8n-nodes-base.set", "position": [-1160, 500], "parameters": {"fields": {"values": [{"name": "keyword", "stringValue": "={{ $json.URL.match(/\\/search\\/(.*?)\\//)[1] }}"}, {"name": "geo", "stringValue": "={{ $json.URL.match(/(@[^\\/?]+)/)[1]}}"}]}, "options": {}}, "typeVersion": 3.2, "notes": "This set node performs automated tasks as part of the workflow."}, {"id": "f6fb8db2-8444-4605-af9d-22ca71c7937d", "name": "Sticky Note1", "type": "n8n-nodes-base.stickyNote", "position": [-1920, 200], "parameters": {"width": 312.2965981499806, "height": 266.8807730722022, "content": "## Adjust frequency to your own needs"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "234b5d18-75d7-495b-960f-06192d9e7c61", "name": "Run workflow every hours", "type": "n8n-nodes-base.scheduleTrigger", "position": [-1800, 300], "parameters": {"rule": {"interval": [{"field": "hours"}]}}, "typeVersion": 1.1, "notes": "This scheduleTrigger node performs automated tasks as part of the workflow."}, {"id": "ea2e9b89-e52c-4e25-803a-ce33c41c20fc", "name": "Sticky Note2", "type": "n8n-nodes-base.stickyNote", "position": [-1460, 200], "parameters": {"height": 511.2196121145973, "content": "## Copy my template and connect it to n8n\n\nTemplate link: \n {{ $env.WEBHOOK_URL }}"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "de515d8d-641d-4b91-9472-608ad3878e32", "name": "Sticky Note3", "type": "n8n-nodes-base.stickyNote", "position": [-980, 169.3107006491615], "parameters": {"height": 535.9388810024284, "content": "## Add your SERPAPI API Key\n\nStart a free trial at serpapi.com and get your API key in \"Your account\" section"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "a5a63861-7ff3-4072-a669-acce938939d8", "name": "Update Status to Success", "type": "n8n-nodes-base.googleSheets", "position": [940, 680], "parameters": {"columns": {"value": {"URL": "{{ $env.BASE_URL }}", "Status": "\u2705"}, "schema": [{"id": "URL", "type": "string", "display": true, "removed": false, "required": false, "displayName": "URL", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "Status", "type": "string", "display": true, "required": false, "displayName": "Status", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "row_number", "type": "string", "display": true, "removed": true, "readOnly": true, "required": false, "displayName": "row_number", "defaultMatch": false, "canBeUsedToMatch": true}], "mappingMode": "defineBelow", "matchingColumns": ["URL"]}, "options": {}, "operation": "update", "sheetName": {"__rl": true, "mode": "list", "value": "gid=0", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Add your search url here"}, "documentId": {"__rl": true, "mode": "url", "value": "{{ $env.WEBHOOK_URL }}"}}, "credentials": {"googleSheetsOAuth2Api": {"id": "{{ $credentials.googleSheetsOAuth2Api.id }}", "name": "Google Sheets account lucas"}}, "executeOnce": true, "typeVersion": 4.2, "notes": "This googleSheets node performs automated tasks as part of the workflow."}, {"id": "2bdc5b63-e3bb-453e-a236-9c83cd12cc03", "name": "Update Status to Error", "type": "n8n-nodes-base.googleSheets", "position": [-640, 620], "parameters": {"columns": {"value": {"URL": "{{ $env.BASE_URL }}", "Status": "\u274c"}, "schema": [{"id": "URL", "type": "string", "display": true, "removed": false, "required": false, "displayName": "URL", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "Status", "type": "string", "display": true, "required": false, "displayName": "Status", "defaultMatch": false, "canBeUsedToMatch": true}, {"id": "row_number", "type": "string", "display": true, "removed": true, "readOnly": true, "required": false, "displayName": "row_number", "defaultMatch": false, "canBeUsedToMatch": true}], "mappingMode": "defineBelow", "matchingColumns": ["URL"]}, "options": {}, "operation": "update", "sheetName": {"__rl": true, "mode": "list", "value": "gid=0", "cachedResultUrl": "{{ $env.WEBHOOK_URL }}", "cachedResultName": "Add your search url here"}, "documentId": {"__rl": true, "mode": "url", "value": "{{ $env.WEBHOOK_URL }}"}}, "credentials": {"googleSheetsOAuth2Api": {"id": "{{ $credentials.googleSheetsOAuth2Api.id }}", "name": "Google Sheets account lucas"}}, "executeOnce": true, "typeVersion": 4.2, "notes": "This googleSheets node performs automated tasks as part of the workflow."}, {"id": "f413f4ef-fd6d-4967-8df7-a4fee4361246", "name": "Sticky Note", "type": "n8n-nodes-base.stickyNote", "position": [-1920, 640], "parameters": {"width": 312.2965981499806, "height": 310.4703136043695, "content": "## Click on Execute Workflow to run the workflow manually"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}, {"id": "cbc53e43-f141-434c-a655-feb1f7d3c65b", "name": "Continue IF Loop is complete", "type": "n8n-nodes-base.if", "position": [-380, 620], "parameters": {"conditions": {"number": [{"value1": "={{ $json.search_parameters.start }}", "operation": "isNotEmpty"}], "string": [{"value1": "={{ $json.serpapi_pagination.next }}", "operation": "isNotEmpty"}]}}, "typeVersion": 1, "notes": "This if node performs automated tasks as part of the workflow."}, {"id": "229f9652-b703-490e-aa3c-c28b0fe1f2e8", "name": "Sticky Note4", "type": "n8n-nodes-base.stickyNote", "position": [-2340, 200], "parameters": {"width": 357.33341618921213, "height": 532.3420004517685, "content": "## Read Me\n\nThis workflow allows to scrape Google Maps data in an efficient way using SerpAPI. \n\nYou'll get all data from Gmaps at a cheaper cost than Google Maps API.\n\nAdd as input, your Google Maps search URL and you'll get a list of places with many data points such as:\n- phone number\n- website\n- rating\n- reviews\n- address\n\nAnd much more.\n\n\n**Full guide to implement the workflow is here**: \n\n{{ $env.WEBHOOK_URL }}"}, "typeVersion": 1, "notes": "This stickyNote node performs automated tasks as part of the workflow."}], "pinData": {}, "connections": {"90194aa3-5960-47bd-9e0e-efee827004c4": {"main": [[{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-9bb10fca", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-bb544fbb", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-96603d70", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-d721b21e", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-e9abee27", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-da3797a7", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-8d3c73a4", "type": "main", "index": 0}], [{"node": "error-handler-90194aa3-5960-47bd-9e0e-efee827004c4-3e36c996", "type": "main", "index": 0}]]}, "4e8e9ae9-f5e3-4bfd-b0d4-9403a1c38d39": {"main": [[{"node": "error-handler-4e8e9ae9-f5e3-4bfd-b0d4-9403a1c38d39-6632eb2f", "type": "main", "index": 0}]]}, "bd7ca3a5-2697-4653-abf6-372088d925e6": {"main": [[{"node": "error-handler-bd7ca3a5-2697-4653-abf6-372088d925e6-827b0f5a", "type": "main", "index": 0}]]}, "a5a63861-7ff3-4072-a669-acce938939d8": {"main": [[{"node": "error-handler-a5a63861-7ff3-4072-a669-acce938939d8-d63a35c3", "type": "main", "index": 0}]]}, "2bdc5b63-e3bb-453e-a236-9c83cd12cc03": {"main": [[{"node": "error-handler-2bdc5b63-e3bb-453e-a236-9c83cd12cc03-51d65b8a", "type": "main", "index": 0}]]}}, "name": "Manualtrigger Workflow", "settings": {"executionOrder": "v1", "saveManualExecutions": true, "callerPolicy": "workflowsFromSameOwner", "errorWorkflow": null, "timezone": "UTC", "executionTimeout": 3600, "maxExecutions": 1000, "retryOnFail": true, "retryCount": 3, "retryDelay": 1000}, "description": "Automated workflow: Manualtrigger Workflow. This workflow integrates 11 different services: itemLists, httpRequest, filter, stickyNote, code. It contains 26 nodes and follows best practices for error handling and security.", "tags": ["automation", "n8n", "production-ready", "excellent", "optimized"], "notes": "Excellent quality workflow: Manualtrigger Workflow. This workflow has been optimized for production use with comprehensive error handling, security, and documentation."}