This workflow corresponds to n8n.io template #12124 — 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": "eZju30PPt5tjTgdr",
"name": "Unified Marketing Reporting Automation",
"tags": [
{
"id": "YD6WImVncCh6AcbZ",
"name": "Het",
"createdAt": "2025-09-08T06:03:03.283Z",
"updatedAt": "2025-09-08T06:03:03.283Z"
}
],
"nodes": [
{
"id": "69cfdcf4-053e-4b62-86f7-e6f7325450a0",
"name": "Schedule Trigger2",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
336,
192
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [
1
],
"triggerAtHour": 9
}
]
}
},
"typeVersion": 1.3
},
{
"id": "8411350a-3755-448c-95d0-1ac10b229b97",
"name": "Schedule Trigger3",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
336,
368
],
"parameters": {
"rule": {
"interval": [
{
"field": "months",
"triggerAtHour": 10
}
]
}
},
"typeVersion": 1.3
},
{
"id": "d5a47b0e-7e71-4436-ae3f-a95cc6001d56",
"name": "check month and week1",
"type": "n8n-nodes-base.code",
"position": [
608,
272
],
"parameters": {
"jsCode": "const today = new Date();\n\n// Get day info\nconst dayOfWeek = today.getDay(); // 0 = Sunday, 1 = Monday\nconst dayOfMonth = today.getDate(); // 1 = First day of month\n\n// Flags\nconst isWeekly = dayOfWeek === 1; // Monday\nconst isMonthly = dayOfMonth === 1; // 1st day of month\n\nreturn [\n {\n json: {\n runType: isMonthly ? \"monthly\" : isWeekly ? \"weekly\" : \"none\",\n isWeekly,\n isMonthly,\n today: today.toISOString()\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "490ca0c7-ca5a-41c4-ac6b-4a6a4f602fd6",
"name": "Set Websites and Campaings1",
"type": "n8n-nodes-base.set",
"position": [
880,
272
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "926a60b6-a4d7-4313-906c-df0607f4958d",
"name": "websites",
"type": "array",
"value": "=[\n {\n \"name\": \"InboxPlus\",\n \"siteId\": \"inboxplus.com\",\n \"campaigns\": [\"InboxPlus-FB-Leads\", \"InboxPlus-IG-Leads\", \"InboxPlus-Retargeting\",\"InboxPlus-Search-1\",\"InboxPlus-Display-1\",\"InboxPlus-Remarketing\"]\n },\n {\n \"name\": \"Tymora\",\n \"siteId\": \"tymora.com\",\n \"campaigns\": [\"Tymora-FB-Leads\", \"Tymora-IG-Leads\", \"Tymora-Retargeting\",\"Tymora-Search-1\",\"Tymora-Display-1\",\"Tymora-Remarketing\"]\n },\n {\n \"name\": \"Jitsi Expert\",\n \"siteId\": \"jitsiexpert.com\",\n \"campaigns\": [\"Jitsi-FB-Leads\", \"Jitsi-IG-Leads\",\"Jitsi-Search-1\",\"Jitsi-Display-1\"]\n },\n {\n \"name\": \"vDoctor\",\n \"siteId\": \"vdoctor.com\",\n \"campaigns\": [\"vDoctor-FB-Leads\", \"vDoctor-IG-Leads\",\"vDoctor-Search-1\",\"vDoctor-Display-1\"]\n }\n]\n"
},
{
"id": "6d994934-d501-4bee-9fc2-368660a6fd93",
"name": "isWeekly",
"type": "boolean",
"value": "={{ $json.isWeekly }}"
},
{
"id": "a55f34ec-f724-40ed-b15b-f49ad55135d0",
"name": "isMonthly",
"type": "boolean",
"value": "={{ $json.isMonthly }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b67d78e4-f6ea-45a1-bbdd-258deedc10fd",
"name": "Loop Websites1",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1520,
272
],
"parameters": {
"options": {},
"batchSize": "=1"
},
"typeVersion": 3
},
{
"id": "30b50688-b6c1-4907-a204-b42900da4542",
"name": "Send Weekly Marketing report2",
"type": "n8n-nodes-base.gmail",
"position": [
3424,
272
],
"parameters": {
"sendTo": "example.com",
"message": "=Hello Team,\n\nHere is your **{{ $json.reportType }} Marketing Performance Report**\n\ud83d\udcc5 **Report Date:** {{ new Date($json.reportDate).toDateString() }}\n\n---\n\n## \ud83d\udcca Website Performance Summary\n\n{{ $json.websites.map(w => `\n\n### ${w.website}\n\n**Traffic & Engagement**\n\n* Visits: ${w.websiteKPIs.visits}\n* Users: ${w.websiteKPIs.users}\n* Page Views: ${w.websiteKPIs.pageViews}\n* Website Conversions: ${w.websiteKPIs.siteConversions}\n* Conversion Rate: ${w.websiteKPIs.conversionRate}%\n\n**Paid Marketing Overview**\n\n* Total Ad Spend: \u20b9${w.websiteKPIs.totalSpend}\n* Total Conversions (Ads): ${w.websiteKPIs.totalConversions}\n* Overall CPL: \u20b9${w.websiteKPIs.overallCPL}\n\n---\n\n`).join('') }}\n\n## \ud83c\udfaf Google Ads \u2013 Campaign Insights\n\n{{ $json.websites.map(w =>\nw.googleAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* CTR: ${c.ctr}%\n* CPA: \u20b9${c.cpa}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83d\udce3 Meta Ads (Facebook & Instagram)\n\n{{ $json.websites.map(w =>\nw.metaAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* Leads: ${c.leads}\n* CTR: ${c.ctr}%\n* CPL: \u20b9${c.cpl}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83e\udde0 Overall Observations\n\n* Campaigns marked **\u201cPerforming well\u201d** should continue with current strategy.\n* Campaigns flagged for optimization should be reviewed for targeting, creatives, or budget efficiency.\n* Website conversion rates indicate the quality of incoming traffic and landing page performance.\n\nIf you\u2019d like:\n\n* week-over-week comparison\n* optimization recommendations\n* channel-wise budget suggestions\n\njust reply and we\u2019ll include it in the next report automatically.\n\nBest regards,\n**Marketing Automation System**\n",
"options": {},
"subject": "={{ $json.reportType }} Marketing Performance Report \u2013 {{ $json.reportDate.split('T')[0] }}"
},
"typeVersion": 2.2
},
{
"id": "25473a12-d5ee-4bd6-aa3c-3f40ea4798c3",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
3184,
464
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "04dd59dd-ae13-4338-a58e-74ccea3cffd3",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.reportType }}",
"rightValue": "Weekly"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e1abf0ff-5d0b-47e4-bb70-22400bbef5e2",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.reportType }}",
"rightValue": "Monthly"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "5e1318b5-c500-44a4-a92e-7f8ef9f3944a",
"name": "Send Monthly Marketing Report2",
"type": "n8n-nodes-base.gmail",
"position": [
3424,
608
],
"parameters": {
"sendTo": "example.com",
"message": "=Hello Team,\n\nHere is your **{{ $json.reportType }} Marketing Performance Report**\n\ud83d\udcc5 **Report Date:** {{ new Date($json.reportDate).toDateString() }}\n\n---\n\n## \ud83d\udcca Website Performance Summary\n\n{{ $json.websites.map(w => `\n\n### ${w.website}\n\n**Traffic & Engagement**\n\n* Visits: ${w.websiteKPIs.visits}\n* Users: ${w.websiteKPIs.users}\n* Page Views: ${w.websiteKPIs.pageViews}\n* Website Conversions: ${w.websiteKPIs.siteConversions}\n* Conversion Rate: ${w.websiteKPIs.conversionRate}%\n\n**Paid Marketing Overview**\n\n* Total Ad Spend: \u20b9${w.websiteKPIs.totalSpend}\n* Total Conversions (Ads): ${w.websiteKPIs.totalConversions}\n* Overall CPL: \u20b9${w.websiteKPIs.overallCPL}\n\n---\n\n`).join('') }}\n\n## \ud83c\udfaf Google Ads \u2013 Campaign Insights\n\n{{ $json.websites.map(w =>\nw.googleAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* CTR: ${c.ctr}%\n* CPA: \u20b9${c.cpa}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83d\udce3 Meta Ads (Facebook & Instagram)\n\n{{ $json.websites.map(w =>\nw.metaAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* Leads: ${c.leads}\n* CTR: ${c.ctr}%\n* CPL: \u20b9${c.cpl}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83e\udde0 Overall Observations\n\n* Campaigns marked **\u201cPerforming well\u201d** should continue with current strategy.\n* Campaigns flagged for optimization should be reviewed for targeting, creatives, or budget efficiency.\n* Website conversion rates indicate the quality of incoming traffic and landing page performance.\n\nIf you\u2019d like:\n\n* week-over-week comparison\n* optimization recommendations\n* channel-wise budget suggestions\n\njust reply and we\u2019ll include it in the next report automatically.\n\nBest regards,\n**Marketing Automation System**",
"options": {},
"subject": "={{ $json.reportType }} Marketing Performance Report \u2013 {{ $json.reportDate.split('T')[0] }}"
},
"typeVersion": 2.2
},
{
"id": "10c7e88a-93b0-43dd-9d5c-30f4c2f70794",
"name": "Expand Websites1",
"type": "n8n-nodes-base.splitOut",
"position": [
1088,
272
],
"parameters": {
"include": "allOtherFields",
"options": {},
"fieldToSplitOut": "websites"
},
"typeVersion": 1
},
{
"id": "c94076e1-9e2b-4f69-850c-054c1ab6331d",
"name": "Attach Run Flags1",
"type": "n8n-nodes-base.set",
"position": [
1296,
272
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "170641b0-0fff-4947-85de-39b3b9f2056c",
"name": "isWeekly",
"type": "string",
"value": "={{$items(\"check month and week1\")[0].json.isWeekly}}"
},
{
"id": "9583be6b-6ce5-4828-8ca1-2ed0aa130624",
"name": "isMonthly",
"type": "string",
"value": "={{$items(\"check month and week1\")[0].json.isMonthly}}"
},
{
"id": "ea8e1f40-e4ca-440f-9a7f-730f17e04109",
"name": "name",
"type": "string",
"value": "={{ $json.websites.name }}"
},
{
"id": "020cabf5-5105-46c0-b60f-02ded5abc8c0",
"name": "siteId",
"type": "string",
"value": "={{ $json.websites.siteId }}"
},
{
"id": "db507cac-58f1-44a9-b2fb-f3738c794745",
"name": "campaigns",
"type": "array",
"value": "={{ $json.websites.campaigns }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "36a8c671-1452-4cf8-9519-18ed9422f3d3",
"name": "Filter Google Ads By Website1",
"type": "n8n-nodes-base.code",
"position": [
2048,
448
],
"parameters": {
"jsCode": "const websiteData = $node[\"Loop Websites1\"].json;\nconst website = websiteData.name.toLowerCase();\n\nconst filteredAds = items.filter(item => {\n const campaign =\n item.json.name ||\n item.json.campaign_name ||\n '';\n return campaign.toLowerCase().includes(website);\n});\n\n// Add website data to each filtered ad\nreturn filteredAds.map(ad => ({\n json: {\n ...ad.json,\n websiteInfo: {\n name: websiteData.name,\n siteId: websiteData.siteId,\n campaigns: websiteData.campaigns,\n isWeekly: websiteData.isWeekly,\n isMonthly: websiteData.isMonthly\n }\n }\n}));"
},
"typeVersion": 2
},
{
"id": "f20bae59-a657-4d5e-8543-57ce6fc2c4a3",
"name": "Filter Meta Ads By Website1",
"type": "n8n-nodes-base.code",
"position": [
2048,
608
],
"parameters": {
"jsCode": "const websiteData = $node[\"Loop Websites1\"].json;\nconst website = websiteData.name.toLowerCase();\n\nconst filteredAds = items.filter(item => {\n const campaign =\n item.json.campaign ||\n item.json.campaign_name ||\n '';\n return campaign.toLowerCase().includes(website);\n});\n\n// Add website data to each filtered ad\nreturn filteredAds.map(ad => ({\n json: {\n ...ad.json,\n websiteInfo: {\n name: websiteData.name,\n siteId: websiteData.siteId,\n campaigns: websiteData.campaigns,\n isWeekly: websiteData.isWeekly,\n isMonthly: websiteData.isMonthly\n }\n }\n}));"
},
"typeVersion": 2
},
{
"id": "6d8c5ddd-a3d2-4559-b113-cb46d429219b",
"name": "Build Website Dataset1",
"type": "n8n-nodes-base.code",
"position": [
2480,
368
],
"parameters": {
"jsCode": "const website = $node[\"Loop Websites1\"].json;\n\n// Get data from each source\nconst analyticsData = $node[\"Mock Google Analytics\"].json;\nconst googleAdsData = $items(\"Filter Google Ads By Website1\");\nconst metaAdsData = $items(\"Filter Meta Ads By Website1\");\n\nreturn [\n {\n json: {\n website: website.name,\n siteId: website.siteId,\n isWeekly: website.isWeekly,\n isMonthly: website.isMonthly,\n analytics: analyticsData,\n googleAds: googleAdsData.map(item => item.json),\n metaAds: metaAdsData.map(item => item.json)\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "4c835c56-8565-4d7c-abae-059bac1d6733",
"name": "Merge1",
"type": "n8n-nodes-base.merge",
"position": [
2304,
352
],
"parameters": {
"numberInputs": 3
},
"typeVersion": 3.2
},
{
"id": "fb78a801-9660-4b40-93c1-ec6b172157de",
"name": "Calculate KPIs & Campaign Insights1",
"type": "n8n-nodes-base.code",
"position": [
2656,
576
],
"parameters": {
"jsCode": "const data = $json;\n\n/* -------------------------\n BASIC WEBSITE INFO\n-------------------------- */\nconst website = data.website;\nconst isWeekly = data.isWeekly;\nconst isMonthly = data.isMonthly;\n\n/* -------------------------\n GOOGLE ANALYTICS METRICS\n-------------------------- */\nconst visits = Number(data.analytics.sessions || 0);\nconst users = Number(data.analytics.users || 0);\nconst pageViews = Number(data.analytics.pageViews || 0);\nconst siteConversions = Number(data.analytics.conversions || 0);\n\n/* -------------------------\n GOOGLE ADS CALCULATIONS\n-------------------------- */\nlet googleSpend = 0;\nlet googleClicks = 0;\nlet googleImpressions = 0;\nlet googleConversions = 0;\n\nconst googleCampaignInsights = data.googleAds.map(ad => {\n const spend = (ad.costMicros || 0) / 1_000_000;\n const clicks = ad.clicks || 0;\n const impressions = ad.impressions || 0;\n const conversions = ad.conversions || 0;\n\n googleSpend += spend;\n googleClicks += clicks;\n googleImpressions += impressions;\n googleConversions += conversions;\n\n const ctr = impressions ? (clicks / impressions) * 100 : 0;\n const cpa = conversions ? spend / conversions : null;\n\n let insight = \"Performing well\";\n\n if (spend > 3000 && conversions < 30) {\n insight = \"High spend but low conversions \u2013 needs optimization\";\n } else if (ctr < 1) {\n insight = \"Low CTR \u2013 ad creatives or targeting may be weak\";\n } else if (conversions === 0) {\n insight = \"No conversions \u2013 consider pausing\";\n }\n\n return {\n campaign: ad.name,\n spend: Number(spend.toFixed(2)),\n clicks,\n impressions,\n conversions,\n ctr: Number(ctr.toFixed(2)),\n cpa: cpa ? Number(cpa.toFixed(2)) : null,\n insight\n };\n});\n\n/* -------------------------\n META ADS CALCULATIONS\n-------------------------- */\nlet metaSpend = 0;\nlet metaClicks = 0;\nlet metaImpressions = 0;\nlet metaLeads = 0;\n\nconst metaCampaignInsights = data.metaAds.map(ad => {\n const spend = ad.spend || 0;\n const clicks = ad.clicks || 0;\n const impressions = ad.impressions || 0;\n const leads = ad.leads || 0;\n\n metaSpend += spend;\n metaClicks += clicks;\n metaImpressions += impressions;\n metaLeads += leads;\n\n const ctr = impressions ? (clicks / impressions) * 100 : 0;\n const cpl = leads ? spend / leads : null;\n\n let insight = \"Performing well\";\n\n if (spend > 7000 && leads < 50) {\n insight = \"High spend but low leads \u2013 targeting or offer issue\";\n } else if (ctr < 0.8) {\n insight = \"Low CTR \u2013 creatives may need improvement\";\n } else if (leads === 0) {\n insight = \"No leads \u2013 campaign underperforming\";\n }\n\n return {\n campaign: ad.campaign,\n spend,\n clicks,\n impressions,\n leads,\n ctr: Number(ctr.toFixed(2)),\n cpl: cpl ? Number(cpl.toFixed(2)) : null,\n insight\n };\n});\n\n/* -------------------------\n TOTAL WEBSITE KPIs\n-------------------------- */\nconst totalSpend = googleSpend + metaSpend;\nconst totalConversions = googleConversions + metaLeads;\n\nconst overallCPL = totalConversions\n ? totalSpend / totalConversions\n : null;\n\nconst conversionRate = visits\n ? (siteConversions / visits) * 100\n : 0;\n\n/* -------------------------\n FINAL OUTPUT\n-------------------------- */\nreturn [\n {\n json: {\n website,\n isWeekly,\n isMonthly,\n\n websiteKPIs: {\n visits,\n users,\n pageViews,\n siteConversions,\n totalSpend: Number(totalSpend.toFixed(2)),\n totalConversions,\n overallCPL: overallCPL ? Number(overallCPL.toFixed(2)) : null,\n conversionRate: Number(conversionRate.toFixed(2))\n },\n\n googleAdsInsights: googleCampaignInsights,\n metaAdsInsights: metaCampaignInsights\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "929c0e9c-8f6f-4856-b768-5261f6e9458d",
"name": "Filter Hubspot Leads",
"type": "n8n-nodes-base.code",
"position": [
1712,
1232
],
"parameters": {
"jsCode": "const now = new Date();\n\n// Get flags from \"check month and week\" node\nconst flagsData = $(\"check month and week1\").first().json;\nconst isWeekly = flagsData.isWeekly;\nconst isMonthly = flagsData.isMonthly;\n\nreturn items.filter(item => {\n const createdAt = new Date(item.json.created_date);\n if (isNaN(createdAt)) return false;\n \n const diffDays = (now - createdAt) / (1000 * 60 * 60 * 24);\n \n if (isWeekly) return diffDays <= 7;\n if (isMonthly) return diffDays <= 30;\n \n return false;\n});"
},
"typeVersion": 2
},
{
"id": "8a10efe3-fdf4-4310-ba26-11958b696e93",
"name": "Summarize Hubspot Leads",
"type": "n8n-nodes-base.code",
"position": [
1936,
1232
],
"parameters": {
"jsCode": "const totalLeads = items.length;\n\n// Normalize helper\nconst normalize = (v) => (v || '').toLowerCase();\n\n// Status-based counts\nconst statusCounts = {\n new: 0,\n contacted: 0,\n qualified: 0,\n followup: 0,\n unqualified: 0,\n converted: 0,\n lost: 0\n};\n\n// Lifecycle stage counts\nconst lifecycleCounts = {\n lead: 0,\n mql: 0,\n sql: 0,\n opportunity: 0,\n customer: 0\n};\n\nitems.forEach(item => {\n const status = normalize(item.json.status);\n const lifecycle = normalize(item.json.lifecycle_stage);\n\n // Status mapping\n if (status === 'new') statusCounts.new++;\n else if (status === 'contacted') statusCounts.contacted++;\n else if (status === 'qualified') statusCounts.qualified++;\n else if (status === 'follow-up' || status === 'followup') statusCounts.followup++;\n else if (status === 'unqualified') statusCounts.unqualified++;\n else if (status === 'converted') statusCounts.converted++;\n else if (status === 'lost') statusCounts.lost++;\n\n // Lifecycle mapping\n if (lifecycle === 'lead') lifecycleCounts.lead++;\n else if (lifecycle.includes('marketing')) lifecycleCounts.mql++;\n else if (lifecycle.includes('sales')) lifecycleCounts.sql++;\n else if (lifecycle === 'opportunity') lifecycleCounts.opportunity++;\n else if (lifecycle === 'customer') lifecycleCounts.customer++;\n});\n\nreturn [\n {\n json: {\n hubspotSummary: {\n totalLeads,\n statusBreakdown: statusCounts,\n lifecycleBreakdown: lifecycleCounts,\n conversionRate: totalLeads\n ? Number(((statusCounts.converted / totalLeads) * 100).toFixed(2))\n : 0\n }\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "5beab407-6357-45a4-abdb-ff11e4504cbc",
"name": "Prepare Report Data2",
"type": "n8n-nodes-base.code",
"position": [
2928,
464
],
"parameters": {
"jsCode": "// Separate website-level reports\nconst websites = items\n .filter(i => i.json.website)\n .map(i => i.json);\n\n// Normalize string booleans safely\nconst toBool = (v) => v === true || v === \"true\";\n\n// Detect run type correctly\nconst isMonthly = websites.some(w => toBool(w.isMonthly));\nconst isWeekly = websites.some(w => toBool(w.isWeekly));\n\n// Find HubSpot summary (single object)\nconst hubspotItem = items.find(\n i => i.json.hubspotSummary || i.json.hubspot\n);\n\nconst hubspot = hubspotItem\n ? (hubspotItem.json.hubspotSummary || hubspotItem.json.hubspot)\n : {};\n\n// Final unified report object\nreturn [\n {\n json: {\n reportDate: new Date().toISOString(),\n reportType: isMonthly ? \"Monthly\" : \"Weekly\",\n\n websites: websites.map(w => ({\n website: w.website,\n siteId: w.siteId,\n isWeekly: toBool(w.isWeekly),\n isMonthly: toBool(w.isMonthly),\n websiteKPIs: w.websiteKPIs,\n googleAdsInsights: w.googleAdsInsights,\n metaAdsInsights: w.metaAdsInsights\n })),\n\n hubspot\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "02b36b48-a3d7-4b76-8622-7bfee68f3125",
"name": "Send Weekly Marketing report3",
"type": "n8n-nodes-base.gmail",
"position": [
2688,
1040
],
"parameters": {
"sendTo": "example.com",
"message": "=Hello Team,\n\nHere is your **{{ $json.reportType }} Marketing Performance Report**\n\ud83d\udcc5 **Report Date:** {{ new Date($json.reportDate).toDateString() }}\n\n---\n\n## \ud83d\udcca Website Performance Summary\n\n{{ $json.websites.map(w => `\n\n### ${w.website}\n\n**Traffic & Engagement**\n\n* Visits: ${w.websiteKPIs.visits}\n* Users: ${w.websiteKPIs.users}\n* Page Views: ${w.websiteKPIs.pageViews}\n* Website Conversions: ${w.websiteKPIs.siteConversions}\n* Conversion Rate: ${w.websiteKPIs.conversionRate}%\n\n**Paid Marketing Overview**\n\n* Total Ad Spend: \u20b9${w.websiteKPIs.totalSpend}\n* Total Conversions (Ads): ${w.websiteKPIs.totalConversions}\n* Overall CPL: \u20b9${w.websiteKPIs.overallCPL}\n\n---\n\n`).join('') }}\n\n## \ud83c\udfaf Google Ads \u2013 Campaign Insights\n\n{{ $json.websites.map(w =>\nw.googleAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* CTR: ${c.ctr}%\n* CPA: \u20b9${c.cpa}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83d\udce3 Meta Ads (Facebook & Instagram)\n\n{{ $json.websites.map(w =>\nw.metaAdsInsights.map(c => `\n**${c.campaign}**\n\n* Spend: \u20b9${c.spend}\n* Impressions: ${c.impressions}\n* Clicks: ${c.clicks}\n* Leads: ${c.leads}\n* CTR: ${c.ctr}%\n* CPL: \u20b9${c.cpl}\n* Insight: ${c.insight}\n\n`).join('')\n).join('') }}\n\n## \ud83e\udde0 Overall Observations\n\n* Campaigns marked **\u201cPerforming well\u201d** should continue with current strategy.\n* Campaigns flagged for optimization should be reviewed for targeting, creatives, or budget efficiency.\n* Website conversion rates indicate the quality of incoming traffic and landing page performance.\n\nIf you\u2019d like:\n\n* week-over-week comparison\n* optimization recommendations\n* channel-wise budget suggestions\n\njust reply and we\u2019ll include it in the next report automatically.\n\nBest regards,\n**Marketing Automation System**\n",
"options": {},
"subject": "={{ $json.reportType }} Marketing Performance Report \u2013 {{ $json.reportDate.split('T')[0] }}"
},
"typeVersion": 2.2
},
{
"id": "62106fee-dfc6-45c4-9c39-24ee05274693",
"name": "Switch3",
"type": "n8n-nodes-base.switch",
"position": [
2448,
1232
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "04dd59dd-ae13-4338-a58e-74ccea3cffd3",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.reportType }}",
"rightValue": "Weekly"
}
]
}
},
{
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e1abf0ff-5d0b-47e4-bb70-22400bbef5e2",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.reportType }}",
"rightValue": "Monthly"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "c7369ab0-5bca-4460-8f4b-24735ee9bc1d",
"name": "Send Monthly Marketing Report3",
"type": "n8n-nodes-base.gmail",
"position": [
2688,
1376
],
"parameters": {
"sendTo": "example.com",
"message": "=<h2>{{ $json.reportType }} HubSpot Lead Performance Report</h2>\n\n<p><strong>Report Date:</strong> {{$json.reportDate}}</p>\n\n<h3>Lead Overview</h3>\n<ul>\n <li><strong>Total Leads:</strong> {{$json.hubspotSummary.totalLeads}}</li>\n <li><strong>Conversion Rate:</strong> {{$json.hubspotSummary.conversionRate}}%</li>\n</ul>\n\n<h3>Lead Status Breakdown</h3>\n<ul>\n <li>New: {{$json.hubspotSummary.statusBreakdown.new}}</li>\n <li>Contacted: {{$json.hubspotSummary.statusBreakdown.contacted}}</li>\n <li>Qualified: {{$json.hubspotSummary.statusBreakdown.qualified}}</li>\n <li>Follow-up: {{$json.hubspotSummary.statusBreakdown.followup}}</li>\n <li>Unqualified: {{$json.hubspotSummary.statusBreakdown.unqualified}}</li>\n <li>Converted: {{$json.hubspotSummary.statusBreakdown.converted}}</li>\n <li>Lost: {{$json.hubspotSummary.statusBreakdown.lost}}</li>\n</ul>\n\n<h3>Lifecycle Stage Breakdown</h3>\n<ul>\n <li>Leads: {{$json.hubspotSummary.lifecycleBreakdown.lead}}</li>\n <li>MQLs: {{$json.hubspotSummary.lifecycleBreakdown.mql}}</li>\n <li>SQLs: {{$json.hubspotSummary.lifecycleBreakdown.sql}}</li>\n <li>Opportunities: {{$json.hubspotSummary.lifecycleBreakdown.opportunity}}</li>\n <li>Customers: {{$json.hubspotSummary.lifecycleBreakdown.customer}}</li>\n</ul>\n\n<p>\nThis automated report summarizes lead performance and funnel progression for the selected period.\n</p>\n",
"options": {},
"subject": "={{ $json.reportType }} HubSpot Lead Summary"
},
"typeVersion": 2.2
},
{
"id": "7a083eaa-9581-4a46-ad46-c7966bbe1ceb",
"name": "Prepare Report Data3",
"type": "n8n-nodes-base.code",
"position": [
2192,
1232
],
"parameters": {
"jsCode": "// ---------- Find HubSpot Summary ----------\nconst hubspotItem = items.find(\n i => i.json.hubspotSummary || i.json.hubspot\n);\n\nconst hubspotSummary = hubspotItem\n ? (hubspotItem.json.hubspotSummary || hubspotItem.json.hubspot)\n : null;\n\n// ---------- Safety Check ----------\nif (!hubspotSummary) {\n return [];\n}\n\n// ---------- Build HubSpot Report ----------\nreturn [\n {\n json: {\n reportType: \"Monthly\", // default fallback\n reportDate: new Date().toISOString(),\n\n hubspotSummary: {\n totalLeads: hubspotSummary.totalLeads,\n conversionRate: hubspotSummary.conversionRate,\n statusBreakdown: hubspotSummary.statusBreakdown,\n lifecycleBreakdown: hubspotSummary.lifecycleBreakdown\n }\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "159f0b87-3443-488e-8499-08ee4d05fbed",
"name": "Append or update row in sheet2",
"type": "n8n-nodes-base.googleSheets",
"position": [
1824,
32
],
"parameters": {
"columns": {
"value": {
"Users": "={{ $json.websiteKPIs.users }}",
"isWeekly": "={{ $json.isWeekly }}",
"isMonthly": "={{ $json.isMonthly }}",
"Created At": "={{ $now }}",
"Conversions": "={{ $json.websiteKPIs.siteConversions }}",
"Report Date": "={{ $now }}",
"Website Name": "={{ $json.website }}",
"Meta Ads Spend": "={{ $json.metaAdsInsights[0].spend }}",
"Google Ads Spend": "={{ $json.googleAdsInsights[0].spend }}",
"Google Ads Clicks": "={{ $json.googleAdsInsights[0].clicks }}",
"Google Ads Conversions": "={{ $json.googleAdsInsights[0].conversions }}"
},
"schema": [
{
"id": "Report Date",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Report Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "isWeekly",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "isWeekly",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "isMonthly",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "isMonthly",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Site ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Site ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Sessions",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Sessions",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Users",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Users",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Conversions",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Conversions",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Google Ads Spend",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Google Ads Spend",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Google Ads Clicks",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Google Ads Clicks",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Google Ads Conversions",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Google Ads Conversions",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Meta Ads Spend",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Meta Ads Spend",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Meta Ads Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Meta Ads Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Meta Ads CPA",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Meta Ads CPA",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Data Source",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Data Source",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Website Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Website Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Created At",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Created At",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Website Name"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "your-document-url-here",
"cachedResultName": "your-document-name-here"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "your-document-id-here",
"cachedResultUrl": "your-document-url-here",
"cachedResultName": "your-document-name-here"
}
},
"typeVersion": 4.7
},
{
"id": "6ff6d4c4-4b44-4c38-9c90-030696fc2b1f",
"name": "Code in JavaScript1",
"type": "n8n-nodes-base.code",
"position": [
2912,
1376
],
"parameters": {
"jsCode": "// Transform filtered HubSpot leads data for Google Sheets\nconst transformedData = [];\n\nfor (const item of items) {\n const lead = item.json;\n \n transformedData.push({\n json: {\n \"Report Date\": new Date().toISOString().split('T')[0],\n \"Report Type\": lead.is_weekly ? \"Weekly\" : \"Monthly\",\n \"Lead ID\": lead.lead_id,\n \"First Name\": lead.first_name,\n \"Last Name\": lead.last_name,\n \"Email\": lead.email,\n \"Phone\": lead.phone,\n \"Company\": lead.company,\n \"Website\": lead.website,\n \"Source\": lead.source,\n \"Campaign\": lead.campaign,\n \"Status\": lead.status,\n \"Lifecycle Stage\": lead.lifecycle_stage,\n \"Owner\": lead.owner,\n \"Created Date\": lead.created_date,\n \"Last Activity Date\": lead.last_activity_date,\n \"Data Source\": \"HubSpot\",\n \"Created At\": new Date().toISOString()\n }\n });\n}\n\nreturn transformedData;"
},
"typeVersion": 2
},
{
"id": "f7ba1482-eb71-49db-b1a9-25453a3bf7cc",
"name": "Append or update row in sheet3",
"type": "n8n-nodes-base.googleSheets",
"position": [
3120,
1376
],
"parameters": {
"columns": {
"value": {},
"schema": [
{
"id": "Report Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Report Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Report Type",
"type": "string",
"display": true,
"required": false,
"displayName": "Report Type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Total Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Total Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Conversion Rate (%)",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Conversion Rate (%)",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "New Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "New Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Contacted Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Contacted Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Qualified Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Qualified Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Follow-up Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Follow-up Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Unqualified Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Unqualified Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Converted Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Converted Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lost Leads",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Lost Leads",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Lead Stage Count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Lead Stage Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "MQL Count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "MQL Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "SQL Count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "SQL Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Opportunity Count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Opportunity Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Count",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Customer Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "CRM Source",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "CRM Source",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Created At",
"type": "string",
"display": true,
"required": false,
"displayName": "Created At",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 91297926,
"cachedResultUrl": "your-document-url-here",
"cachedResultName": "your-document-name-here"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "your-document-id-here",
"cachedResultUrl": "your-document-url-here",
"cachedResultName": "your-document-name-here"
}
},
"typeVersion": 4.7
},
{
"id": "64c18f37-cdb0-46de-8bbd-1c82273a18b8",
"name": "Get a report",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
1824,
304
],
"parameters": {
"metricsGA4": {
"metricValues": [
{},
{
"listName": "sessions"
},
{
"listName": "screenPageViews"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{$json.siteId}}"
},
"dimensionsGA4": {
"dimensionValues": [
{}
]
},
"additionalFields": {}
},
"typeVersion": 2
},
{
"id": "015e5bff-792c-4c30-bb5a-4be20a7472aa",
"name": "Get many campaigns",
"type": "n8n-nodes-base.googleAds",
"position": [
1824,
448
],
"parameters": {
"requestOptions": {},
"additionalOptions": {}
},
"typeVersion": 1
},
{
"id": "e2172991-3ad7-48a5-848d-c5a6906344ce",
"name": "Fetch Meta Ads",
"type": "n8n-nodes-base.httpRequest",
"position": [
1824,
608
],
"parameters": {
"url": "your-meta-ads-api-endpoint-here",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "fields",
"value": "spend,clicks,impressions,actions"
},
{
"name": "time_range",
"value": "weekly or monthly"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "b01a1e30-c993-44a3-8a8d-fdcaaffea4ad",
"name": "Fetch1",
"type": "n8n-nodes-base.hubspot",
"position": [
1488,
1232
],
"parameters": {
"limit": 250,
"operation": "getAll",
"additionalFields": {}
},
"typeVersion": 2.2
},
{
"id": "c947d90b-30de-40dc-9a33-8c35d6472d14",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-384,
-176
],
"parameters": {
"width": 672,
"height": 992,
"content": "## Unified Marketing Intelligence & Reporting Automation\n\nThis workflow automatically collects, analyzes, and reports marketing performance data across websites, paid ads, and CRM systems. It eliminates manual reporting by generating clean, structured weekly or monthly marketing reports and storing historical data for long-term analysis.\n\n### How it works\nThis automation runs on a schedule and first determines whether the execution is weekly or monthly. It then loops through multiple websites, fetches website analytics data, paid advertising performance, and CRM lead data, and combines everything into a unified dataset. Key KPIs such as users, conversions, ad spend, CTR, CPA, CPL, and conversion rates are calculated automatically. Based on these results, the workflow generates professional marketing performance reports and delivers them via email, while also logging all data into Google Sheets for tracking and audits.\n\n### Setup steps\n1. Configure weekly and monthly Schedule Trigger nodes \n2. Define websites and their associated ad campaigns \n3. Connect Google Analytics for website traffic and conversions \n4. Connect Google Ads and Meta Ads for campaign performance data \n5. Connect HubSpot to retrieve lead and lifecycle information \n6. Review KPI calculation and insight logic \n7. Connect Gmail to send automated reports \n8. Connect Google Sheets for performance data storage \n9. Activate the workflow and monitor automated reports\n\n### Customization tips\n- Add or remove websites easily from the website mapping node \n- Adjust KPI thresholds to match your business goals \n- Extend reporting with additional ad platforms or CRM fields\n"
},
"typeVersion": 1
},
{
"id": "ceec494a-c50a-44e0-8533-512f9f36144a",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
-176
],
"parameters": {
"color": 7,
"width": 1136,
"height": 992,
"content": "## Step 1: Trigger & Report Type Detection\nScheduled triggers decide whether the workflow runs weekly or monthly and set flags used throughout the workflow.\n"
},
"typeVersion": 1
},
{
"id": "04048207-9680-4412-b7de-b323e6497e80",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1456,
-176
],
"parameters": {
"color": 7,
"width": 1360,
"height": 992,
"content": "## Step 2: Website & Ads Data Processing\nLoops through each website, fetches analytics and ad data, filters campaigns, merges sources, and calculates performance KPIs.\n"
},
"typeVersion": 1
},
{
"id": "56197f7a-00c0-48ac-95da-9274962dc3cd",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
2832,
-176
],
"parameters": {
"color": 7,
"width": 880,
"height": 992,
"content": "## Step 2.1: Marketing Report Generation\nCombines all website performance data and sends a clean weekly or monthly marketing report via email.\n"
},
"typeVersion": 1
},
{
"id": "5cd382c8-2ce2-414a-b90d-cb5131ca6e06",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
1456,
864
],
"parameters": {
"color": 7,
"width": 928,
"height": 864,
"content": "## Step 3: HubSpot Lead Analysis\nFetches HubSpot leads, filters by reporting period, and summarizes lead status and lifecycle metrics.\n"
},
"typeVersion": 1
},
{
"id": "0a9977ec-3b7f-492b-bf1f-7ccbbc77050b",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
2400,
864
],
"parameters": {
"color": 7,
"width": 960,
"height": 864,
"content": "## Step 3.1: CRM Reporting & Storage\nSends HubSpot lead summary reports and stores detailed CRM data in Google Sheets for long-term analysis.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "1b3b11b6-6eb0-4f35-9a03-46555ad6c9f6",
"connections": {
"Fetch1": {
"main": [
[
{
"node": "Filter Hubspot Leads",
"type": "main",
"index": 0
}
]
]
},
"Merge1": {
"main": [
[
{
"node": "Build Website Dataset1",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Send Weekly Marketing report2",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Monthly Marketing Report2",
"type": "main",
"index": 0
}
]
]
},
"Switch3": {
"main": [
[
{
"node": "Send Weekly Marketing report3",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Monthly Marketing Report3",
"type": "main",
"index": 0
}
]
]
},
"Get a report": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 0
}
]
]
},
"Fetch Meta Ads": {
"main": [
[
{
"node": "Filter Meta Ads By Website1",
"type": "main",
"index": 0
}
]
]
},
"Loop Websites1": {
"main": [
[
{
"node": "Append or update row in sheet2",
"type": "main",
"index": 0
}
],
[
{
"node": "Get a report",
"type": "main",
"index": 0
},
{
"node": "Get many campaigns",
"type": "main",
"index": 0
},
{
"node": "Fetch Meta Ads",
"type": "main",
"index": 0
}
]
]
},
"Expand Websites1": {
"main": [
[
{
"node": "Attach Run Flags1",
"type": "main",
"index": 0
}
]
]
},
"Attach Run Flags1": {
"main": [
[
{
"node": "Loop Websites1",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger2": {
"main": [
[
{
"node": "check month and week1",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger3": {
"main": [
[
{
"node": "check month and week1",
"type": "main",
"index": 0
}
]
]
},
"Get many campaigns": {
"main": [
[
{
"node": "Filter Google Ads By Website1",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "Append or update row in sheet3",
"type": "main",
"index": 0
}
]
]
},
"Filter Hubspot Leads": {
"main": [
[
{
"node": "Summarize Hubspot Leads",
"type": "main",
"index": 0
}
]
]
},
"Prepare Report Data2": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Prepare Report Data3": {
"main": [
[
{
"node": "Switch3",
"type": "main",
"index": 0
}
]
]
},
"check month and week1": {
"main": [
[
{
"node": "Set Websites and Campaings1",
"type": "main",
"index": 0
},
{
"node": "Fetch1",
"type": "main",
"index": 0
}
]
]
},
"Build Website Dataset1": {
"main": [
[
{
"node": "Calculate KPIs & Campaign Insights1",
"type": "main",
"index": 0
}
]
]
},
"Summarize Hubspot Leads": {
"main": [
[
{
"node": "Prepare Report Data3",
"type": "main",
"index": 0
}
]
]
},
"Filter Meta Ads By Website1": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 2
}
]
]
},
"Set Websites and Campaings1": {
"main": [
[
{
"node": "Expand Websites1",
"type": "main",
"index": 0
}
]
]
},
"Filter Google Ads By Website1": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 1
}
]
]
},
"Send Monthly Marketing Report3": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"Calculate KPIs & Campaign Insights1": {
"main": [
[
{
"node": "Loop Websites1",
"type": "main",
"index": 0
},
{
"node": "Prepare Report Data2",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs on scheduled weekly and monthly triggers to generate unified marketing performance reports. It processes multiple websites by collecting analytics data, paid ads performance, and CRM leads, then calculates KPIs and insights automatically. The workflow sends…
Source: https://n8n.io/workflows/12124/ — 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.
This workflow is designed for marketing teams, data analysts, and business owners who need to consistently track key performance indicators (KPIs). It saves hours of manual data collection and reporti
Watch target companies for C-level and VP hiring signals, then send AI-personalized outreach emails when leadership roles are posted.
Monitor a company watchlist for new Seed and Series A funding rounds and deliver a formatted weekly scouting report via email and Slack.
Detect when target accounts adopt competitor technology by enriching company watchlists with PredictLeads tech detection data and emailing the assigned AE.
This template enables fully automated lead enrichment using Surfe’s bulk API. Simply drop a Google Spreadsheet into your Google Drive, and n8n will handle everything — from reading the leads, enrichin