This workflow corresponds to n8n.io template #16364 — we link there as the canonical source.
This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "SMzmcQfryP0eGNSK",
"name": "A (LITE) \u2014 Newsletter: Daily Sender [FREE]",
"tags": [],
"nodes": [
{
"id": "schedule-lite",
"name": "Daily at 08:00",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
0,
400
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"typeVersion": 1.3
},
{
"id": "config-lite",
"name": "\u2699\ufe0f Config",
"type": "n8n-nodes-base.code",
"position": [
224,
400
],
"parameters": {
"jsCode": "// ========================================\n// CONFIGURATION \u2014 edit only this node\n// ========================================\n// sheetId: Your Google Sheet ID (from the URL between /d/ and /edit)\nconst sheetId = 'YOUR-GOOGLE-SHEET-ID';\n\nreturn [{ json: { sheetId } }];"
},
"typeVersion": 2
},
{
"id": "read-products-lite",
"name": "Read Products",
"type": "n8n-nodes-base.googleSheets",
"position": [
448,
400
],
"parameters": {
"options": {},
"sheetName": {
"mode": "name",
"value": "newsletter_products"
},
"documentId": {
"mode": "id",
"value": "={{ $('\u2699\ufe0f Config').first().json.sheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "filter-today-lite",
"name": "Filter by Today",
"type": "n8n-nodes-base.code",
"position": [
672,
400
],
"parameters": {
"jsCode": "const today = new Date().toISOString().split('T')[0];\nconst result = [];\nconst allItems = $input.all();\nfor (let i = 0; i < allItems.length; i++) {\n const item = allItems[i];\n const raw = item.json.send_date;\n if (raw) {\n try {\n const normalized = new Date(raw).toISOString().split('T')[0];\n if (normalized === today) {\n result.push({ json: item.json });\n }\n } catch (e) {}\n }\n}\nreturn result;"
},
"typeVersion": 2
},
{
"id": "if-lite",
"name": "Products Found?",
"type": "n8n-nodes-base.if",
"position": [
880,
400
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond1",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $input.all().length }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.3
},
{
"id": "build-html-lite",
"name": "Build HTML Email",
"type": "n8n-nodes-base.code",
"position": [
1104,
400
],
"parameters": {
"jsCode": "const items = $input.all();\nconst today = new Date();\nconst days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\nconst months = ['January','February','March','April','May','June','July','August','September','October','November','December'];\nconst weekday = days[today.getDay()];\nconst dateStr = today.getDate() + ' ' + months[today.getMonth()] + ' ' + today.getFullYear();\nconst products = items.map(i => i.json);\nconst count = products.length;\nconst cards = [];\nfor (let i = 0; i < products.length; i++) {\n const p = products[i];\n const hasRef = p.referral_link && p.referral_link.trim() !== '';\n let card = '<div style=\"margin-bottom:24px;border:1px solid #e5e7eb;border-radius:8px;overflow:hidden;\">';\n if (p.image_url) { card += '<div style=\"padding:12px 12px 0;\"><img src=\"' + p.image_url + '\" style=\"width:100%;max-height:220px;object-fit:contain;display:block;\" alt=\"' + p.product_name + '\" /></div>'; }\n card += '<div style=\"padding:10px 14px 12px;\">';\n card += '<h2 style=\"margin:0 0 4px;font-size:15px;color:#111;\">' + p.product_name + '</h2>';\n card += '<p style=\"margin:0 0 10px;color:#666;line-height:1.4;font-size:13px;\">' + p.description + '</p>';\n if (hasRef) {\n card += '<a href=\"' + p.referral_link + '\" style=\"display:inline-block;background:#000;color:#fff;padding:7px 16px;border-radius:6px;text-decoration:none;font-size:13px;\">Learn more \u2192</a>';\n }\n card += '</div></div>';\n cards.push(card);\n}\nconst productCards = cards.join('');\nconst h1text = count + ' new product' + (count > 1 ? 's' : '') + ' for you today';\nconst html = '<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body style=\"margin:0;padding:0;background:#f9fafb;\"><div style=\"max-width:600px;margin:0 auto;padding:24px;font-family:-apple-system,sans-serif;\"><h1 style=\"margin:0 0 24px;font-size:24px;color:#111;\">' + h1text + '</h1>' + productCards + '<p style=\"margin-top:32px;font-size:12px;color:#999;\">You are receiving this because you subscribed to our product newsletter.</p></div></body></html>';\nconst subject = count + ' new product' + (count > 1 ? 's' : '') + ' for you \u2013 ' + weekday + ', ' + dateStr;\nreturn [{ json: { html, subject } }];"
},
"typeVersion": 2
},
{
"id": "read-recipients-lite",
"name": "Read Recipients",
"type": "n8n-nodes-base.googleSheets",
"position": [
1360,
400
],
"parameters": {
"options": {},
"sheetName": {
"mode": "name",
"value": "newsletter_recipients"
},
"documentId": {
"mode": "id",
"value": "={{ $('\u2699\ufe0f Config').first().json.sheetId }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "personalize-lite",
"name": "Prepare per Recipient",
"type": "n8n-nodes-base.code",
"position": [
1552,
400
],
"parameters": {
"jsCode": "const template = $('Build HTML Email').first().json;\nconst recipients = $input.all();\nconst result = [];\nfor (let i = 0; i < recipients.length; i++) {\n const email = recipients[i].json.email;\n if (!email) continue;\n result.push({ json: { to: email, subject: template.subject, html: template.html } });\n}\nreturn result;"
},
"typeVersion": 2
},
{
"id": "send-lite",
"name": "Send Newsletter",
"type": "n8n-nodes-base.gmail",
"position": [
1760,
400
],
"parameters": {
"sendTo": "={{ $json.to }}",
"message": "={{ $json.html }}",
"options": {},
"subject": "={{ $json.subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "sticky-overview",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-528,
-16
],
"parameters": {
"color": 4,
"width": 430,
"height": 880,
"content": "## \ud83d\udcec Daily Product Newsletter\n\n**Who's it for**\nAffiliate marketers, niche-site owners & creators who want an automated daily product newsletter \u2014 without a paid email tool.\n\n**What it does**\nReads products from a Google Sheet and emails a clean HTML newsletter to your subscribers every morning via Gmail.\n\n**How it works**\n1\ufe0f\u20e3 Runs daily at 08:00\n2\ufe0f\u20e3 Reads products, keeps only those due today\n3\ufe0f\u20e3 Builds an HTML email with product cards\n4\ufe0f\u20e3 Sends it to your recipient list\n\n**Setup (~15 min)**\n1. Copy the Google Sheet template \u2192 File \u2192 Make a copy:\nhttps://docs.google.com/spreadsheets/d/1t3x9_qWaklk0T9Z25r4QxUbJ2lqTSU5CjKF_1wwVrgE/edit?usp=sharing\n2. Paste your Sheet ID into the \u2699\ufe0f Config node\n3. Connect Google Sheets + Gmail credentials\n4. Add a product + recipient, test, activate\n\n**Requirements**\nn8n \u00b7 a Google account \u00b7 a Gmail account (all free)\n\n---\n\u2b50 **Want open & click tracking + unsubscribe?**\nThe full version tracks who opens and which products get clicked:\nrvmautomations.lemonsqueezy.com\n\n---\n\n**Want open & click tracking?**\nThis free version sends newsletters but doesn't track opens, clicks or unsubscribes.\n\n\ud83d\udc49 [Upgrade to Premium](https://rvmautomations.lemonsqueezy.com/checkout/buy/83671e3e-481d-4cf4-98ad-eaf22758e379) \u2014 adds full tracking, bot filtering, unsubscribe management and an analytics dashboard. One-time $39."
},
"typeVersion": 1
},
{
"id": "sticky-sec-a",
"name": "Section 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-48,
160
],
"parameters": {
"color": 5,
"width": 460,
"height": 384,
"content": "## \u23f0 1. Schedule & Config\n\nRuns automatically every day at 08:00 (change it in the trigger).\n\nSet your **Google Sheet ID** in the **\u2699\ufe0f Config** node \u2014 it's the only thing you need to edit."
},
"typeVersion": 1
},
{
"id": "sticky-sec-b",
"name": "Section 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
432,
160
],
"parameters": {
"color": 5,
"width": 640,
"height": 384,
"content": "## \ud83d\udce5 2. Get today's products\n\nReads all products from the sheet, then keeps only those whose **send_date** is today.\n\nIf no products are due, the workflow stops quietly \u2014 no empty emails."
},
"typeVersion": 1
},
{
"id": "sticky-sec-c",
"name": "Section 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1088,
160
],
"parameters": {
"color": 5,
"width": 230,
"height": 384,
"content": "## \u2709\ufe0f 3. Build the email\n\nLoops over today's products and builds a clean HTML newsletter \u2014 each product becomes a card with image, text and an affiliate button."
},
"typeVersion": 1
},
{
"id": "sticky-sec-d",
"name": "Section 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1328,
160
],
"parameters": {
"color": 5,
"width": 660,
"height": 384,
"content": "## \ud83d\udce4 4. Send to subscribers\n\nReads your recipient list and sends the newsletter to each subscriber via Gmail."
},
"typeVersion": 1
},
{
"id": "upgrade-hint-sticky-a1",
"name": "Upgrade to Premium",
"type": "n8n-nodes-base.stickyNote",
"position": [
2200,
160
],
"parameters": {
"color": 3,
"width": 420,
"height": 460,
"content": "## \u2b50 Upgrade to Premium\n\nThis **free** version sends newsletters but has **no tracking**.\n\nThe **Premium** version adds:\n- \ud83d\udcca Open & click tracking per recipient\n- \ud83e\udd16 Bot filtering (no fake clicks)\n- \ud83d\ude4b Unsubscribe management\n- \ud83d\udcc8 Analytics dashboard (auto-built in Google Sheets)\n\n\ud83d\udc49 [Get the Premium version \u2014 $39 one-time](https://rvmautomations.lemonsqueezy.com/checkout/buy/83671e3e-481d-4cf4-98ad-eaf22758e379)"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"timezone": "Europe/Berlin",
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "e6876c55-d696-4896-a530-75107c2a213e",
"nodeGroups": [],
"connections": {
"Read Products": {
"main": [
[
{
"node": "Filter by Today",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Config": {
"main": [
[
{
"node": "Read Products",
"type": "main",
"index": 0
}
]
]
},
"Daily at 08:00": {
"main": [
[
{
"node": "\u2699\ufe0f Config",
"type": "main",
"index": 0
}
]
]
},
"Filter by Today": {
"main": [
[
{
"node": "Products Found?",
"type": "main",
"index": 0
}
]
]
},
"Products Found?": {
"main": [
[
{
"node": "Build HTML Email",
"type": "main",
"index": 0
}
]
]
},
"Read Recipients": {
"main": [
[
{
"node": "Prepare per Recipient",
"type": "main",
"index": 0
}
]
]
},
"Build HTML Email": {
"main": [
[
{
"node": "Read Recipients",
"type": "main",
"index": 0
}
]
]
},
"Prepare per Recipient": {
"main": [
[
{
"node": "Send Newsletter",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs daily at 08:00, pulls products scheduled for today from Google Sheets, generates an HTML newsletter email, and sends it to each subscriber via Gmail. Runs every day at 08:00 on a schedule. Reads all rows from the sheet in Google Sheets. Keeps only products…
Source: https://n8n.io/workflows/16364/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.
special-day-email-sender. Uses googleSheets, gmail. Scheduled trigger; 43 nodes.
Looking for a way to track GitHub bounty issues automatically and get notified in real time? This GitHub Bounty Tracker workflow monitors repositories for issues labeled 💎 Bounty, logs them in Google
This workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.
This n8n template demonstrates how to build a Auto Lead Gen & Outreach System for Local Businesses specifically designed to help businesses that don’t have a website yet.