This workflow corresponds to n8n.io template #9463 — we link there as the canonical source.
This workflow follows the Agent → Emailsend 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": "qxecimVbLMgxfjK3",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Automate End-of-Day Report Generation from ClickUp and GoHighLevel to Slack, Email, and Google Drive",
"tags": [],
"nodes": [
{
"id": "bd6d56ca-edb5-44a2-a281-0dccc2103891",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4512,
-496
],
"parameters": {
"color": 6,
"width": 389,
"height": 753,
"content": "## \ud83d\udcca Automate End-of-Day Report Generation from ClickUp and GoHighLevel to Slack, Email, and Google Drive \n\nThis workflow automatically generates comprehensive End-of-Day (EOD) reports by:\n- Fetching tasks from ClickUp\n- Retrieving opportunities from GoHighLevel (GHL)\n- Merging and transforming data into a unified format\n- Using AI to analyze and generate insightful reports\n- Distributing reports via Slack, Email, and Google Drive\n\n### \ud83c\udfaf Use Case\nPerfect for teams wanting automated daily summaries of:\n- Task completions and blockers\n- Sales pipeline progress\n- Team performance metrics\n- Action items for tomorrow\n\n### \u23f0 Schedule\nRuns Monday-Friday at 6:00 PM (18:00)\n\n### \ud83d\udd27 Setup Requirements\n1. ClickUp OAuth2 credentials\n2. GoHighLevel OAuth2 credentials\n3. Azure OpenAI API credentials\n4. Slack API credentials\n5. SMTP credentials for email\n6. Google Drive OAuth2 credentials"
},
"typeVersion": 1
},
{
"id": "379fe532-1b85-4c6d-ae9b-47a925359848",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3920,
-464
],
"parameters": {
"width": 318,
"height": 358,
"content": "## \u23f0 Step 1: Schedule Trigger\n\n**Cron Expression:** `0 18 * * 1-5`\n- Runs at 6:00 PM (18:00)\n- Monday through Friday only\n- Timezone: Server default\n\n**Setup Instructions:**\n1. Click this node\n2. Adjust time if needed using cron expression\n3. Test manually using \"Execute Node\" button"
},
"typeVersion": 1
},
{
"id": "ea406065-c358-4fcf-a38a-604312920c35",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3536,
-720
],
"parameters": {
"width": 343,
"height": 497,
"content": "## \ud83d\udccb Step 2: Fetch ClickUp Tasks\n\n**What it does:**\nRetrieves tasks from your ClickUp workspace for the current day.\n\n**Setup Instructions:**\n1. Connect ClickUp OAuth2 credentials\n2. Replace these IDs with your own:\n - Team ID (get from ClickUp workspace URL)\n - Space ID (from space settings)\n - Folder ID (from folder URL)\n - List ID (from list URL)\n\n**Filters Applied:**\n- Due date: Today\n- Includes subtasks\n\n**Security:** Remove hardcoded IDs before sharing!"
},
"typeVersion": 1
},
{
"id": "972b5e17-42e1-49b5-9aac-a4d01ada89d4",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3472,
160
],
"parameters": {
"width": 343.2558139534883,
"height": 339.5348837209302,
"content": "## \ud83d\udcbc Step 3: Fetch GHL Opportunities\n\n**What it does:**\nRetrieves won opportunities from GoHighLevel CRM.\n\n**Setup Instructions:**\n1. Connect GoHighLevel OAuth2 credentials\n2. Adjust filters if needed:\n - Current: Only \"won\" opportunities\n - Optional: Add date range filters\n\n**Limit:** 100 opportunities\n\n**Security:** Credentials are stored securely in n8n"
},
"typeVersion": 1
},
{
"id": "1646ef95-15d9-422d-9419-d84a5a9603f1",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3168,
-528
],
"parameters": {
"width": 303,
"height": 374,
"content": "## \ud83d\udd00 Step 4: Merge Data Sources\n\n**What it does:**\nCombines ClickUp tasks and GHL opportunities into a single dataset.\n\n**Merge Strategy:**\n- Input 1: ClickUp tasks\n- Input 2: GHL opportunities\n- Mode: Append (combines all items)\n\n**No configuration needed** - just ensure both data sources connect here."
},
"typeVersion": 1
},
{
"id": "37efa8ec-2c49-4dd7-a2bb-11adf09b5ded",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3040,
96
],
"parameters": {
"width": 343.2558139534883,
"height": 400,
"content": "## \ud83d\udd04 Step 5: Transform & Structure Data\n\n**What it does:**\nTransforms merged data into a unified format for AI analysis.\n\n**Key Transformations:**\n- Maps ClickUp tasks \u2192 GHL opportunity format\n- Extracts monetary values from custom fields\n- Normalizes status values\n- Aggregates summary statistics\n\n**Output Structure:**\n- Total items count\n- Opportunities array\n- Summary metrics (by status, source, total value)\n\n**No configuration needed** - transformation logic is built-in."
},
"typeVersion": 1
},
{
"id": "2fb72697-f98e-484c-8d9f-fac71da8c90e",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2784,
-640
],
"parameters": {
"width": 343,
"height": 501,
"content": "## \ud83e\udd16 Step 6: AI Report Generation\n\n**What it does:**\nUses Azure OpenAI GPT-4o to analyze data and generate structured EOD report.\n\n**Setup Instructions:**\n1. Connect Azure OpenAI credentials\n2. Model: GPT-4o (recommended)\n3. Memory: 7-message window for context\n\n**AI Analysis Includes:**\n- Brief summary\n- Key wins\n- Important metrics\n- Blockers/issues\n- Action items for tomorrow\n\n**Output:** Structured JSON matching defined schema"
},
"typeVersion": 1
},
{
"id": "a7000d6c-e0ee-40c6-968e-f233b120e33e",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2320,
48
],
"parameters": {
"width": 343,
"height": 492,
"content": "## \ud83d\udce4 Step 7: Format for Distribution\n\n**What it does:**\nCreates three formatted versions of the report:\n1. **Slack**: Markdown with emojis\n2. **Email**: HTML with styling\n3. **Google Drive**: Plain text file\n\n**Each Output Contains:**\n- Title\n- Summary\n- Wins\n- Key metrics\n- Blockers\n- Action items\n- Timestamp\n\n**No configuration needed** - automatic routing."
},
"typeVersion": 1
},
{
"id": "8d3b5528-a03f-4298-a336-d1cb84324f1e",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2144,
-736
],
"parameters": {
"width": 343,
"height": 413,
"content": "## \ud83d\udd00 Step 8: Route to Channels\n\n**What it does:**\nThree parallel IF nodes route data to appropriate channels.\n\n**Routing Logic:**\n- `type = \"slack\"` \u2192 Slack node\n- `type = \"email\"` \u2192 Email node\n- `type = \"google_drive\"` \u2192 Google Drive node\n\n**All three routes execute in parallel** for simultaneous delivery.\n\n**No configuration needed** - automatic based on data type."
},
"typeVersion": 1
},
{
"id": "ae1581a1-f411-4a51-a557-875e97535b8c",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-768
],
"parameters": {
"width": 343,
"height": 432,
"content": "## \ud83d\udcac Step 9A: Send to Slack\n\n**Setup Instructions:**\n1. Connect Slack OAuth2 credentials\n2. **IMPORTANT:** Replace channel ID with your own:\n - Get from: Slack \u2192 Right-click channel \u2192 Copy link\n - Extract: Last part of URL (e.g., C09GNB90TED)\n3. Select channel from dropdown\n\n**Message Format:**\n- Title with icon\n- Markdown formatting\n- All report sections\n"
},
"typeVersion": 1
},
{
"id": "4614de3e-b2e4-4954-9567-32f5345a7305",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1424,
-288
],
"parameters": {
"width": 343.2558139534883,
"height": 400,
"content": "## \ud83d\udce7 Step 9B: Send Email\n\n**Setup Instructions:**\n1. Connect SMTP credentials (Gmail, Outlook, etc.)\n2. **IMPORTANT:** Replace these placeholders:\n - `fromEmail`: Your company email\n - `toEmail`: Recipient(s) email\n3. Customize subject line if needed\n\n**Email Features:**\n- Professional HTML template\n- Gradient header\n- Color-coded sections\n- Mobile-responsive design\n"
},
"typeVersion": 1
},
{
"id": "c8166ad6-7729-40c4-a1ac-cc5b8e7d76a9",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1584,
272
],
"parameters": {
"width": 343,
"height": 448,
"content": "## \ud83d\udcc1 Step 9C: Upload to Google Drive\n\n**Setup Instructions:**\n1. Connect Google Drive OAuth2 credentials\n2. Select destination folder:\n - Default: Root folder\n - Recommended: Create \"EOD Reports\" folder\n3. Filename format: `EOD_Report_YYYY-MM-DD.txt`\n\n**File Content:**\n- Plain text with ASCII art borders\n- All report sections\n- Timestamp\n\n**Security:** Folder ID is safe to share (no personal data)"
},
"typeVersion": 1
},
{
"id": "8d5f5a2a-c6a7-455c-a570-c4266e64179b",
"name": "Schedule EOD Report Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-3568,
-112
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 18 * * 1-5"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "745ec334-f971-4a2f-9433-bcd0ae03942a",
"name": "Merge All Data Sources",
"type": "n8n-nodes-base.merge",
"position": [
-3120,
-112
],
"parameters": {},
"typeVersion": 2.1
},
{
"id": "219dad0b-4101-4203-875f-cfbb3124d9b5",
"name": "Transform and Structure Data",
"type": "n8n-nodes-base.code",
"position": [
-2896,
-112
],
"parameters": {
"jsCode": "// n8n Code Node - Transform Merged ClickUp + GHL Data & Aggregate\n\nconst transformedItems = [];\n\n// Process each item from the merged input\nfor (const item of $input.all()) {\n const data = item.json;\n \n // Check if this is a ClickUp task (has custom_id, creator, project fields)\n // or a GHL opportunity (has pipelineId, monetaryValue, contactId)\n const isClickUpTask = data.hasOwnProperty('custom_id') && \n data.hasOwnProperty('creator') && \n data.hasOwnProperty('project');\n \n if (isClickUpTask) {\n // Transform ClickUp task to GHL opportunity format\n const transformedItem = {\n // Use ClickUp task ID as the opportunity ID\n id: data.id,\n \n // Use task name as opportunity name\n name: data.name,\n \n // Set default monetary value (you can extract from custom fields if available)\n monetaryValue: extractMonetaryValue(data.custom_fields),\n \n // Map ClickUp project to pipeline ID\n pipelineId: data.project?.id || \"YOUR_PIPELINE_ID\",\n \n // Map ClickUp status to pipeline stage\n pipelineStageId: data.status?.id || null,\n pipelineStageUId: data.status?.id || null,\n \n // Map first assignee ID\n assignedTo: data.assignees?.[0]?.id?.toString() || null,\n \n // Map ClickUp status type to GHL status\n status: mapClickUpStatusToGHL(data.status?.type),\n \n // Source information\n source: \"ClickUp\",\n \n // Timestamps - convert from milliseconds to ISO string\n lastStatusChangeAt: data.date_updated ? new Date(parseInt(data.date_updated)).toISOString() : null,\n lastStageChangeAt: data.date_updated ? new Date(parseInt(data.date_updated)).toISOString() : null,\n createdAt: data.date_created ? new Date(parseInt(data.date_created)).toISOString() : null,\n updatedAt: data.date_updated ? new Date(parseInt(data.date_updated)).toISOString() : null,\n \n // Index version\n indexVersion: 1,\n \n // Use first assignee as contact ID\n contactId: data.assignees?.[0]?.id?.toString() || null,\n \n // Location from team ID\n locationId: data.team_id || \"YOUR_LOCATION_ID\",\n \n // Custom fields\n customFields: data.custom_fields || [],\n \n // Lost reason\n lostReasonId: null,\n \n // Followers from watchers\n followers: data.watchers?.map(w => w.id.toString()) || [],\n \n // Relations - create from assignees\n relations: data.assignees?.map((assignee, index) => ({\n associationId: \"OPPORTUNITIES_CONTACTS_ASSOCIATION\",\n relationId: data.id,\n primary: index === 0,\n objectKey: \"contact\",\n recordId: assignee.id.toString(),\n fullName: assignee.username,\n contactName: assignee.username,\n companyName: data.project?.name || null,\n email: assignee.email,\n phone: null,\n tags: data.tags?.map(t => t.name) || [],\n attributed: null\n })) || [],\n \n // Primary contact from first assignee\n contact: data.assignees?.[0] ? {\n id: data.assignees[0].id.toString(),\n name: data.assignees[0].username,\n companyName: data.project?.name || null,\n email: data.assignees[0].email,\n phone: null,\n tags: data.tags?.map(t => t.name) || [],\n score: []\n } : null,\n \n // Sort fields\n sort: [\n parseInt(data.date_created),\n data.assignees?.[0]?.id?.toString() || \"\"\n ],\n \n // Attributions\n attributions: [{\n utmSessionSource: \"ClickUp\",\n isFirst: true,\n medium: \"integration\"\n }]\n };\n \n transformedItems.push(transformedItem);\n \n } else {\n // This is already a GHL opportunity - pass it through as-is\n transformedItems.push(data);\n }\n}\n\n// Helper function to map ClickUp status types to GHL status\nfunction mapClickUpStatusToGHL(statusType) {\n if (!statusType) return 'open';\n \n const statusMap = {\n 'closed': 'won',\n 'complete': 'won',\n 'done': 'won',\n 'open': 'open',\n 'in progress': 'open',\n 'to do': 'open',\n 'cancelled': 'abandoned',\n 'blocked': 'abandoned',\n 'lost': 'lost'\n };\n \n return statusMap[statusType.toLowerCase()] || 'open';\n}\n\n// Helper function to extract monetary value from custom fields\nfunction extractMonetaryValue(customFields) {\n if (!customFields || customFields.length === 0) return 0;\n \n // Look for common field names that might contain monetary value\n const moneyField = customFields.find(f => \n f.name && (\n f.name.toLowerCase().includes('value') ||\n f.name.toLowerCase().includes('amount') ||\n f.name.toLowerCase().includes('price') ||\n f.name.toLowerCase().includes('deal')\n )\n );\n \n return moneyField?.value || 0;\n}\n\n// AGGREGATION: Combine all transformed items into a single output\n// This ensures the AI Agent receives ONE item with all data\nconst aggregatedOutput = {\n totalItems: transformedItems.length,\n timestamp: new Date().toISOString(),\n opportunities: transformedItems,\n summary: {\n totalOpportunities: transformedItems.length,\n byStatus: {},\n totalMonetaryValue: 0,\n bySource: {}\n }\n};\n\n// Calculate summary statistics\ntransformedItems.forEach(item => {\n // Count by status\n aggregatedOutput.summary.byStatus[item.status] = \n (aggregatedOutput.summary.byStatus[item.status] || 0) + 1;\n \n // Sum monetary values\n aggregatedOutput.summary.totalMonetaryValue += item.monetaryValue || 0;\n \n // Count by source\n const source = item.source || 'GHL';\n aggregatedOutput.summary.bySource[source] = \n (aggregatedOutput.summary.bySource[source] || 0) + 1;\n});\n\n// Return single aggregated item for AI Agent\nreturn [{ json: aggregatedOutput }];"
},
"typeVersion": 2
},
{
"id": "1d93fe28-b9f0-4ff1-a169-542dae1f1783",
"name": "Format Reports for Distribution",
"type": "n8n-nodes-base.code",
"position": [
-2208,
-112
],
"parameters": {
"jsCode": "// Extract the output data from your input format\nconst inputData = $input.first().json;\nconst output = inputData.output;\n\n// Create routing objects based on your end-of-day report structure\nconst slackReport = {\n type: 'slack',\n title: output.title,\n summary: output.briefSummary,\n wins: output.wins,\n keyMetrics: output.keyMetrics,\n blockers: output.blockers,\n actionItems: output.actionItems,\n timestamp: new Date().toISOString(),\n icon: '\ud83d\udcca'\n};\n\nconst emailReport = {\n type: 'email',\n subject: output.title,\n body: {\n title: output.title,\n briefSummary: output.briefSummary,\n wins: output.wins,\n keyMetrics: output.keyMetrics,\n blockers: output.blockers,\n actionItems: output.actionItems\n },\n timestamp: new Date().toISOString()\n};\n\nconst googleDriveReport = {\n type: 'google_drive',\n filename: `EOD_Report_${new Date().toISOString().split('T')[0]}.txt`,\n content: `\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n${output.title}\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\ud83d\udccb BRIEF SUMMARY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n${output.briefSummary}\n\n\u2705 WINS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n${output.wins}\n\n\ud83d\udcca KEY METRICS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n${output.keyMetrics}\n\n\u26a0\ufe0f BLOCKERS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n${output.blockers}\n\n\ud83c\udfaf ACTION ITEMS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n${output.actionItems}\n\nGenerated: ${new Date().toISOString()}\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n `,\n timestamp: new Date().toISOString(),\n mimeType: 'text/plain'\n};\n\n// Return all three routing objects\nreturn [\n { json: slackReport },\n { json: emailReport },\n { json: googleDriveReport }\n];"
},
"typeVersion": 2
},
{
"id": "77d78b5e-49f6-4779-8828-344332a262ee",
"name": "Route to Slack",
"type": "n8n-nodes-base.if",
"position": [
-1984,
-304
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "334e8803-cf37-4a69-9a74-dc77d4541f8c",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "slack"
}
]
}
},
"typeVersion": 2
},
{
"id": "7ad743bb-a433-429c-a894-3dfef643ce2d",
"name": "Route to Email",
"type": "n8n-nodes-base.if",
"position": [
-1984,
-112
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "8b96c805-abe1-4588-a043-53c4ffeee9f3",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "email"
}
]
}
},
"typeVersion": 2
},
{
"id": "736cd539-135a-40e9-92a3-f2cc1d17e7e8",
"name": "Route to Google Drive",
"type": "n8n-nodes-base.if",
"position": [
-1984,
96
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a78ce4a7-5624-4f2b-9606-3eb64119a671",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "google_drive"
}
]
}
},
"typeVersion": 2
},
{
"id": "9275db81-48b1-493b-8bf9-e581e814a33f",
"name": "Send Slack Message",
"type": "n8n-nodes-base.slack",
"position": [
-1760,
-320
],
"parameters": {
"text": "=*Title:*\n{{ $json.title }} \n\n*Summary:*\n{{ $json.summary }} \n\n*Wins:*\n{{ $json.wins }} \n\n*Key Metrics:*\n{{ $json.keyMetrics }} \n\n*Blockers:*\n{{ $json.blockers }} \n\n*ActionItems:*\n{{ $json.actionItems }}\n\n",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_CHANNEL_ID",
"cachedResultName": "Select your channel"
},
"otherOptions": {
"includeLinkToWorkflow": false
}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "447a40d6-4f69-4b6c-a239-62c595941a56",
"name": "Send Email Report",
"type": "n8n-nodes-base.emailSend",
"position": [
-1760,
-128
],
"parameters": {
"html": "=<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <style>\n body {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n line-height: 1.6;\n color: #333;\n background-color: #f4f4f4;\n margin: 0;\n padding: 0;\n }\n .container {\n max-width: 700px;\n margin: 0 auto;\n background-color: #ffffff;\n padding: 0;\n }\n .header {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n padding: 30px;\n text-align: center;\n }\n .header h1 {\n margin: 0;\n font-size: 28px;\n font-weight: 600;\n }\n .header p {\n margin: 8px 0 0 0;\n font-size: 14px;\n opacity: 0.9;\n }\n .content {\n padding: 30px;\n }\n .section {\n margin-bottom: 25px;\n }\n .section-title {\n font-size: 16px;\n font-weight: 700;\n color: #667eea;\n margin: 0 0 15px 0;\n padding-bottom: 10px;\n border-bottom: 2px solid #f0f0f0;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .icon {\n font-size: 18px;\n }\n .summary-text {\n background-color: #f9f9f9;\n padding: 15px;\n border-left: 4px solid #667eea;\n border-radius: 4px;\n font-size: 14px;\n line-height: 1.7;\n }\n .wins-box {\n background-color: #f0fdf4;\n padding: 15px;\n border-left: 4px solid #10b981;\n border-radius: 4px;\n font-size: 14px;\n line-height: 1.7;\n }\n .blockers-box {\n background-color: #fef3c7;\n padding: 15px;\n border-left: 4px solid #f59e0b;\n border-radius: 4px;\n font-size: 14px;\n line-height: 1.7;\n }\n .metrics-text {\n background-color: #f9f9f9;\n padding: 15px;\n border-left: 4px solid #667eea;\n border-radius: 4px;\n font-size: 14px;\n line-height: 1.7;\n }\n .action-items {\n background-color: #f9f9f9;\n padding: 15px;\n border-left: 4px solid #667eea;\n border-radius: 4px;\n font-size: 14px;\n white-space: pre-wrap;\n word-wrap: break-word;\n }\n .footer {\n background-color: #f9f9f9;\n padding: 20px;\n text-align: center;\n font-size: 12px;\n color: #999;\n border-top: 1px solid #e0e0e0;\n }\n .footer p {\n margin: 5px 0;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>\ud83d\udcca {{ $json.body.title }}</h1>\n <p>Generated on {{ $json.timestamp }}</p>\n </div>\n <div class=\"content\">\n <div class=\"section\">\n <div class=\"section-title\">\n <span class=\"icon\">\ud83d\udccb</span>\n Brief Summary\n </div>\n <div class=\"summary-text\">\n {{ $json.body.briefSummary }}\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span class=\"icon\">\u2705</span>\n Wins\n </div>\n <div class=\"wins-box\">\n {{ $json.body.wins }}\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span class=\"icon\">\ud83d\udcca</span>\n Key Metrics\n </div>\n <div class=\"metrics-text\">\n {{ $json.body.keyMetrics }}\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span class=\"icon\">\u26a0\ufe0f</span>\n Blockers\n </div>\n <div class=\"blockers-box\">\n {{ $json.body.blockers }}\n </div>\n </div>\n <div class=\"section\">\n <div class=\"section-title\">\n <span class=\"icon\">\ud83c\udfaf</span>\n Action Items\n </div>\n <div class=\"action-items\">\n {{ $json.body.actionItems }}\n </div>\n </div>\n </div>\n <div class=\"footer\">\n <p><strong>End-of-Day Summary Report</strong></p>\n <p>This is an automated report generated by N8N Workflow</p>\n <p>Do not reply to this email</p>\n </div>\n </div>\n</body>\n</html>",
"options": {},
"subject": "={{ $json.subject }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "a2dcf9df-2d0c-4aa3-ab95-315b3ba5a617",
"name": "Upload Report to Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
-1536,
80
],
"parameters": {
"name": "={{ $('Route to Google Drive').item.json.filename }}",
"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": "root",
"cachedResultName": "/ (Root folder)"
}
},
"typeVersion": 3
},
{
"id": "53b786aa-1dfb-428c-b4d7-902c4d65b82b",
"name": "Fetch GHL Won Opportunities",
"type": "n8n-nodes-base.highLevel",
"position": [
-3344,
-16
],
"parameters": {
"limit": 100,
"filters": {
"status": "won"
},
"resource": "opportunity",
"operation": "getAll",
"requestOptions": {}
},
"typeVersion": 2
},
{
"id": "37bf0171-f463-42bf-a7bf-3664fef59f3f",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-2416,
128
],
"parameters": {
"jsonSchemaExample": "{\n \"title\": \"\",\n \"briefSummary\": \"\",\n \"wins\": \"\",\n \"keyMetrics\": \"\",\n \"blockers\": \"\",\n \"actionItems\":\"\"\n}\n"
},
"typeVersion": 1.3
},
{
"id": "0471b16d-770a-479e-90a6-44931fa8a62d",
"name": "Azure OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
-2672,
128
],
"parameters": {
"model": "gpt-4o",
"options": {}
},
"typeVersion": 1
},
{
"id": "63437c56-ea42-4b38-a6f9-9fb1d37e1027",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-2544,
128
],
"parameters": {
"sessionKey": "\"eod_report_generator\"",
"sessionIdType": "customKey",
"contextWindowLength": 7
},
"typeVersion": 1.3
},
{
"id": "65dba1ea-9525-48b3-ba77-47eef856b341",
"name": "AI Agent: Generate EOD Report",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-2624,
-112
],
"parameters": {
"text": "=You are given the following aggregated End-of-Day data from ClickUp (task management) and GHL (sales pipeline):\n\n{{ JSON.stringify($json.opportunities || $json, null, 2) }}\n\nPlease analyze this data and generate a structured End-of-Day (EOD) summary report.\n\n**Analysis Guidelines:**\n\n**For ClickUp Tasks:**\n- Count tasks by status (complete, in progress, blocked, etc.)\n- Calculate total time spent across all tasks\n- Identify completed tasks as wins\n- Flag blocked or delayed tasks as blockers\n- Note team members with completed work\n\n**For GHL Opportunities:**\n- Count opportunities by status (won, open, lost, abandoned)\n- Sum total monetary value of won deals\n- Identify new opportunities created today\n- Note high-value deals in progress\n- Track conversion rates if applicable\n",
"options": {
"systemMessage": "=You are an expert executive assistant AI specialized in creating comprehensive End-of-Day (EOD) summary reports.\n\nYour task is to analyze aggregated data from two systems:\n1. **ClickUp Tasks**: Project management tasks with status, assignees, time tracking, and completion details\n2. **GHL Opportunities**: Sales pipeline data with deals, monetary values, stages, and contact information\n\n**Your responsibilities:**\n- Analyze the combined data from both systems\n- Extract key metrics, wins, blockers, and action items\n- Identify patterns and trends across tasks and opportunities\n- Highlight team member contributions and achievements\n- Flag any issues or blockers that need attention\n- Provide actionable next steps\n\n**Output Requirements:**\n- Structure your response as valid JSON matching the provided schema\n- Be concise, professional, and actionable\n- Use specific numbers and metrics from the data\n- Focus on insights, not just data repetition\n- Ensure all arrays contain strings, not objects\n- Keep each item brief (1-2 sentences maximum)\n\n**Data Structure:**\n- ClickUp tasks will have fields like: id, name, status, assignees, time_spent, date_created, date_updated, project\n- GHL opportunities will have fields like: id, name, monetaryValue, status, pipelineStageId, contact, source\n\nGenerate a comprehensive but concise EOD report based on this combined dataset."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "46add9d4-fd38-4d52-aeac-22b47796b6d2",
"name": "Fetch ClickUp Tasks for Today",
"type": "n8n-nodes-base.clickUp",
"position": [
-3344,
-208
],
"parameters": {
"list": "YOUR_LIST_ID",
"team": "YOUR_TEAM_ID",
"space": "YOUR_SPACE_ID",
"folder": "YOUR_FOLDER_ID",
"filters": {
"subtasks": true,
"dueDateGt": "={{ $today.minus({ days: 1 }).toFormat('yyyy-MM-dd') }}",
"dueDateLt": "={{ $today.toFormat('yyyy-MM-dd') }}"
},
"operation": "getAll",
"authentication": "oAuth2"
},
"typeVersion": 1
},
{
"id": "4d12ff96-2f31-4984-8762-8b54519843ac",
"name": "Convert to File",
"type": "n8n-nodes-base.convertToFile",
"position": [
-1760,
80
],
"parameters": {
"options": {},
"operation": "toJson"
},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "2635cb23-0e0e-4ee1-885e-5ff809150414",
"connections": {
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent: Generate EOD Report",
"type": "ai_memory",
"index": 0
}
]
]
},
"Route to Email": {
"main": [
[
{
"node": "Send Email Report",
"type": "main",
"index": 0
}
]
]
},
"Route to Slack": {
"main": [
[
{
"node": "Send Slack Message",
"type": "main",
"index": 0
}
]
]
},
"Convert to File": {
"main": [
[
{
"node": "Upload Report to Google Drive",
"type": "main",
"index": 0
}
]
]
},
"Route to Google Drive": {
"main": [
[
{
"node": "Convert to File",
"type": "main",
"index": 0
}
]
]
},
"Merge All Data Sources": {
"main": [
[
{
"node": "Transform and Structure Data",
"type": "main",
"index": 0
}
]
]
},
"Azure OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent: Generate EOD Report",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent: Generate EOD Report",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Fetch GHL Won Opportunities": {
"main": [
[
{
"node": "Merge All Data Sources",
"type": "main",
"index": 1
}
]
]
},
"Schedule EOD Report Trigger": {
"main": [
[
{
"node": "Fetch GHL Won Opportunities",
"type": "main",
"index": 0
},
{
"node": "Fetch ClickUp Tasks for Today",
"type": "main",
"index": 0
}
]
]
},
"Transform and Structure Data": {
"main": [
[
{
"node": "AI Agent: Generate EOD Report",
"type": "main",
"index": 0
}
]
]
},
"AI Agent: Generate EOD Report": {
"main": [
[
{
"node": "Format Reports for Distribution",
"type": "main",
"index": 0
}
]
]
},
"Fetch ClickUp Tasks for Today": {
"main": [
[
{
"node": "Merge All Data Sources",
"type": "main",
"index": 0
}
]
]
},
"Format Reports for Distribution": {
"main": [
[
{
"node": "Route to Slack",
"type": "main",
"index": 0
},
{
"node": "Route to Email",
"type": "main",
"index": 0
},
{
"node": "Route to Google Drive",
"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.
slackApismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automatically generate and distribute detailed End-of-Day (EOD) reports combining task progress from ClickUp and opportunity data from GoHighLevel. This workflow uses AI to analyze daily performance, summarize key metrics, identify blockers, and deliver polished reports directly…
Source: https://n8n.io/workflows/9463/ — 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.
Automate your team's daily stand-ups with AI-powered morning briefs, directly pulled from ClickUp tasks and shared via Slack and Gmail every morning. ☀️📋💬 Triggers automatically at 9:15 AM each mornin
Automatically analyze incoming lead replies from Google Sheets using Azure OpenAI GPT-4, classify their intent (Demo Request, Pricing, Objection, etc.), and create actionable follow-up tasks in ClickU
This workflow automates end-to-end validation, assessment, and reporting of n8n workflow JSON templates using Google Drive, Azure OpenAI GPT-4o, Gmail, and Slack. It retrieves workflows from a Drive f
Automatically capture customer onboarding help requests from Typeform, log them in Google Sheets, validate email addresses, and send a professional HTML welcome email via Gmail. Ensures smooth onboard
Automate your entire content-to-audio workflow by converting new blog articles into fully produced podcast episodes using AI scriptwriting and ElevenLabs narration. 🎙🤖 This automation monitors an RSS