This workflow follows the Agent → Gmail 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 →
{
"name": "daily-report-agent",
"nodes": [
{
"parameters": {
"method": "POST",
"url": "=https://googleads.googleapis.com/v21/customers/<insert-customer-id-here>/googleAds:search",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleAdsOAuth2Api",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "login-customer-id",
"value": "<insert-mcc-id-here>"
},
{
"name": "developer-token",
"value": "<insert-developer-token-here>"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\n \"query\": \"SELECT campaign.name, metrics.clicks, metrics.impressions, metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM campaign WHERE metrics.cost_micros > 0 AND campaign.primary_status != 'REMOVED' AND segments.date DURING THIS_MONTH\"\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
0,
0
],
"id": "cbb45312-e808-4c10-9954-8d400d67e542",
"name": "HTTP Request",
"credentials": {
"googleAdsOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"fieldToSplitOut": "results",
"options": {}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
224,
0
],
"id": "3038129f-b22c-482f-a4da-8f475e2e7191",
"name": "Split Out"
},
{
"parameters": {
"mode": "raw",
"jsonOutput": "={\n \"clicks\": {{ $json.metrics.clicks || 0 }},\n \"conversion_value\": {{ $json.metrics.conversionsValue || 0 }},\n \"conversions\": {{ $json.metrics.conversions || 0 }},\n \"costMicros\": {{ $json.metrics.costMicros || 0 }},\n \"impressions\": {{ $json.metrics.impressions || 0 }}\n}",
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
448,
0
],
"id": "e1b78a50-c26b-4331-bc57-28d33f43638e",
"name": "Edit Fields"
},
{
"parameters": {
"jsCode": "const safeDiv = (num, den) => (den ? num / den : null);\nconst rnd = (n, d = 6) => (n == null ? null : Number(n.toFixed(d)));\n\nlet records = [];\nif (items.length > 0) {\n const first = items[0].json || {};\n if (Array.isArray(first.data)) {\n records = first.data;\n } else if ('clicks' in first) {\n records = items.map(i => i.json);\n }\n}\n\nlet totals = {\n clicks: 0,\n impressions: 0,\n conversions: 0,\n conversion_value: 0,\n costMicros: 0,\n};\n\nfor (const r of records) {\n totals.clicks += Number(r.clicks ?? 0);\n totals.impressions += Number(r.impressions ?? 0);\n totals.conversions += Number(r.conversions ?? 0);\n totals.conversion_value += Number(r.conversion_value ?? 0);\n totals.costMicros += Number(r.costMicros ?? 0);\n}\n\nconst cost = totals.costMicros / 1e6;\nconst hasValue = totals.conversion_value > 0;\n\nconst result = {\n clicks: totals.clicks,\n impressions: totals.impressions,\n conversions: rnd(totals.conversions),\n conversion_value: hasValue ? rnd(totals.conversion_value) : 0,\n cost: rnd(cost),\n ctr: rnd(safeDiv(totals.clicks, totals.impressions)),\n cvr: rnd(safeDiv(totals.conversions, totals.clicks)),\n cpa: rnd(safeDiv(cost, totals.conversions)),\n roas: hasValue ? rnd(safeDiv(totals.conversion_value, cost)) : null,\n};\n\nreturn [{ json: { this_month: result } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
672,
0
],
"id": "5700a2d1-9a41-41c9-9b91-c0b2d0050c8c",
"name": "Code"
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-224,
16
],
"id": "2d51937c-7513-48b3-8e69-0a50908eadf7",
"name": "When clicking \u2018Execute workflow\u2019"
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.this_month }}",
"options": {
"systemMessage": "Create a comprehensive daily report based on this accounts Google Ads performance. "
}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 2.2,
"position": [
880,
0
],
"id": "8dfc1624-7c37-46b1-bd7b-4661f76e90e6",
"name": "AI Agent"
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1,
"position": [
880,
256
],
"id": "cb40f05d-8ad9-4bef-9dd2-dbae1ad66256",
"name": "Google Gemini Chat Model",
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"sendTo": "<insert-email-here>",
"subject": "Daily Report - <insert-account-name-here>",
"emailType": "text",
"message": "={{ $json.output }}",
"options": {}
},
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
1232,
0
],
"id": "0f5efdd6-4c8b-4c70-ae6b-5a3b8910b25d",
"name": "Send a message",
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
}
}
],
"connections": {
"HTTP Request": {
"main": [
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Send a message",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "e901b4fd-b063-4c13-9666-47203638dae7",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "T3v6pLvTvsZzptYK",
"tags": []
}
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.
gmailOAuth2googleAdsOAuth2ApigooglePalmApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
daily-report-agent. Uses httpRequest, agent, lmChatGoogleGemini, gmail. Event-driven trigger; 8 nodes.
Source: https://github.com/Pitcocy/ppc-summit-resources/blob/8c7c830de300284d90a04dfc60ae65f39b2ddb77/n8n-workflows/daily-report-agent.json — 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.
Arvifund - Supabase (Fixed v6). Uses httpRequest, telegram, supabase, telegramTrigger. Event-driven trigger; 92 nodes.
Arvifund - Supabase (Fixed v5). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 91 nodes.
Arvifund - Supabase. Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
Arvifund - Supabase (Fixed v2). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.
Arvifund - Supabase (Fixed v4). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.