{
  "nodes": [
    {
      "id": "24150f37-a6ce-42b2-b134-b68387218a53",
      "name": "Send Lead Notification",
      "type": "n8n-nodes-base.slack",
      "position": [
        608,
        -48
      ],
      "parameters": {
        "text": "=",
        "select": "channel",
        "blocksUi": "={{ $json }}",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "C0A2JFJ3L3Z"
        },
        "messageType": "block",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "508dbddc-a251-4a1e-9048-7bc3ed5451c5",
      "name": "Submission Trigger",
      "type": "n8n-nodes-tallyforms.tallyTrigger",
      "position": [
        -832,
        -32
      ],
      "parameters": {
        "formId": "ODajpY"
      },
      "credentials": {
        "tallyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a8222f5f-7529-42db-b053-b728e256a49b",
      "name": "Append Data (New Sheet)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        176,
        208
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email Address",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email Address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submission Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submission Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submission Time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submission Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "cellFormat": "RAW"
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Create Affiliate Sheet').item.json.sheets[0].properties.sheetId }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Create Affiliate Sheet').item.json.spreadsheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "487993ac-9c89-4a71-bedb-c44b0665c516",
      "name": "Append Data (Existing Sheet)",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        96,
        -48
      ],
      "parameters": {
        "columns": {
          "value": {
            "Name": "={{ $('Extract Form Fields').item.json.Name }}",
            "Phone Number": "={{ $('Extract Form Fields').item.json[\"Phone Number\"] }}",
            "Email Address": "={{ $('Extract Form Fields').item.json[\"Email Address\"] }}",
            "Submission Date": "={{ $('Extract Form Fields').item.json[\"Submission Date\"] }}",
            "Submission Time": "={{ $('Extract Form Fields').item.json[\"Submission Time\"] }}"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email Address",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email Address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submission Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Submission Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submission Time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Submission Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.name }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ea09e9e1-9c11-4fbf-8e88-dc43cf90785d",
      "name": "Extract Form Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -608,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fe3f23e0-2fa7-4324-beea-82ac185da369",
              "name": "Name",
              "type": "string",
              "value": "={{ $json.question_W54VPJ.trim().replace(/\\s+/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase()) }}"
            },
            {
              "id": "a1cb654f-d206-4ae8-ba84-351cbfd99fd5",
              "name": "Email Address",
              "type": "string",
              "value": "={{ $json.question_aYWq09.toLowerCase() }}"
            },
            {
              "id": "5e056aba-3a04-4dd1-9b77-597079ad1b88",
              "name": "Phone Number",
              "type": "string",
              "value": "={{ $json.question_62qERe }}"
            },
            {
              "id": "5cd3cbbb-017b-4505-9d28-a8dc00d39c1a",
              "name": "Affiliation Code",
              "type": "string",
              "value": "={{ $json.question_72QroL.replace(/\\s+/g, '').toLowerCase() }}"
            },
            {
              "id": "5a195b3c-1cf7-4c4c-8663-d14de0370438",
              "name": "Submission Date",
              "type": "string",
              "value": "={{ $json.createdAt.toDateTime().format('MM/dd/yyyy') }}"
            },
            {
              "id": "864adc87-ed5a-48b5-a6e0-0f0f6b402521",
              "name": "Submission Time",
              "type": "string",
              "value": "={{ $json.createdAt.toDateTime().format('HH:mm') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6a75e48c-c5d0-43e0-b0db-69bac678adb0",
      "name": "Find Affiliate Sheet",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -384,
        -32
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "__rl": true,
            "mode": "list",
            "value": "My Drive",
            "cachedResultUrl": "https://drive.google.com/drive/my-drive",
            "cachedResultName": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "1H5x2r0sV0xJGbaZXW-lDjZTUmiZtefv0",
            "cachedResultUrl": "https://drive.google.com/drive/folders/1H5x2r0sV0xJGbaZXW-lDjZTUmiZtefv0",
            "cachedResultName": "Affiliate_Submissions"
          },
          "whatToSearch": "files"
        },
        "options": {
          "fields": [
            "name",
            "id"
          ]
        },
        "resource": "fileFolder",
        "returnAll": true,
        "queryString": "={{ $json[\"Affiliation Code\"]+\"_Submissions\" }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "ec92c2ad-f863-41d4-a5e9-321c37a63679",
      "name": "Sheet Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        -192,
        -32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4b4796c3-f397-4668-87ad-070e2eb002dd",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json.keys() }}",
              "rightValue": "name"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "88049984-cdfe-40e0-bda8-575405d275d6",
      "name": "Create Affiliate Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -384,
        208
      ],
      "parameters": {
        "title": "={{ $('Extract Form Fields').item.json[\"Affiliation Code\"]+\"_Submissions\" }}",
        "options": {},
        "resource": "spreadsheet",
        "sheetsUi": {
          "sheetValues": [
            {
              "title": "={{ $('Extract Form Fields').item.json[\"Affiliation Code\"]+\"_Submissions\" }}"
            }
          ]
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "74bbe628-29f5-4758-a85b-49a5ae34bb80",
      "name": "Format Row Data",
      "type": "n8n-nodes-base.code",
      "position": [
        16,
        208
      ],
      "parameters": {
        "jsCode": "return [{\n  json: {\n    \"Name\": $('Extract Form Fields').first().json.Name,\n    \"Email Address\": $('Extract Form Fields').first().json[\"Email Address\"],\n    \"Phone Number\": $('Extract Form Fields').first().json[\"Phone Number\"],\n    \"Submission Date\": $('Extract Form Fields').first().json[\"Submission Date\"],\n    \"Submission Time\": $('Extract Form Fields').first().json[\"Submission Time\"]\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b7da68d6-7f5c-429f-bb21-61e84b18dda1",
      "name": "Build Slack Message",
      "type": "n8n-nodes-base.code",
      "position": [
        368,
        -48
      ],
      "parameters": {
        "jsCode": "const blocks = [\n  {\n    \"type\": \"header\",\n    \"text\": {\n        \"type\": \"plain_text\",\n        \"text\": \"\ud83c\udf89 New Lead Received!\",\n        \"emoji\": true\n    }\n  },\n  {\n    \"type\": \"section\",\n    \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": `*\ud83d\udc64 Name:* ${ $input.first().json.Name }`\n    }\n  },\n  {\n    \"type\": \"section\",\n    \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": `*\ud83d\udce7 Email Address:* ${ $input.first().json[\"Email Address\"] }`\n    }\n  }\n];\n\nconst phone_number = $input.first().json[\"Phone Number\"];\n\nif ( phone_number !== \"\") {\n   blocks.push({\n      \"type\": \"section\",\n      \"text\": {\n          \"type\": \"mrkdwn\",\n          \"text\": `*\ud83d\udcde Phone Number:* ${ phone_number }`\n      }\n    }\n  ); \n}\n\nblocks.push({\n    \"type\": \"section\",\n    \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": `_Affiliated from *${ $('Extract Form Fields').first().json[\"Affiliation Code\"] }*_`\n    }\n  }\n);\n\nreturn {\n  \"json\": {\n      \"blocks\": blocks\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "b3f6b059-75a8-483d-abda-6f32b65ed6f8",
      "name": "Move to Target Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -192,
        208
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.spreadsheetId }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1H5x2r0sV0xJGbaZXW-lDjZTUmiZtefv0",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1H5x2r0sV0xJGbaZXW-lDjZTUmiZtefv0",
          "cachedResultName": "Affiliate_Submissions"
        },
        "operation": "move"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "fb116606-8992-4e53-88b4-7dd37ea2391b",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1552,
        -144
      ],
      "parameters": {
        "width": 656,
        "height": 560,
        "content": "## How it works\n1. **Form Trigger**: Listens for new public submissions via a Tally.so webhook.\n2. **Data Routing**: Extracts the affiliation code and searches Google Drive for an existing matching spreadsheet.\n3. **Sheet Management**: Automatically appends the lead to the correct affiliate sheet. If no sheet exists, it creates a new one and moves it to the target Drive folder.\n4. **Notification**: Formats the lead details and sends an instant alert to a specified Slack channel.\n\n## Setup Process\n- [ ] Deploy the n8n environment using Docker Compose.\n- [ ] Connect your **Tally.so** API Key.\n- [ ] Create a Google Drive folder (e.g., `Affiliate_Submissions`) and copy its Folder ID.\n- [ ] Set up Google OAuth credentials and connect the **Google Drive** and **Google Sheets** nodes.\n- [ ] Connect a **Slack** Bot Token (`xoxb-...`) with `chat:write` scope.\n- [ ] Update node parameters: Add the Tally form, Drive Folder IDs, and Slack Channel ID.\n\n## Customization\n- **Form Fields**: Modify your Tally form to capture extra info (like budget or company size) and map the new fields in n8n.\n- **Target Location**: Change the target Google Drive directory for generated affiliate sheets.\n- **Alerts**: Adjust the Slack message template to @mention specific sales team members or include custom formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "92d0aad1-555e-42e6-9b30-b494c65a7466",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 272,
        "content": "## Capture Form Submissions\nTriggers the workflow instantly when a new lead submits the Tally form and extracts their data."
      },
      "typeVersion": 1
    },
    {
      "id": "9bee6577-47e4-4a80-8e5c-a20d40e63fbd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 528,
        "content": "## Affiliate Sheet Management\nSearches for an existing affiliate spreadsheet in Google Drive, branching to create and organize a new one if missing."
      },
      "typeVersion": 1
    },
    {
      "id": "52184583-ccbc-404a-826b-224fb1582f95",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 528,
        "content": "## Record Lead Data\nAppends the captured lead information as a new row in the appropriate Google Sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "513b8123-92cb-4a92-be10-a900191a1296",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 368,
        "content": "## Team Notification\nConstructs a formatted message summarizing the lead and delivers it to a Slack channel."
      },
      "typeVersion": 1
    },
    {
      "id": "e2f5f5b0-fd29-4889-9916-95174574a11d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -64
      ],
      "parameters": {
        "color": 3,
        "width": 192,
        "height": 272,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\nThe Slack app must be added/invited to the target channel to successfully post messages."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Sheet Exists?": {
      "main": [
        [
          {
            "node": "Append Data (Existing Sheet)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Affiliate Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Row Data": {
      "main": [
        [
          {
            "node": "Append Data (New Sheet)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Submission Trigger": {
      "main": [
        [
          {
            "node": "Extract Form Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Slack Message": {
      "main": [
        [
          {
            "node": "Send Lead Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Form Fields": {
      "main": [
        [
          {
            "node": "Find Affiliate Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Affiliate Sheet": {
      "main": [
        [
          {
            "node": "Sheet Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Move to Target Folder": {
      "main": [
        [
          {
            "node": "Format Row Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Affiliate Sheet": {
      "main": [
        [
          {
            "node": "Move to Target Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Lead Notification": {
      "main": [
        []
      ]
    },
    "Append Data (New Sheet)": {
      "main": [
        [
          {
            "node": "Build Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Data (Existing Sheet)": {
      "main": [
        [
          {
            "node": "Build Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}