AutomationFlows β€Ί Data & Sheets β€Ί Send Appointment SMS Follow-ups with Typeform, Twilio and Google Sheets

Send Appointment SMS Follow-ups with Typeform, Twilio and Google Sheets

ByDavid S @david-s on n8n.io

πŸ“‹ Customer submits your Typeform β†’ instant personalised welcome SMS fires via Twilio πŸ“Š Submission logged to Google Sheets with name, phone, timestamp, and nudge tracking πŸ’¬ Twilio listens 24/7 for replies β†’ marks customer as responded, stops all future nudges ⏰ Scheduler runs…

Event triggerβ˜…β˜…β˜…β˜…β˜† complexity19 nodesTypeform TriggerTwilioGoogle SheetsTwilio Trigger
Data & Sheets Trigger: Event Nodes: 19 Complexity: β˜…β˜…β˜…β˜…β˜† Added:

This workflow corresponds to n8n.io template #15000 β€” we link there as the canonical source.

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": "XMQU1Cl3DrsiwDR3",
  "meta": {
    "aiBuilderAssisted": true
  },
  "name": "New Appointment \u2192 Welcome SMS",
  "tags": [],
  "nodes": [
    {
      "id": "548a5512-d4ba-474a-9be8-c2402f852554",
      "name": "Sticky Note 88ddccbc",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1168,
        160
      ],
      "parameters": {
        "color": "#F7F0C5",
        "width": 760,
        "height": 1788,
        "content": "## \ud83d\udcd6 README: Automated SMS Follow-Up System\n\n**What This Does**\nA complete 3-branch system that sends a welcome SMS when someone submits your Typeform, then automatically follows up with up to 2 nudge messages if they don't reply \u2014 all while respecting responses and stopping nudges the moment someone engages.\n\n**The Three Branches:**\n\n**Branch 1: New Submission Flow** (Typeform Trigger)\n- Instant welcome SMS when form is submitted\n- Logs customer data to Google Sheets tracking table\n- Starts the customer journey\n\n**Branch 2: SMS Reply Handler** (Twilio Trigger)\n- Listens 24/7 for incoming SMS replies\n- Marks customer as \"replied\" in Google Sheets\n- Stops all future nudges for that customer\n\n**Branch 3: Automated Nudge System** (Schedule Trigger - every 6 hours)\n- Checks for non-responders who need follow-up\n- Sends Nudge 1 at 24 hours after welcome SMS\n- Sends Nudge 2 at 24 hours after Nudge 1\n- Stops after 2 nudges (respects customer boundaries)\n\n**Who This Is For**\n- Dental & medical practices \u2014 welcome new patients and ensure they confirm appointments\n- Fitness studios \u2014 greet new members and get them to book their first session\n- Law firms \u2014 acknowledge inquiries and prompt for next steps\n- Real estate agents \u2014 confirm receipt and encourage follow-up questions\n- Agencies or local businesses - follow up with leads instantly\n- Any service business using Typeform for bookings/intake\n\n**What You Need**\n- Typeform account (free tier works)\n- Twilio account + phone number (~$1/mo for number, ~$0.0075/SMS)\n**!! WARNING !! getting A2P verification for a 10DLC can be challenging and take weeks**\n*A2P registration is highly regulated and requires careful opt in disclosures on signup form, term, and privacy policy will be reviewed for compliance without exception*\n- Google Sheets (free)\n- Your form must collect Name and Phone Number fields\n\n**Setup Steps**\n\n1. **Google Sheets Setup**\n   - Create a new spreadsheet for tracking\n   - Add headers: customerName | customerPhone | submittedAt | repliedAt | nudgeCount | lastNudgeAt\n\n2. **Branch 1: New Submission Flow**\n   - Connect Typeform credential on \"New Form Submission\" trigger\n   - Select your form from dropdown\n   - Verify field names in \"Extract Name and Phone\" match your form exactly\n   - Connect Twilio credential on \"Send Welcome SMS\"\n   - Set your Twilio From number (+1XXXXXXXXXX)\n   - Connect Google Sheets credential on \"Track Submissions\"\n   - Select your tracking spreadsheet and sheet\n\n3. **Branch 2: SMS Reply Handler**\n   - Connect Twilio credential on \"Incoming SMS Reply\" trigger\n   - Connect Google Sheets credential on \"Mark as Replied\"\n   - Select same tracking spreadsheet\n\n4. **Branch 3: Automated Nudge System**\n   - Connect Google Sheets credential on \"Get Non-Responders\"\n   - Select same tracking spreadsheet\n   - Connect Twilio credential on \"Send Nudge SMS\"\n   - Set your Twilio From number (same as Branch 1)\n   - Connect Google Sheets credential on \"Update Nudge Count\"\n\n5. **Test & Activate**\n   - Submit a test form with your own phone\n   - Confirm welcome SMS arrives\n   - Reply to the SMS and check that Google Sheets updates\n   - Toggle workflow Active\n\n**How It Works Together**\n\n1. Customer submits form \u2192 Welcome SMS sent + tracked in Sheets\n2. If customer replies \u2192 Sheets updated, nudges stop\n3. If no reply after 24 hours \u2192 Nudge 1 sent\n4. If still no reply after another 24 hours \u2192 Nudge 2 sent\n5. After 2 nudges or any reply \u2192 System stops contacting that customer\n\n**Troubleshooting**\n- SMS not sending \u2192 Check Twilio credentials, confirm From number is active\n- Nudges not sending \u2192 Verify Google Sheets has data, check \"Get Non-Responders\" filters\n- Reply not stopping nudges \u2192 Confirm \"Mark as Replied\" is updating the correct sheet\n- Schedule not running \u2192 Make sure workflow is Active\n\n---\n\n## Learn more at [Orchestrate Academy](https://www.orchestrate.academy)"
      },
      "typeVersion": 1
    },
    {
      "id": "20197c1f-f7ac-4718-9720-c048dce07dd2",
      "name": "New Form Submission",
      "type": "n8n-nodes-base.typeformTrigger",
      "position": [
        240,
        288
      ],
      "parameters": {
        "formId": "<__PLACEHOLDER_VALUE__Select your Typeform form from the dropdown__>",
        "onlyAnswers": false
      },
      "typeVersion": 1.1
    },
    {
      "id": "00ebbec1-a2df-474f-bdbc-dedf38672070",
      "name": "Extract Name and Phone",
      "type": "n8n-nodes-base.set",
      "position": [
        464,
        288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "field-name",
              "name": "customerName",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "field-phone",
              "name": "customerPhone",
              "type": "string",
              "value": "={{ $json.phone }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "14723d1d-422c-4d34-b57b-be487d6a7477",
      "name": "Send Welcome SMS",
      "type": "n8n-nodes-base.twilio",
      "position": [
        688,
        192
      ],
      "parameters": {
        "to": "={{ $json.customerPhone }}",
        "from": "<__PLACEHOLDER_VALUE__Your Twilio phone number e.g. +1234567890__>",
        "message": "=Hi {{ $json.customerName }}, thanks for booking with us! We look forward to seeing you soon. Reply STOP to opt out.",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "0ea2e481-1a18-4cb0-8a40-5fbc659f565e",
      "name": "Track Submissions",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        912,
        384
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "40dc1744-9a42-4bc4-8dd3-c82dc8333682",
      "name": "Prepare Tracking Data",
      "type": "n8n-nodes-base.set",
      "position": [
        688,
        384
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "customerName",
              "type": "string",
              "value": "={{ $json.customerName }}"
            },
            {
              "id": "id-2",
              "name": "customerPhone",
              "type": "string",
              "value": "={{ $json.customerPhone }}"
            },
            {
              "id": "id-3",
              "name": "submittedAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            },
            {
              "id": "id-4",
              "name": "repliedAt",
              "type": "string",
              "value": ""
            },
            {
              "id": "id-5",
              "name": "nudgeCount",
              "type": "number",
              "value": 0
            },
            {
              "id": "id-6",
              "name": "lastNudgeAt",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fb6f8e35-1132-43c7-81af-e9a3ba519d78",
      "name": "Incoming SMS Reply",
      "type": "n8n-nodes-base.twilioTrigger",
      "position": [
        256,
        1168
      ],
      "parameters": {
        "updates": [
          "com.twilio.messaging.inbound-message.received"
        ]
      },
      "typeVersion": 1
    },
    {
      "id": "4aaf9fd8-55f0-4e6c-abfc-85a69a8e91e8",
      "name": "Mark as Replied",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        704,
        1168
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "2ae9f1ed-7453-490f-b2a1-44b22f9c0a71",
      "name": "Prepare Reply Update",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        1168
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "repliedAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e318974b-8545-426f-a55d-a6974b869973",
      "name": "Check for Non-Responders",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        240,
        720
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "05d9ece8-7b6d-44f9-80c5-3bd7dcd23217",
      "name": "Get Non-Responders",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        464,
        720
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "02b1db98-a56d-4a2c-94e4-41ecccfd07c9",
      "name": "Split Non-Responders",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        688,
        720
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "7d130b4d-0010-4500-9a83-5367b67d5a1e",
      "name": "Check If Time for Nudge",
      "type": "n8n-nodes-base.if",
      "position": [
        912,
        720
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ ($json.nudgeCount === 0 && $now.diff(DateTime.fromISO($json.submittedAt), 'hours').hours >= 24) || ($json.nudgeCount === 1 && $json.lastNudgeAt && $now.diff(DateTime.fromISO($json.lastNudgeAt), 'hours').hours >= 24) }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "62a867ce-3c63-4bd8-8938-cec6c5a9f374",
      "name": "Send Nudge SMS",
      "type": "n8n-nodes-base.twilio",
      "position": [
        1136,
        720
      ],
      "parameters": {
        "to": "={{ $json.customerPhone }}",
        "from": "<__PLACEHOLDER_VALUE__Your Twilio phone number e.g. +1234567890__>",
        "message": "=Hi {{ $json.customerName }}, just checking in! We're looking forward to your appointment. Reply anytime if you have questions. Reply STOP to opt out.",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "5ad17dd4-c24e-4bdf-8f30-fd8f6afc2fb9",
      "name": "Update Nudge Count",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1584,
        720
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "bfad877c-de69-410b-870a-b4bdf73d5e6d",
      "name": "Prepare Nudge Update",
      "type": "n8n-nodes-base.set",
      "position": [
        1360,
        720
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "nudgeCount",
              "type": "number",
              "value": "={{ $json.nudgeCount + 1 }}"
            },
            {
              "id": "id-2",
              "name": "lastNudgeAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1332f714-a024-4a96-99ef-e7f8cdd87c65",
      "name": "Branch 1: New Submission Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        160
      ],
      "parameters": {
        "color": "#FFBDBD",
        "width": 480,
        "height": 380,
        "content": "## \ud83c\udfaf Branch 1: New Submission Flow\n\n**Trigger:** Typeform submission\n\n**What It Does:**\n1. Captures new form submissions instantly\n2. Extracts customer name and phone number\n3. Sends personalized welcome SMS via Twilio\n4. Logs submission to Google Sheets tracking table\n\n**Data Tracked:**\n- Customer name & phone\n- Submission timestamp\n- Reply status (empty initially)\n- Nudge count (starts at 0)\n- Last nudge timestamp (empty initially)\n\n**Key Point:** This is the entry point that kicks off the entire customer journey."
      },
      "typeVersion": 1
    },
    {
      "id": "2833ffc0-8386-4e51-99d0-558f610b32db",
      "name": "Branch 2: SMS Reply Handler",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        1040
      ],
      "parameters": {
        "color": "#9EFFA9",
        "width": 480,
        "height": 380,
        "content": "## \ud83d\udcac Branch 3: SMS Reply Handler\n\n**Trigger:** Incoming SMS to your Twilio number\n\n**What It Does:**\n1. Listens for customer SMS replies 24/7\n2. Captures reply timestamp\n3. Updates Google Sheets to mark customer as \"replied\"\n4. **Stops all future nudges** for that customer\n\n**Why This Matters:**\nThe moment a customer replies, they're engaged. No need to nudge them anymore. This branch ensures you respect their response and don't over-communicate.\n\n**Key Point:** This is your \"kill switch\" for the nudge sequence \u2014 one reply stops everything."
      },
      "typeVersion": 1
    },
    {
      "id": "65cae54a-e355-44a6-a79e-07b770160a85",
      "name": "Branch 3: Automated Nudge System",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        576
      ],
      "parameters": {
        "color": "#D7D6FF",
        "width": 480,
        "height": 420,
        "content": "## \u23f0 Branch 2: Automated Nudge System\n\n**Trigger:** Every 6 hours (Schedule)\n\n**What It Does:**\n1. Queries Google Sheets for non-responders\n2. Filters customers who haven't replied AND haven't hit max nudges (2)\n3. Checks if enough time has passed (24 hours since last contact)\n4. Sends follow-up SMS via Twilio\n5. Updates nudge count and timestamp in Google Sheets\n\n**Nudge Schedule:**\n- Nudge 1: 24 hours after welcome SMS\n- Nudge 2: 24 hours after Nudge 1\n- Then stops (max 2 nudges)\n\n**Key Point:** Runs every 6 hours to catch customers at the right time, but only sends when conditions are met."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "59915da1-19f8-43f2-9689-9d1f95a592aa",
  "connections": {
    "Send Nudge SMS": {
      "main": [
        [
          {
            "node": "Prepare Nudge Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Non-Responders": {
      "main": [
        [
          {
            "node": "Split Non-Responders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Incoming SMS Reply": {
      "main": [
        [
          {
            "node": "Prepare Reply Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Form Submission": {
      "main": [
        [
          {
            "node": "Extract Name and Phone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Nudge Update": {
      "main": [
        [
          {
            "node": "Update Nudge Count",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Reply Update": {
      "main": [
        [
          {
            "node": "Mark as Replied",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Non-Responders": {
      "main": [
        [
          {
            "node": "Check If Time for Nudge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Tracking Data": {
      "main": [
        [
          {
            "node": "Track Submissions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Name and Phone": {
      "main": [
        [
          {
            "node": "Send Welcome SMS",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Tracking Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Time for Nudge": {
      "main": [
        [
          {
            "node": "Send Nudge SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Non-Responders": {
      "main": [
        [
          {
            "node": "Get Non-Responders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

πŸ“‹ Customer submits your Typeform β†’ instant personalised welcome SMS fires via Twilio πŸ“Š Submission logged to Google Sheets with name, phone, timestamp, and nudge tracking πŸ’¬ Twilio listens 24/7 for replies β†’ marks customer as responded, stops all future nudges ⏰ Scheduler runs…

Source: https://n8n.io/workflows/15000/ β€” original creator credit. Request a take-down β†’

More Data & Sheets workflows β†’ Β· Browse all categories β†’

Related workflows

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

Data & Sheets

This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.

HTTP Request, Gmail, Twilio +3
Data & Sheets

[](https://youtu.be/6QKbzoWMaXE)

Google Sheets Trigger, Twilio, Google Sheets
Data & Sheets

This workflow is a comprehensive, AI-powered system that acts as a virtual client relationship manager for any appointment-based business. It handles the entire client journeyβ€”from appointment booking

Google Calendar Trigger, Google Sheets, Twilio
Data & Sheets

This template is perfect for Gumroad creators, solopreneurs, digital product sellers, and freelancers who want to track and thank customers automatically β€” without spending time on manual work.

Google Sheets, Gumroad Trigger, Telegram +8
Data & Sheets

typeform feedback workflow. Uses typeformTrigger, googleSheets. Event-driven trigger; 5 nodes.

Typeform Trigger, Google Sheets