{
  "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
          }
        ]
      ]
    }
  }
}