{
  "id": "t6aeFxOJar5rX33K",
  "name": "Automated Sales Proposal & Summary Generator using GPT-4o, Sheets & Drive",
  "tags": [],
  "nodes": [
    {
      "id": "777285a5-1eef-449f-a871-d49ad20559ed",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -320,
        80
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "c0b2ce0c-9203-4ebf-91b7-d653a32cda10",
      "name": "Retrieve Lead Records from Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -32,
        80
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 46113423,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM/edit#gid=46113423",
          "cachedResultName": "outreach automation"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM/edit?usp=drivesdk",
          "cachedResultName": "sample_leads_50"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "96d9cd04-cbed-4b76-b834-cfd9879a50c4",
      "name": "Validate Lead Data Payload",
      "type": "n8n-nodes-base.if",
      "position": [
        224,
        80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e2adb005-2b3c-4d1e-8445-442df1fe925a",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "=/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test({{ $json.Email }})",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f62f1223-0844-4508-8890-81005623a89c",
      "name": "Log Invalid Leads to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        560,
        704
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "8494847c-18f2-4acf-9df9-631cc6171385",
      "name": "Filter for Booked Leads",
      "type": "n8n-nodes-base.if",
      "position": [
        624,
        64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b7913fcd-b70c-47fd-a926-d09a0086b40e",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json[\"Booking Status\"] }}",
              "rightValue": "BOOKED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "aa70865b-a489-409b-a0f7-33c90c80be6d",
      "name": "Configure GPT-4o Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        1040,
        656
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "03677f7a-0d0a-4cbc-9eef-90c3b152190c",
      "name": "Configure GPT-4o Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        2592,
        304
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f895ef8e-f5fe-42d7-aa1c-78048a47e31f",
      "name": "Generate Sales Collateral (AI)",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        960,
        48
      ],
      "parameters": {
        "text": "=Generate personalized sales materials for this booked lead:\n\nCompany Name: {{ $json[\"Company Name\"] }}\nContact Person: {{ $json[\"Contact Person\"] }}\nJob Title: {{ $json[\"Job Title\"] }}\nEmail: {{ $json[\"Email\"] }}\nPhone: {{ $json[\"Phone\"] }}\nIndustry: {{ $json[\"Industry\"] }}\nLocation: {{ $json[\"Location\"] }}\nLead Source: {{ $json[\"Lead Source\"] }}\nBooking Status: {{ $json[\"Booking Status\"] }}\nClient Message: {{ $json[\"ClientMessage\"] }}\n\nInstructions:\n1. Write a short \"Sales Summary\" (under 80 words) for an email follow-up.\n2. Write a \"One-Pager\" (headline + 3 bullet points + short CTA).\n3. Write a \"Proposal Draft\" (intro, scope, timeline, and next steps).\n\nReturn everything as JSON:\n{\n  \"summary\": \"...\",\n  \"one_pager\": \"...\",\n  \"proposal\": \"...\"\n}\n",
        "options": {
          "systemMessage": "=You are an AI sales assistant that creates short, friendly, and professional B2B sales materials. \nYour task is to generate:\n1. A short Sales Summary (for email follow-up),\n2. A One-Pager (pitch overview),\n3. A Proposal Draft (detailed offer).\n\nEach output must be relevant to the lead\u2019s company, job title, and industry. \nKeep tone professional and persuasive. \nOutput everything in JSON format with three fields: \"summary\", \"one_pager\", and \"proposal\".\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a47f8735-b2e1-419f-8d0a-a19c7571c284",
      "name": "Parse AI JSON Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1328,
        48
      ],
      "parameters": {
        "jsCode": "// Process each item (one per lead)\nreturn items.map(item => {\n  // Get raw AI text output\n  let text = item.json.output || \"\";\n\n  // \ud83e\uddf9 Step 1: Clean the text (remove ```json, ```, and unwanted quotes)\n  text = text\n    .replace(/```json/g, \"\")   // remove ```json\n    .replace(/```/g, \"\")       // remove ```\n    .replace(/\\n/g, \" \")       // flatten newlines\n    .trim();\n\n  // \ud83e\udde0 Step 2: Try parsing it as JSON\n  let parsed;\n  try {\n    parsed = JSON.parse(text);\n  } catch (err) {\n    parsed = { error: \"Invalid JSON\", raw: text };\n  }\n\n  // \u2705 Step 3: Return clean structured data\n  return {\n    json: {\n      summary: parsed.summary || \"\",\n      one_pager: parsed.one_pager || parsed.onePager || \"\",\n      proposal: parsed.proposal || \"\",\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e9645b11-a174-4b8c-837a-965e96891ea5",
      "name": "Convert Collateral into Text Reports",
      "type": "n8n-nodes-base.code",
      "position": [
        1600,
        48
      ],
      "parameters": {
        "jsCode": "// n8n automatically provides Buffer, no need to import it\n\nreturn items.map((item, index) => {\n  const data = item.json;\n\n  // Build text report for each lead\n  let report = \"\";\n  report += `Lead Report #${index + 1}\\n`;\n  report += \"===================================\\n\\n\";\n\n  // === Summary ===\n  report += `\ud83d\udccb SALES SUMMARY\\n${data.summary}\\n\\n`;\n\n  // === One Pager ===\n  const onePager = data.one_pager || {};\n  report += `\ud83d\udcc4 ONE PAGER\\nHeadline: ${onePager.headline || \"N/A\"}\\n`;\n  if (onePager.bullet_points && onePager.bullet_points.length > 0) {\n    onePager.bullet_points.forEach(p => (report += `\u2022 ${p}\\n`));\n  }\n  report += `\\nCTA: ${onePager.cta || \"N/A\"}\\n\\n`;\n\n  // === Proposal ===\n  const proposal = data.proposal || {};\n  report += `\ud83d\udcd1 PROPOSAL\\n`;\n  report += `Introduction: ${proposal.introduction || proposal.intro || \"N/A\"}\\n\\n`;\n\n  // Scope\n  if (proposal.scope) {\n    report += `Scope:\\n`;\n    if (Array.isArray(proposal.scope)) {\n      proposal.scope.forEach(s => (report += `- ${s}\\n`));\n    } else {\n      report += `- ${proposal.scope}\\n`;\n    }\n  }\n\n  // Timeline\n  if (proposal.timeline) {\n    report += `\\nTimeline:\\n`;\n    if (Array.isArray(proposal.timeline)) {\n      proposal.timeline.forEach(t => (report += `- ${t}\\n`));\n    } else {\n      report += `- ${proposal.timeline}\\n`;\n    }\n  }\n\n  report += `\\nNext Steps:\\n${proposal.next_steps || \"N/A\"}\\n\\n`;\n  report += \"===================================\\n\";\n\n  // \u2705 Convert text to binary data (no imports needed)\n  const buffer = Buffer.from(report, \"utf8\");\n\n  return {\n    json: {\n      fileName: `Lead_Report_${index + 1}.txt`,\n    },\n    binary: {\n      data: {\n        data: buffer.toString(\"base64\"),\n        mimeType: \"text/plain\",\n        fileName: `Lead_Report_${index + 1}.txt`,\n      },\n    },\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "883fc755-e17b-4b52-a0bf-dad261233226",
      "name": "Upload Sales Collateral to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1952,
        48
      ],
      "parameters": {
        "name": "={{$json[\"fileName\"]}}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1WVD9VVLyV34NCynIizt9R2xnTP5SsTfj",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1WVD9VVLyV34NCynIizt9R2xnTP5SsTfj",
          "cachedResultName": "collatral data"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "7dc0e8b7-c4c0-402b-a07b-d08d17f0a310",
      "name": "Map Uploaded Files with Lead Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2416,
        -560
      ],
      "parameters": {
        "jsCode": "// \u2705 FIXED: Correct way to reference previous node data in n8n\n\n// Get all leads from the \"Filter for Booked Leads\" node\n// Use $items() function to get all items from a specific node\nconst allLeads = $('Filter for Booked Leads').all();\n\n// OR if that doesn't work, use this alternative:\n// const allLeads = $input.all();\n\nconsole.log(\"Total leads from Filter node:\", allLeads.length);\nconsole.log(\"Total files uploaded:\", items.length);\n\nreturn items.map((item, index) => {\n  \n  // 1\ufe0f\u20e3 Get file link from current Upload file node output\n  const fileLink = \n    item.json.webViewLink || \n    item.json.webContentLink || \n    null;\n  \n  const fileName = item.json.name || `Lead_Report_${index + 1}.txt`;\n\n  // 2\ufe0f\u20e3 Match with corresponding lead data by index\n  const leadData = allLeads[index]?.json || {};\n  \n  // 3\ufe0f\u20e3 Extract lead information\n  const email = leadData.Email || null;\n  const companyName = leadData[\"Company Name\"] || \"N/A\";\n  const contactPerson = leadData[\"Contact Person\"] || \"N/A\";\n  const jobTitle = leadData[\"Job Title\"] || \"N/A\";\n\n  // 4\ufe0f\u20e3 Debug logging\n  console.log(`Processing item ${index + 1}:`, {\n    email,\n    companyName,\n    hasFileLink: !!fileLink\n  });\n\n  // 5\ufe0f\u20e3 Validation\n  if (!email || !fileLink) {\n    return { \n      json: { \n        skip: true, \n        message: `Missing data for ${companyName || 'Unknown Company'}`,\n        details: {\n          itemIndex: index + 1,\n          hasEmail: !!email,\n          hasFileLink: !!fileLink,\n          fileName: fileName,\n          email: email || \"MISSING\",\n          fileLink: fileLink || \"MISSING\"\n        }\n      } \n    };\n  }\n\n  // 6\ufe0f\u20e3 Return complete data for Sheet update\n  return {\n    json: {\n      Email: email,\n      ProposalLink: fileLink,\n      FileName: fileName,\n      CompanyName: companyName,\n      ContactPerson: contactPerson,\n      JobTitle: jobTitle,\n      UpdatedAt: new Date().toISOString(),\n      skip: false\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "96bf790b-3c72-4b5b-a6fc-441f54190bb7",
      "name": "Update Lead Record with Proposal Link",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2848,
        -560
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $json.Email }}",
            "Proposal Link": "={{ $json.ProposalLink }}"
          },
          "schema": [
            {
              "id": "Company Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Company Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Contact Person",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Contact Person",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Job Title",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Job Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Industry",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Industry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Location",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Lead Source",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Lead Source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Booking Status",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Booking Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ClientMessage",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "ClientMessage",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LastUpdated",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "LastUpdated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ThreadID",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "ThreadID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Proposal Link",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Proposal Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 46113423,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM/edit#gid=46113423",
          "cachedResultName": "outreach automation"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/17rcNd_ZpUQLm0uWEVbD-NY6GyFUkrD4BglvawlyBygM/edit?usp=drivesdk",
          "cachedResultName": "sample_leads_50"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "c7cb7d0c-649b-42e9-9240-80a145ead27f",
      "name": "Generate Sales Summary Email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2592,
        48
      ],
      "parameters": {
        "text": "=You are an expert sales reporting assistant.  \nBased on the uploaded lead reports below, write a short **HTML-formatted** sales summary email section.\n\nInput Details:\n- Total Booked Leads: {{ $json[\"totalLeads\"] || \"0\" }}\n- Uploaded Files:\n{{ $json[\"fileListText\"] || \"No uploaded file data available\" }}\n\nInstructions:\n1. Write the message in **HTML format**.\n2. Include:\n   - A title section (e.g., \ud83d\udcca Sales Report Summary)\n   - A line showing total leads\n   - A bullet list with file names and links\n   - A short \u201cSales Insights\u201d paragraph (2\u20134 sentences) based on the leads.\n3. Use professional formatting (e.g., <h2>, <ul>, <p> tags).\n4. Do not include <html> or <body> \u2014 only return the inner HTML section.\n5. Keep tone: short, friendly, and analytical.\n",
        "options": {
          "systemMessage": "=You are an AI assistant that generates professional HTML snippets for automated sales reports.  \nAlways return clean, valid HTML \u2014 no markdown, no JSON \u2014 just formatted HTML ready to embed in an email body.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2a05b783-c46f-4af6-ad3d-bfff4846f41d",
      "name": "Send Sales Summary Email via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2992,
        48
      ],
      "parameters": {
        "sendTo": "=newscctv22@gmail.com",
        "message": "={{ $json.output }}",
        "options": {},
        "subject": "=Sales Collateral Summary "
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e38eb667-93f5-49c7-8339-587d80081bdb",
      "name": "Aggregate Uploaded File Metadata",
      "type": "n8n-nodes-base.code",
      "position": [
        2320,
        48
      ],
      "parameters": {
        "jsCode": "let uploadedFiles = [];\nlet totalLeads = 0;\n\n// \u2705 Array for structured file data (for downstream use)\nlet fileList = [];\n\nfor (const item of items) {\n  // 1\ufe0f\u20e3 Get the real file name\n  const fileName =\n    item.json.name ||\n    item.binary?.data?.fileName ||\n    item.json.originalFilename ||\n    \"Unnamed_Report.txt\";\n\n  // 2\ufe0f\u20e3 Get the Drive link\n  const link =\n    item.json.webViewLink ||\n    item.json.webContentLink ||\n    null;\n\n  // 3\ufe0f\u20e3 If valid, push into both arrays\n  if (link) {\n    uploadedFiles.push(\n      `<li><a href=\"${link}\" target=\"_blank\" style=\"color:#1a73e8; text-decoration:none; font-weight:bold;\">${fileName}</a></li>`\n    );\n\n    fileList.push({\n      fileName,\n      link,\n    });\n\n    totalLeads++;\n  }\n}\n\n// 4\ufe0f\u20e3 Build HTML list\nconst fileListText =\n  uploadedFiles.length > 0\n    ? `<ul>${uploadedFiles.join(\"\")}</ul>`\n    : \"<p>No files were uploaded for this report.</p>\";\n\n// 5\ufe0f\u20e3 Return everything\nreturn [\n  {\n    json: {\n      totalLeads,\n      fileList,\n      fileListText,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ff89bb1a-43f2-4818-9c2a-ae2380004c1d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        -688
      ],
      "parameters": {
        "width": 736,
        "height": 528,
        "content": "## \ud83d\ude80 Automated Sales Proposal & Summary Generator using GPT-4o, Sheets & Drive\nAutomatically generates personalized **Sales Collateral** (Summary, One-Pager, and Proposal) for each booked lead using GPT-4o.  \nUploads materials to Google Drive, updates lead records in Sheets, and sends a professional HTML summary email report.\n\n### \ud83d\udd39 Workflow Highlights\n1\ufe0f\u20e3 Fetch booked leads from Google Sheets  \n2\ufe0f\u20e3 Validate data and skip invalid entries  \n3\ufe0f\u20e3 Generate 3 AI-based materials (Summary, One-Pager, Proposal)  \n4\ufe0f\u20e3 Convert AI output to formatted text files  \n5\ufe0f\u20e3 Upload collateral to Google Drive  \n6\ufe0f\u20e3 Map Drive links to corresponding leads in Google Sheets  \n7\ufe0f\u20e3 Generate HTML Sales Summary Report  \n8\ufe0f\u20e3 Send report to the marketing/sales inbox  \n\n### \ud83d\udd39 Tools Used\n- Google Sheets \u2192 Lead database  \n- GPT-4o (Azure OpenAI) \u2192 Collateral generation & summary writing  \n- Google Drive \u2192 Document storage  \n- Gmail \u2192 Email delivery  \n- JavaScript \u2192 Parsing & file conversion\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4938a972-69ef-482a-a151-3d240d1dbee0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -112,
        -176
      ],
      "parameters": {
        "color": 7,
        "height": 480,
        "content": "## \ud83e\uddfe Retrieve Lead Records from Google Sheets  \nFetches lead data (Company Name, Email, Booking Status, etc.) from the  sheet.  \nActs as the workflow\u2019s entry point.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f2783d33-207f-45ba-badc-45a8504aa3ef",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -144
      ],
      "parameters": {
        "color": 7,
        "height": 384,
        "content": "## \ud83e\udde9 Validate Lead Data Payload  \nChecks if lead records have a valid email address.  \n\u2705 Valid \u2192 Sent for further processing  \n\u274c Invalid \u2192 Logged in the \u201cInvalid Leads\u201d sheet.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "36fd3162-6f11-4eb5-ad6d-38ef92c4cdce",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        384
      ],
      "parameters": {
        "color": 7,
        "height": 496,
        "content": "## \u26a0\ufe0f Log Invalid Leads to Google Sheets  \nStores any malformed or missing lead entries for later cleanup.  \nPrevents workflow interruption due to bad data.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6f580e0a-4ac0-4e11-a6ec-784e1ac12f89",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -160
      ],
      "parameters": {
        "color": 7,
        "height": 416,
        "content": "## \ud83c\udfaf Filter for Booked Leads  \nFilters only leads marked as \u201cBOOKED\u201d.  \nEnsures collateral generation only runs for confirmed clients.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3e90c054-d86d-43a9-bc9a-7f8205cd180f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        400
      ],
      "parameters": {
        "color": 7,
        "height": 416,
        "content": "## \u2699\ufe0f Configure GPT-4o Model  \nConnects Azure OpenAI GPT-4o for downstream nodes.  \nUsed for both sales collateral and HTML summary generation.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b5d84a31-27ec-4e6d-8aad-c3b353528b99",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 368,
        "height": 496,
        "content": "## \ud83e\udde0 Generate Sales Collateral (AI)  \nGPT-4o generates 3 structured outputs per booked lead:\n1. **Sales Summary** \u2014 short overview  \n2. **One-Pager** \u2014 headline + 3 bullet points + CTA  \n3. **Proposal Draft** \u2014 intro, scope, timeline, and next steps  \nAll returned as structured JSON.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "79046b82-31d1-4167-a3ca-c6b284414e1b",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 496,
        "content": "## \ud83e\uddf9 Parse AI JSON Output  \nCleans and parses the GPT-4o output into usable JSON keys:  \n- `summary`  \n- `one_pager`  \n- `proposal`  \nHandles invalid or raw responses safely.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "78156c47-0768-4e0c-9510-b8bc9484fa7b",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1520,
        -192
      ],
      "parameters": {
        "color": 7,
        "height": 448,
        "content": "## \ud83d\udcc4 Convert Collateral into Text Reports  \nConverts parsed AI output into `.txt` files using Node.js Buffer.  \nEach report contains Summary, One-Pager, and Proposal sections, formatted for readability.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "04ac0c9f-379a-48a1-87db-53e617d46318",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1872,
        -240
      ],
      "parameters": {
        "color": 7,
        "height": 528,
        "content": "## \u2601\ufe0f Upload Sales Collateral to Google Drive  \nUploads each generated `.txt` collateral file to the \u201ccollatral data\u201d folder.  \nReturns Google Drive view & download links for each file.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7b809214-d5b2-4dd1-a78a-92b229118d98",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2256,
        -192
      ],
      "parameters": {
        "color": 7,
        "height": 480,
        "content": "## \ud83d\uddc2\ufe0f Aggregate Uploaded File Metadata  \nBuilds an HTML-formatted list of all uploaded collateral files.  \nIncludes file names, links, and lead count for summary email generation.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1add2ee3-c9a5-4ff0-9063-818d04019863",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2352,
        -864
      ],
      "parameters": {
        "color": 7,
        "height": 512,
        "content": "## \ud83d\udd17 Map Uploaded Files with Lead Data  \nMatches each uploaded file with its corresponding lead using index mapping.  \nPrepares structured data (Email, ProposalLink, FileName, etc.) for updating the sheet.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "eaf359c6-89fb-4048-9daf-60de8aaf94c4",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2768,
        -816
      ],
      "parameters": {
        "color": 7,
        "height": 448,
        "content": "## \u2705 Update Lead Record with Proposal Link  \nUpdates each lead\u2019s Google Sheet row with its proposal file link.  \nKeeps all generated collateral traceable directly from the CRM.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f2049739-3eb0-4fcc-985c-653c637d4155",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2928,
        -224
      ],
      "parameters": {
        "color": 7,
        "height": 480,
        "content": "## \ud83d\udce7 Send Sales Summary Email via Gmail  \nDelivers the AI-generated HTML report to the marketing/sales inbox.  \nSubject: \u201cSales Collateral Summary.\u201d  \nAutomatically formatted for Gmail/Outlook rendering.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1cefbc60-68af-4210-89ee-c4192987b53b",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2528,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 688,
        "content": "## \u2709\ufe0f Generate Sales Summary Email (AI)  \nUses GPT-4o to create a **HTML-formatted sales summary email** that includes:  \n- Total booked leads processed  \n- List of uploaded proposal files (with links)  \n- 2\u20134 sentence insights section  \n- Professional layout (uses <h2>, <ul>, <p> tags)\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6cc051e3-8841-4c67-8d00-640e72d4bb6b",
  "connections": {
    "Parse AI JSON Output": {
      "main": [
        [
          {
            "node": "Convert Collateral into Text Reports",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure GPT-4o Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Sales Collateral (AI)",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Configure GPT-4o Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Sales Summary Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Filter for Booked Leads": {
      "main": [
        [
          {
            "node": "Generate Sales Collateral (AI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Lead Data Payload": {
      "main": [
        [
          {
            "node": "Filter for Booked Leads",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Invalid Leads to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Sales Summary Email": {
      "main": [
        [
          {
            "node": "Send Sales Summary Email via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Sales Collateral (AI)": {
      "main": [
        [
          {
            "node": "Parse AI JSON Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Uploaded File Metadata": {
      "main": [
        [
          {
            "node": "Generate Sales Summary Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Uploaded Files with Lead Data": {
      "main": [
        [
          {
            "node": "Update Lead Record with Proposal Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Collateral into Text Reports": {
      "main": [
        [
          {
            "node": "Upload Sales Collateral to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Retrieve Lead Records from Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Sales Collateral to Google Drive": {
      "main": [
        [
          {
            "node": "Aggregate Uploaded File Metadata",
            "type": "main",
            "index": 0
          },
          {
            "node": "Map Uploaded Files with Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Lead Records from Google Sheets": {
      "main": [
        [
          {
            "node": "Validate Lead Data Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}