AutomationFlowsMarketing & Ads › Send Whatsapp Booking Links for Facebook Leads with Sheets, Redis, and Cal.com

Send Whatsapp Booking Links for Facebook Leads with Sheets, Redis, and Cal.com

Byiamvaar @iamvaar on n8n.io

Youtube Video: https://youtu.be/2yB1Imaa6AY?si=FAY4YCeSqqnxCdgW

Event trigger★★★★☆ complexity15 nodesFacebook Lead Ads TriggerGoogle SheetsWhatsAppRedis
Marketing & Ads Trigger: Event Nodes: 15 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Sheets → WhatsApp 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": "r3Lx2TdP4752qrLM",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Leads to Instant Outreach",
  "tags": [],
  "nodes": [
    {
      "id": "d7501d1b-8898-45fd-a608-e0f78026b333",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        -368
      ],
      "parameters": {
        "width": 480,
        "height": 848,
        "content": "## Leads to Instant Outreach\n\n### How it works\n\n1. The workflow triggers when a new lead is captured via Facebook Lead Ads.\n2. It queries Google Sheets to check if the lead's information is already logged.\n3. Depending on the condition, it either creates a new database entry or proceeds to evaluation.\n4. Data is formatted and specialized Cal.com autofill parameters are generated.\n5. The lead is sent a WhatsApp message containing their personalized booking details.\n6. The state is updated in Redis and the finalized status is written back to the Google Sheet.\n\n### Setup steps\n\n- [ ] Connect and authenticate your Facebook Lead Ads account\n- [ ] Link your Google account and select the correct spreadsheet and worksheet in the Google Sheets nodes\n- [ ] Set up your WhatsApp API credentials to enable message sending\n- [ ] Provide the appropriate connection string and credentials for your Redis instance\n\n### Customization\n\nYou can modify the Edit Fields node to include additional lead data in the WhatsApp message or the Cal.com parameters."
      },
      "typeVersion": 1
    },
    {
      "id": "9f70b6d0-c53e-4ab4-8170-79025f68e53c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 304,
        "content": "## Trigger and check existing lead\n\nReceives new leads from Facebook and checks Google Sheets to see if they already exist in the database."
      },
      "typeVersion": 1
    },
    {
      "id": "910f9837-0420-4880-a1a9-621ed3d98f44",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 560,
        "content": "## Handle new or existing lead\n\nUses conditional logic to either append a new row for new leads or route existing leads accordingly."
      },
      "typeVersion": 1
    },
    {
      "id": "72425022-a370-4cc1-b609-14e794732c6e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 304,
        "content": "## Format booking parameters\n\nPrepares the lead's data and injects autofill parameters for a Cal.com booking link."
      },
      "typeVersion": 1
    },
    {
      "id": "bcd2150e-b58f-45ec-88e7-af1fb4813644",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1040,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 304,
        "content": "## Send message and save state\n\nDispatches a WhatsApp message to the lead, caches the event in Redis, and logs the final status back in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "117c50ea-41cf-4811-9c82-bdddab1f0ed8",
      "name": "When Facebook Lead Received",
      "type": "n8n-nodes-base.facebookLeadAdsTrigger",
      "position": [
        -512,
        -112
      ],
      "parameters": {
        "form": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "page": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "options": {}
      },
      "credentials": {
        "facebookLeadAdsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "de416da0-999f-4d99-9ea4-c06d2971b034",
      "name": "Upsert Lead in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        192,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "dnd": "false",
            "email": "={{ $('When Facebook Lead Received').item.json.field_data[1].values[0] }}",
            "phone": "={{ $('When Facebook Lead Received').item.json.field_data[2].values[0].replace('+', '') }}",
            "full name": "={{ $('When Facebook Lead Received').item.json.field_data[0].values[0] }}",
            "contacted?": "false",
            "Property Name": "={{ $('When Facebook Lead Received').item.json.field_data[3].values[0] }}"
          },
          "schema": [
            {
              "id": "full name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "full name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Property Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Property Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contacted?",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contacted?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "dnd",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "dnd",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "phone"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit?usp=drivesdk",
          "cachedResultName": "Facebook Leads"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "61d2818e-4f82-4f6a-8252-558bbcc54e64",
      "name": "Fetch Lead from Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -304,
        -112
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.field_data[2].values[0].replace('+', '') }}",
              "lookupColumn": "phone"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit?usp=drivesdk",
          "cachedResultName": "Facebook Leads"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "9062a660-e273-428a-ad6d-74bc5d97bd49",
      "name": "Check If Row Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        -96,
        -112
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b47f1ea9-b27f-4e55-beaa-56194504246a",
              "operator": {
                "type": "number",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.row_number }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d9990d60-46da-4220-830b-26e185f61601",
      "name": "Check If Contacted",
      "type": "n8n-nodes-base.if",
      "position": [
        208,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "68e557ba-1f59-4e82-ad0b-4cfc958705ca",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json['contacted?'] }}",
              "rightValue": ""
            },
            {
              "id": "61f9724e-a4c6-4a7b-a1e1-1749a1f6ab68",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.dnd }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "12722dc1-5608-47f6-a68e-f5d3dbc3c2bc",
      "name": "Send WhatsApp Message",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        1088,
        -48
      ],
      "parameters": {
        "textBody": "=Hi {{ $json.lead_name }}, thank you for your interest in the {{ $json.lead_property }}! \ud83c\udfe1\n\nWould you like to schedule a viewing or a quick chat? You can easily pick a time that works perfectly for you by tapping the link below:\n\n\ud83d\udc49 {{ $json.whatsapp_ready_url }}\n\nLet me know if you have any questions!",
        "operation": "send",
        "phoneNumberId": "1083481144853090",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('When Facebook Lead Received').item.json.field_data[2].values[0] }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "cc1380f2-7c53-4ba6-9258-b1d2766f4a5e",
      "name": "Save Session to Redis",
      "type": "n8n-nodes-base.redis",
      "position": [
        1296,
        -48
      ],
      "parameters": {
        "list": "=session:{{ $('When Facebook Lead Received').item.json.field_data[2].values[0].replace('+', '') }}",
        "operation": "push",
        "messageData": "=[\n  {\n    \"type\": \"ai\",\n    \"data\": {\n      \"content\": \"Hi {{ $('Add Calcom Params').item.json.lead_name }}, thank you for your interest in the {{ $('Add Calcom Params').item.json.lead_property }}! Would you like to schedule a viewing or a quick chat? You can easily pick a time that works perfectly for you by tapping the link below: {{ $('Add Calcom Params').item.json.whatsapp_ready_url }}\"\n    }\n  }\n]"
      },
      "credentials": {
        "redis": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5c456a62-5820-46e1-a433-a3624095276c",
      "name": "Mark Contacted in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1504,
        -48
      ],
      "parameters": {
        "columns": {
          "value": {
            "phone": "={{ $('When Facebook Lead Received').item.json.field_data[2].values[0].replace('+', '') }}",
            "contacted?": "true"
          },
          "schema": [
            {
              "id": "full name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "full name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Property Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Property Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contacted?",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contacted?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "dnd",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "dnd",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "phone"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1lKiWyaXfSVTQ6azjWbVg4sFc6owXRdIBWYNd7tnWxaY/edit?usp=drivesdk",
          "cachedResultName": "Facebook Leads"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "86bffc8d-7a6f-48b6-a4fd-c440fcd39d8e",
      "name": "Set Address Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        624,
        -48
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "5986aa9b-f408-4dbb-bfec-344b8217f462",
              "name": "NY street, Studio Appartment",
              "type": "string",
              "value": "https://cal.com/iam-v5192/nystudioappartment"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5a1cae28-45a0-4a6d-bd7c-36750312fd0f",
      "name": "Add Calcom Params",
      "type": "n8n-nodes-base.code",
      "position": [
        848,
        -48
      ],
      "parameters": {
        "jsCode": "// 1. Grab the incoming data from your 'Edit Fields' node\nconst item = $input.first().json;\n\n// 2. Pull the raw lead data from the Facebook Trigger\nconst fbData = $('When Facebook Lead Received').first().json.field_data;\nconst fullName = fbData.find(f => f.name === 'full_name')?.values[0] || '';\nconst email = fbData.find(f => f.name === 'email')?.values[0] || '';\nconst phone = fbData.find(f => f.name === 'phone_number')?.values[0] || '';\nconst propertyName = fbData.find(f => f.name === 'Property Name')?.values[0] || '';\n\n// 3. Dynamically grab the base link you created in the 'Edit Fields' node \nconst baseLink = item[propertyName];\n\n// 4. Construct the autofill parameters manually using encodeURIComponent (safe for n8n sandbox)\nconst paramsObj = {\n  name: fullName,\n  email: email,\n  notes: `Phone: ${phone}`\n};\n\nconst queryString = Object.keys(paramsObj)\n  .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(paramsObj[key])}`)\n  .join('&');\n\n// 5. Stitch them together\nconst finalBookingUrl = baseLink ? `${baseLink}?${queryString}` : 'URL_NOT_FOUND';\n\n// 6. Output everything so it's ready for WhatsApp\nreturn {\n  json: {\n    ...item,\n    lead_name: fullName,\n    lead_property: propertyName,\n    whatsapp_ready_url: finalBookingUrl\n  }\n};"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "1aeef405-1a6d-439b-afb5-9becdd6a368a",
  "nodeGroups": [],
  "connections": {
    "Add Calcom Params": {
      "main": [
        [
          {
            "node": "Send WhatsApp Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Contacted": {
      "main": [
        [
          {
            "node": "Set Address Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Address Fields": {
      "main": [
        [
          {
            "node": "Add Calcom Params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Row Exists": {
      "main": [
        [
          {
            "node": "Upsert Lead in Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check If Contacted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Session to Redis": {
      "main": [
        [
          {
            "node": "Mark Contacted in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send WhatsApp Message": {
      "main": [
        [
          {
            "node": "Save Session to Redis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Lead in Sheets": {
      "main": [
        [
          {
            "node": "Set Address Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Lead from Sheets": {
      "main": [
        [
          {
            "node": "Check If Row Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Facebook Lead Received": {
      "main": [
        [
          {
            "node": "Fetch Lead from Sheets",
            "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

Youtube Video: https://youtu.be/2yB1Imaa6AY?si=FAY4YCeSqqnxCdgW

Source: https://n8n.io/workflows/17190/ — original creator credit. Request a take-down →

More Marketing & Ads workflows → · Browse all categories →

Related workflows

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

Marketing & Ads

This n8n workflow automates the process of finding ecommerce seller leads, enriching them with product and business details, discovering company websites, and extracting contact information such as em

Google Sheets, N8N Nodes Mrscraper, HTTP Request
Marketing & Ads

This template is for B2B sales teams, SDRs, growth marketers, and founders who maintain a spreadsheet of prospects and need verified contact details -- emails and mobile numbers -- without manual rese

Google Sheets, HTTP Request
Marketing & Ads

This workflow finds local businesses from Google Maps and automatically enriches them with emails, social profiles, AI summaries, and personalized outreach messages — all saved to Google Sheets. Searc

HTTP Request, Google Sheets
Marketing & Ads

This workflow leverages n8n to perform automated Google Maps API queries and manage data efficiently in Google Sheets. It's designed to extract specific location data based on a given list of ZIP code

Execute Workflow Trigger, Stop And Error, HTTP Request +1
Marketing & Ads

This workflow reads LinkedIn profile URLs from Google Sheets, enriches each lead using PhantomBuster profile and company scrapers, finds a work email via Hunter.io with a Dropcontact fallback, writes

Google Sheets, HTTP Request, PhantomBuster +2