{
  "id": "TEMPLATE_WORKFLOW_ID",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Newsletter",
  "tags": [],
  "nodes": [
    {
      "id": "88924d6c-0524-45c6-8982-b43bc79951c6",
      "name": "When clicking 'Test workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "notes": "\ud83d\ude80 START HERE: Click to generate newsletters from pending topics in your Google Sheet",
      "position": [
        -40,
        -180
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "d386375c-ecac-4335-a29a-cd39d9233f07",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "notes": "\u23f0 AUTOMATED: Runs daily to send approved newsletters to clients. Configure timing in settings.",
      "position": [
        -40,
        230
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ca49af2b-0d7f-4aa1-b63c-dc828bfeb7d6",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "notes": "\ud83d\udd04 BATCH PROCESSING: Handles multiple client emails efficiently. Prevents rate limiting and ensures reliable delivery.",
      "position": [
        840,
        230
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "2208eb0e-a0aa-4082-905b-166fa521b75a",
      "name": "Get topic from newsletter sheet",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcca FETCH TOPICS: Gets all pending newsletter topics from your Google Sheet. Only processes items with 'Pending' status.",
      "position": [
        180,
        -180
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "Pending",
              "lookupColumn": "Status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "2b47d026-a70e-40d5-a2c4-4f07551f0eef",
      "name": "Validate Status as Pending",
      "type": "n8n-nodes-base.if",
      "notes": "\u2705 DATE FILTER: Only processes newsletters scheduled for today. Prevents processing old or future-dated items.",
      "position": [
        400,
        -180
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2d883784-6213-45b4-944f-55c0ffcc19b6",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Date }}",
              "rightValue": "={{ new Date().toLocaleDateString('en-US') }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "448be138-181b-4bda-95dd-66d632635256",
      "name": "Create HTML for Newsletter",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "notes": "\ud83e\udd16 AI MAGIC: Uses GPT-4O to create professional HTML newsletter content. Customize the prompt here for different styles and tones.",
      "position": [
        620,
        -180
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Create an HTML newsletter on the topic:{{ $json.Topic }}. \n Include these hook sentences:{{ $json.hooks }} . \n Structure with a header, body paragraphs, and footer\n"
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "f552d84a-9d14-4cb1-89d7-d99bc9784a5e",
      "name": "Prepare Data to create word doc",
      "type": "n8n-nodes-base.code",
      "notes": "\ud83d\udd27 FORMAT PREP: Converts AI-generated HTML into proper file format for Google Drive upload. Auto-generates timestamped filename.",
      "position": [
        996,
        -180
      ],
      "parameters": {
        "jsCode": "// Get HTML content from current input\nconst htmlContent = $input.first().json.message.content;\n\n// Generate filename with current date\nconst currentDate = new Date().toISOString().split('T')[0];\nconst filename = `document_${currentDate}.html`;\n\n// Convert string to binary buffer\nconst buffer = Buffer.from(htmlContent, 'utf8');\n\nreturn [{\n  json: {\n    fileName: filename,\n    mimeType: 'text/html'\n  },\n  binary: {\n    data: buffer\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f2421bc4-2045-46c9-beab-ff5459b4a17c",
      "name": "Upload doc to google drive",
      "type": "n8n-nodes-base.googleDrive",
      "notes": "\ud83d\udcbe CLOUD STORAGE: Saves the newsletter to your Google Drive 'Newsletter' folder. Creates shareable link for easy access.",
      "position": [
        1216,
        -180
      ],
      "parameters": {
        "name": "=newsletter-{{ $('Get topic from newsletter sheet').item.json.Date }}.html",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultName": "Newsletter"
        },
        "inputDataFieldName": "=data"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "6b39c176-25cf-4b47-a25c-8b886f0709ba",
      "name": "Send an email to admin",
      "type": "n8n-nodes-base.gmail",
      "notes": "\ud83d\udce7 ADMIN ALERT: Notifies you when newsletter is ready for review. Update email address to yours. Includes Google Drive link.",
      "position": [
        1436,
        -180
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=Review the attached newsletter  {{ $json.webViewLink }}",
        "options": {},
        "subject": "=Newsletter Preview for {{ $('Get topic from newsletter sheet').item.json.Date }} and HTML body attached",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8e7c42de-3fd8-4acc-afdb-83491674bf7b",
      "name": "Update Status as Generated",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcdd TRACKING UPDATE: Marks newsletter as 'Generated' in Google Sheet. Adds timestamp and document URL for audit trail.",
      "position": [
        1656,
        -180
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Get topic from newsletter sheet').item.json.Date }}",
            "Status": "Generated",
            "Timestamp": "={{ $('Upload doc to google drive').item.json.createdTime }}",
            "Document URL": "={{ $('Upload doc to google drive').item.json.webViewLink }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hooks",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "hooks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Document URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Document URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0f6f5d15-dbd9-415b-923d-81809708542d",
      "name": "Validate Status as Approved",
      "type": "n8n-nodes-base.if",
      "notes": "\u2705 APPROVAL CHECK: Only sends newsletters with 'Approved' status. Prevents accidental sending of unreviewed content.",
      "position": [
        400,
        230
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b3730359-d11f-4a9c-aa5f-f4dcc1f0702e",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Approved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f03eed28-1c06-401e-8c4b-ba5b5891b048",
      "name": "Pick records to send email to client",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udcec CLIENT QUEUE: Fetches all newsletter records ready for client delivery. Runs on schedule to automate sending.",
      "position": [
        180,
        230
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "23ae0b93-f121-493b-a0d1-80fc748137a2",
      "name": "Get Client email address",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\ud83d\udc65 CLIENT LOOKUP: Gets email addresses from the 'Email' sheet. Maintains separate client database for easy management.",
      "position": [
        620,
        230
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_EMAIL_SHEET_GID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=YOUR_EMAIL_SHEET_GID",
          "cachedResultName": "Email"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4281a45c-5af5-4311-bca6-aaee14152afc",
      "name": "Send email to client",
      "type": "n8n-nodes-base.gmail",
      "notes": "\ud83d\udce4 CLIENT DELIVERY: Sends newsletter to individual clients via Gmail. Customize subject line and message template here.",
      "position": [
        1060,
        280
      ],
      "parameters": {
        "sendTo": "={{ $json.Email }}",
        "message": "=Attached is the newsletter  {{ $('Pick records to send email to client').item.json['Document URL'] }}",
        "options": {},
        "subject": "Newsletter",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c2634a85-88f6-49b5-bd14-6e03336a49f2",
      "name": "Update status as Sent",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "\u2705 COMPLETION TRACKING: Marks newsletter as 'Sent' to prevent duplicate deliveries. Maintains complete audit trail.",
      "position": [
        1060,
        80
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Pick records to send email to client').item.json.Date }}",
            "Status": "Sent"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Topic",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hooks",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "hooks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Document URL",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Document URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit#gid=0",
          "cachedResultName": "Topic"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID_HERE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID_HERE/edit?usp=drivesdk",
          "cachedResultName": "Newsletter"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "TEMPLATE_VERSION_ID",
  "connections": {
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Update status as Sent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send email to client",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Pick records to send email to client",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send email to client": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send an email to admin": {
      "main": [
        [
          {
            "node": "Update Status as Generated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Client email address": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create HTML for Newsletter": {
      "main": [
        [
          {
            "node": "Prepare Data to create word doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload doc to google drive": {
      "main": [
        [
          {
            "node": "Send an email to admin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Status as Pending": {
      "main": [
        [
          {
            "node": "Create HTML for Newsletter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Status as Approved": {
      "main": [
        [
          {
            "node": "Get Client email address",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Test workflow'": {
      "main": [
        [
          {
            "node": "Get topic from newsletter sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get topic from newsletter sheet": {
      "main": [
        [
          {
            "node": "Validate Status as Pending",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Data to create word doc": {
      "main": [
        [
          {
            "node": "Upload doc to google drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick records to send email to client": {
      "main": [
        [
          {
            "node": "Validate Status as Approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}