Send new listings to matching buyers on WhatsApp
When you add a listing, every opted-in buyer whose area, type and budget match gets it on WhatsApp.
How it works
- Add a listing (code, area, type, bedrooms, price, photos link).
- Read your Buyers sheet.
- Keep opted-in buyers whose area, type and budget fit.
- Send each one a WhatsApp template with the listing.
Diagram
Code
JavaScript used in the Code step — already included in the template below.
// Buyers sheet columns: name | phone | area | type (apartment, villa…) | min_budget | max_budget | opted_in
// Finds opted-in buyers whose area, type and budget fit the new listing.
const listing = $("New listing").first().json;
const price = Number(String(listing.price).replace(/[^0-9.]/g, ""));
const same = (a, b) => String(a || "").trim().toLowerCase() === String(b || "").trim().toLowerCase();
return $input.all()
.map((item) => item.json)
.filter((b) => String(b.opted_in).toLowerCase() === "yes" && b.phone)
.filter((b) => same(b.area, listing.area) && (!b.type || same(b.type, listing.type)))
.filter((b) => price >= (Number(b.min_budget) || 0) && price <= (Number(b.max_budget) || Infinity))
.map((b) => ({
json: {
phone: String(b.phone).replace(/[^0-9]/g, ""),
name: b.name,
code: listing.code,
summary: `${listing.type} · ${listing.bedrooms} bed · ${listing.area}`,
price: listing.price,
link: listing.photos_link || "",
},
}));Build it
Pick your tool — same automation, step by step.
Copy and paste straight into an n8n canvas (Ctrl+V), or download and use Import from File. Then connect your own credentials and replace every YOUR_… placeholder.
Show code (174 lines)
{
"name": "Send new listings to matching buyers on WhatsApp (Flowngn)",
"nodes": [
{
"parameters": {
"content": "## Send new listings to matching buyers on WhatsApp\nWhen you add a listing, every opted-in buyer whose area, type and budget match gets it on WhatsApp.\n\n**Setup**\n1. Open each node and connect your own credentials.\n2. Replace every YOUR_… placeholder.\n3. Test once, then activate.\n\nFree template from Flowngn",
"height": 260,
"width": 340
},
"id": "343164f5-4864-4c3c-aba4-cefe1e85c9da",
"name": "Setup notes",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-420,
-60
]
},
{
"parameters": {
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Listings",
"mode": "name"
},
"event": "rowAdded",
"options": {}
},
"id": "343164f5-4864-4c3c-aba4-cefe1e85c9da",
"name": "New listing",
"type": "n8n-nodes-base.googleSheetsTrigger",
"typeVersion": 1,
"position": [
0,
0
]
},
{
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "YOUR_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Buyers",
"mode": "name"
},
"options": {}
},
"id": "343164f5-4864-4c3c-aba4-cefe1e85c9da",
"name": "Read buyers",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
300,
0
]
},
{
"parameters": {
"jsCode": "// Buyers sheet columns: name | phone | area | type (apartment, villa…) | min_budget | max_budget | opted_in\n// Finds opted-in buyers whose area, type and budget fit the new listing.\nconst listing = $(\"New listing\").first().json;\nconst price = Number(String(listing.price).replace(/[^0-9.]/g, \"\"));\nconst same = (a, b) => String(a || \"\").trim().toLowerCase() === String(b || \"\").trim().toLowerCase();\n\nreturn $input.all()\n .map((item) => item.json)\n .filter((b) => String(b.opted_in).toLowerCase() === \"yes\" && b.phone)\n .filter((b) => same(b.area, listing.area) && (!b.type || same(b.type, listing.type)))\n .filter((b) => price >= (Number(b.min_budget) || 0) && price <= (Number(b.max_budget) || Infinity))\n .map((b) => ({\n json: {\n phone: String(b.phone).replace(/[^0-9]/g, \"\"),\n name: b.name,\n code: listing.code,\n summary: `${listing.type} · ${listing.bedrooms} bed · ${listing.area}`,\n price: listing.price,\n link: listing.photos_link || \"\",\n },\n }));"
},
"id": "343164f5-4864-4c3c-aba4-cefe1e85c9da",
"name": "Matching buyers",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
600,
0
]
},
{
"parameters": {
"operation": "sendTemplate",
"phoneNumberId": "YOUR_PHONE_NUMBER_ID",
"recipientPhoneNumber": "={{ $json.phone }}",
"template": "YOUR_NEW_LISTING_TEMPLATE|ar",
"components": {
"component": [
{
"type": "body",
"bodyParameters": {
"parameter": [
{
"type": "text",
"text": "={{ $json.name }}"
},
{
"type": "text",
"text": "={{ $json.summary }}"
},
{
"type": "text",
"text": "={{ $json.price }}"
},
{
"type": "text",
"text": "={{ $json.link }}"
}
]
}
}
]
}
},
"id": "343164f5-4864-4c3c-aba4-cefe1e85c9da",
"name": "Send the listing",
"type": "n8n-nodes-base.whatsApp",
"typeVersion": 1,
"position": [
900,
0
]
}
],
"connections": {
"New listing": {
"main": [
[
{
"node": "Read buyers",
"type": "main",
"index": 0
}
]
]
},
"Read buyers": {
"main": [
[
{
"node": "Matching buyers",
"type": "main",
"index": 0
}
]
]
},
"Matching buyers": {
"main": [
[
{
"node": "Send the listing",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"meta": {
"templateCredsSetupCompleted": false
},
"tags": []
}In Make, create a new scenario and add these modules in order:
- Google Sheets › Watch New Rows
- Google Sheets › Search Rows
- Tools › Set variable / Iterator + Array aggregator (same logic as the Code step)
- WhatsApp Business Cloud › Send a Template Message
- Every module run uses Make operations — the free plan includes a monthly quota.
- Make's built-in functions (map, sum, formatDate…) can replace most Code steps; for complex logic use a code module.
- Module and step names can differ slightly as Make and Zapier update their apps.
In Zapier, create a new Zap and add these steps in order:
- Google Sheets — New Spreadsheet Row
- Google Sheets — Lookup Spreadsheet Rows (or Code by Zapier)
- Code by Zapier — Run JavaScript (paste the code from the Code section)
- WhatsApp — Send Template Message
- Zaps with more than two steps need a paid Zapier plan.
- Webhooks, Filters/Paths and Code by Zapier are premium features on some Zapier plans.
- Code by Zapier runs JavaScript: reuse the code shown above, reading inputs from inputData instead of $json.
- Module and step names can differ slightly as Make and Zapier update their apps.
Tips
- Write areas exactly the same way in both sheets, e.g. "New Cairo", not "new cairo 5th settlement".
Related flows
Rent due reminders on WhatsApp
Three days before rent is due, each tenant gets a polite WhatsApp reminder with the amount and date.
Property inquiries straight to your agent's phone
Website and portal inquiries are saved as leads and sent to the agent on Telegram within seconds.
Bosta delivery updates to customers on WhatsApp
Customers get a WhatsApp message when their Bosta shipment is picked up, out for delivery or delivered.