diff --git a/workflows/Send personalized daily learning emails for women using GPT-4o and Gmail-14021/send_personalized_daily_learning_emails_for_women_using_gpt-4o_and_gmail.json b/workflows/Send personalized daily learning emails for women using GPT-4o and Gmail-14021/send_personalized_daily_learning_emails_for_women_using_gpt-4o_and_gmail.json new file mode 100644 index 000000000..d225e20d3 --- /dev/null +++ b/workflows/Send personalized daily learning emails for women using GPT-4o and Gmail-14021/send_personalized_daily_learning_emails_for_women_using_gpt-4o_and_gmail.json @@ -0,0 +1 @@ +{"id":"fSwTqrZlWzlIIJY2","meta":{"instanceId":"8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177","templateCredsSetupCompleted":true},"name":"Automate Personalized Learning Emails for Women Using GPT-4o and Google Sheets","tags":[],"nodes":[{"id":"e05da8b9-13c1-452f-8ca7-77f87d656e7c","name":"Fetch All Subscribers","type":"n8n-nodes-base.googleSheets","position":[-1184,640],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA/edit#gid=0","cachedResultName":"Subscribers"},"documentId":{"__rl":true,"mode":"list","value":"1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA/edit?usp=drivesdk","cachedResultName":"Women Skill Learning Automation"}},"credentials":{"googleSheetsOAuth2Api":{"id":"ajCmdXdhjJqZW6RE","name":"automations"}},"typeVersion":4.4},{"id":"d344c966-709a-46a1-a7f8-9e43c7be44ee","name":"Fetch Content Library","type":"n8n-nodes-base.googleSheets","position":[-736,640],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":96514431,"cachedResultUrl":"https://docs.google.com/spreadsheets/d/1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA/edit#gid=96514431","cachedResultName":"ContentLibrary"},"documentId":{"__rl":true,"mode":"list","value":"1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1eSkNLIT6Mc8rUswvloelGmKL7vj39XO1CHTqTYGlrkA/edit?usp=drivesdk","cachedResultName":"Women Skill Learning Automation"}},"credentials":{"googleSheetsOAuth2Api":{"id":"ajCmdXdhjJqZW6RE","name":"automations"}},"executeOnce":true,"typeVersion":4.4},{"id":"f7cb081e-4537-42ea-ab23-7a793295df84","name":"Daily 9AM Trigger","type":"n8n-nodes-base.scheduleTrigger","position":[-1408,640],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 9 * * *"}]}},"typeVersion":1.2},{"id":"99c71da5-c251-49dd-b6e1-43814c90b433","name":"Calculate Day, Week & Phase","type":"n8n-nodes-base.code","position":[-960,640],"parameters":{"jsCode":"// Calculate day of year, week number, and learning phase per subscriber\nconst now = new Date();\n\n// Day of year\nconst start = new Date(now.getFullYear(), 0, 0);\nconst diff = now - start;\nconst oneDay = 86400000;\nconst dayOfYear = Math.floor(diff / oneDay);\n\n// Week number\nconst weekNumber = Math.ceil(dayOfYear / 7);\n\nconst results = [];\n\nfor (const item of $input.all()) {\n const subscribedDate = new Date(item.json['Subscribed Date'] || now);\n const subscribedDays = Math.floor((now - subscribedDate) / oneDay);\n\n // Determine learning phase\n let phase = 'Beginner';\n if (subscribedDays > 90) {\n phase = 'Advanced';\n } else if (subscribedDays > 30) {\n phase = 'Intermediate';\n }\n\n results.push({\n json: {\n ...item.json,\n dayOfYear,\n weekNumber,\n subscribedDays,\n phase\n }\n });\n}\n\nreturn results;"},"typeVersion":2},{"id":"e09a85e1-9d33-4300-b7e8-6bd6194f8b33","name":"Match Subscriber to Lesson","type":"n8n-nodes-base.code","position":[-432,640],"parameters":{"jsCode":"// Get subscribers (from previous node)\nconst subscribers = $('Calculate Day, Week & Phase').all();\n\n// Get content library (from input - Fetch Content Library node)\nconst contentItems = $input.all();\n\nconst results = [];\n\nfor (const subscriber of subscribers) {\n const interest = (subscriber.json['Topic Interest'] || '').toLowerCase();\n const phase = subscriber.json['phase'] || 'Beginner';\n const dayOfYear = subscriber.json['dayOfYear'] || 1;\n\n // Score and match lessons\n let bestLesson = null;\n let bestScore = -1;\n\n for (const content of contentItems) {\n let score = 0;\n const category = (content.json['Category'] || '').toLowerCase();\n const lessonPhase = (content.json['Phase'] || '').toLowerCase();\n\n if (category.includes(interest) || interest.includes(category)) score += 3;\n if (lessonPhase === phase.toLowerCase()) score += 2;\n\n if (score > bestScore) {\n bestScore = score;\n bestLesson = content.json;\n }\n }\n\n // Fallback by day index\n if (!bestLesson && contentItems.length > 0) {\n bestLesson = contentItems[dayOfYear % contentItems.length].json;\n }\n\n results.push({\n json: {\n name: subscriber.json['Name'],\n email: subscriber.json['Email'],\n topicInterest: subscriber.json['Topic Interest'],\n phase: subscriber.json['phase'],\n dayOfYear: subscriber.json['dayOfYear'],\n weekNumber: subscriber.json['weekNumber'],\n subscribedDays: subscriber.json['subscribedDays'],\n lessonTitle: bestLesson?.['Lesson Title'] || 'Daily Skill Tip',\n lessonCategory: bestLesson?.['Category'] || 'Career Growth',\n lessonRawContent: bestLesson?.['Raw Content'] || '',\n resourceLink: bestLesson?.['Resource Link'] || 'https://n8n.io'\n }\n });\n}\n\nreturn results;"},"typeVersion":2},{"id":"3f8d5ce6-0ad6-4a80-a090-7fe2fab98f0e","name":"Loop Each Subscriber","type":"n8n-nodes-base.splitInBatches","position":[-160,640],"parameters":{"options":{}},"typeVersion":3},{"id":"1e18d082-3e42-4183-9f90-5094934e4004","name":"Personalize Lesson","type":"@n8n/n8n-nodes-langchain.openAi","position":[128,672],"parameters":{"modelId":{"__rl":true,"mode":"list","value":"gpt-4o","cachedResultName":"GPT-4O"},"options":{},"responses":{"values":[{"content":"=Generate a personalized skill lesson for:\n\nName: {{ $json.name }}\nTopic Interest: {{ $json.topicInterest }}\nLearning Phase: {{ $json.phase }}\nDay Number: {{ $json.dayOfYear }}\nLesson Title: {{ $json.lessonTitle }}\nRaw Content: {{ $json.lessonRawContent }}\n\nRespond ONLY in this JSON format:\n{\n \"personalizedLesson\": \"3 paragraph personalized explanation adapted to their phase\",\n \"actionableTask\": \"One specific task they can do today in under 30 minutes\",\n \"motivationalQuote\": \"An inspiring quote from a woman leader in this field\",\n \"keyTakeaways\": [\"takeaway 1\", \"takeaway 2\", \"takeaway 3\"]\n}"},{"role":"system","content":"You are an expert women's career coach and educator. You generate personalized, inspiring, and practical skill lessons for women at different career stages. Always be encouraging, concise, and actionable. Format your response strictly as JSON only, no markdown, no extra text, no code blocks."}]},"builtInTools":{}},"credentials":{"openAiApi":{"id":"5Kzt6hGSZ1JHZqWN","name":"OpenAi account 2"}},"typeVersion":2.1},{"id":"d515c2be-1102-4b3c-8489-bda06b41211e","name":"Build Personalized Email","type":"n8n-nodes-base.code","position":[496,672],"parameters":{"jsCode":"const results = [];\n\nfor (const item of $input.all()) {\n let aiData = {};\n\n try {\n const rawContent = item.json.output?.[0]?.content?.[0]?.text || '{}';\n const cleaned = rawContent.replace(/```json|```/g, '').trim();\n aiData = JSON.parse(cleaned);\n } catch (e) {\n aiData = {\n personalizedLesson: 'Keep growing every day!',\n actionableTask: 'Spend 20 minutes today practicing your skill.',\n motivationalQuote: \"The question isn't who is going to let me; it's who is going to stop me. โ Ayn Rand\",\n keyTakeaways: ['Stay consistent', 'Take small steps', 'Celebrate progress']\n };\n }\n\n // Pull subscriber + lesson data from Combine + Match node\n const subscriberData = $('Match Subscriber to Lesson').item.json;\n\n const name = subscriberData.name || 'Learner';\n const lessonCategory = subscriberData.lessonCategory || 'Career Growth';\n const phase = subscriberData.phase || 'Beginner';\n const dayOfYear = subscriberData.dayOfYear || '';\n const lessonTitle = subscriberData.lessonTitle || 'Daily Skill Tip';\n const resourceLink = subscriberData.resourceLink || 'https://n8n.io';\n\n const takeawaysList = (aiData.keyTakeaways || []).map(t => `
Hi ${name} ๐
\nHere is your personalized lesson for today:
\n