This workflow corresponds to n8n.io template #13745 — we link there as the canonical source.
This workflow follows the Google Sheets → HTTP Request 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": "il6jbx3WZTbZ4uWL",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "meta ads reporting by client template",
"tags": [],
"nodes": [
{
"id": "a0d67daf-1c5d-4d17-986b-d46fec916cdd",
"name": "Get row(s) in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
208,
0
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11repzs1T85xH0waYFkngj8nNzqisWZ27K4gjNKVNlZU/edit#gid=0",
"cachedResultName": "clients data"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "11repzs1T85xH0waYFkngj8nNzqisWZ27K4gjNKVNlZU",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/11repzs1T85xH0waYFkngj8nNzqisWZ27K4gjNKVNlZU/edit?usp=drivesdk",
"cachedResultName": "client_registry_copy"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "910c7dd6-b90a-48e9-8c75-b29fbc06f65a",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
416,
0
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "aab68f51-d8a7-4742-af9b-bf155dc776a8",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
160,
-192
],
"parameters": {
"color": 4,
"width": 176,
"content": "Loads the [client list](https://docs.google.com/spreadsheets/d/11repzs1T85xH0waYFkngj8nNzqisWZ27K4gjNKVNlZU/edit?usp=sharing) (one row per client). Each row contains the Meta ad account ID, API access token, and the destination Google Sheets report URL."
},
"typeVersion": 1
},
{
"id": "d807ee28-2c2c-4d88-ac09-509d252c766a",
"name": "HTTP Request \u0432 ads manager \u043a\u043b\u0438\u0435\u043d\u0442\u0430",
"type": "n8n-nodes-base.httpRequest",
"position": [
944,
0
],
"parameters": {
"url": "={{ 'https://graph.facebook.com/v25.0/act_' + $json.ad_account_id + '/insights' }}",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "level",
"value": "={{$json.metrics_level || 'campaign'}}"
},
{
"name": "date_preset",
"value": "yesterday"
},
{
"name": "fields",
"value": "campaign_name,spend,impressions,clicks,ctr,cpm,cpc,date_start,date_stop"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $json.meta_access_token }}"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "a920ef57-a601-4f8c-a4fb-3e5a0c6f2eab",
"name": "Split campaigns",
"type": "n8n-nodes-base.code",
"position": [
1440,
-32
],
"parameters": {
"jsCode": "const campaigns = $json.data || [];\nif (!Array.isArray(campaigns) || campaigns.length === 0) return [];\n\nreturn campaigns.map(c => ({\n ad_account_id: $json.ctx.ad_account_id,\n report_sheet_url: $json.ctx.report_sheet_url,\n \nsheet_list: $json.sheet_list,\n // \u0434\u0430\u0442\u0430 \u043e\u0442\u0447\u0451\u0442\u0430 \u0438\u0437 Meta\n report_date: c.date_start,\n\n // \u043c\u0435\u0442\u0440\u0438\u043a\u0438\n campaign_name: c.campaign_name,\n spend: Number(c.spend),\n impressions: Number(c.impressions),\n clicks: Number(c.clicks),\n ctr: Number(c.ctr),\n cpm: Number(c.cpm),\n cpc: Number(c.cpc),\n\n date_start: c.date_start,\n date_stop: c.date_stop,\n}));"
},
"typeVersion": 2
},
{
"id": "500061bf-198c-4e45-b503-3813cba84daf",
"name": "Extract spreadsheetId",
"type": "n8n-nodes-base.code",
"position": [
1584,
64
],
"parameters": {
"jsCode": "const url = $json.report_sheet_url;\nif (!url) throw new Error('report_sheet_url \u043f\u0443\u0441\u0442\u043e\u0439');\n\nconst match = url.match(/\\/d\\/([a-zA-Z0-9-_]+)/);\nif (!match) throw new Error('\u041d\u0435 \u043d\u0430\u0448\u043b\u0430 spreadsheetId \u0432 \u0441\u0441\u044b\u043b\u043a\u0435');\n\nreturn [{\n ...$json,\n report_spreadsheet_id: match[1],\n}];"
},
"typeVersion": 2
},
{
"id": "da8344be-b467-4ec8-a330-4b1b9d2235b9",
"name": "ctx",
"type": "n8n-nodes-base.code",
"position": [
624,
0
],
"parameters": {
"jsCode": "return [{\n ...$json,\n ctx: {\n client_id: $json.client_id,\n client_name: $json.client_name,\n timezone: $json.timezone,\n ad_account_id: $json.ad_account_id,\n report_sheet_url: $json.report_sheet_url,\n meta_access_token: $json.meta_access_token,\n metrics_level: $json.metrics_level,\n }\n}];"
},
"typeVersion": 2
},
{
"id": "527145ad-9971-48f7-a084-9fec00b96655",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1280,
-160
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "b403d77c-c2fb-44be-9097-9ed39ecdb9f4",
"name": "Append row in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1760,
176
],
"parameters": {
"columns": {
"value": {},
"schema": [
{
"id": "ad_account_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ad_account_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "report_date",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "report_date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "campaign_name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "campaign_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "spend",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "spend",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "impressions",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "impressions",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "clicks",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "clicks",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ctr",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ctr",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "cpm",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "cpm",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "cpc",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "cpc",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "date_start",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "date_start",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "date_stop",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "date_stop",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "report_sheet_url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "report_sheet_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "report_spreadsheet_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "report_spreadsheet_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "sheet_list",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "sheet_list",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "autoMapInputData",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "={{$json.sheet_list}}"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{$json.report_spreadsheet_id}}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "a1943933-f0f1-43de-9117-d87a41921d29",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
1920,
272
],
"parameters": {
"jsCode": "const rows = $input.all();\nconst first = rows[0]?.json || {};\n\n// Detect client\nconst clientName =\n first.client_name ||\n first.ctx?.client_name ||\n \"Client\";\n\nconst clientId =\n first.client_id ||\n first.ctx?.client_id ||\n first.ad_account_id ||\n first.ctx?.ad_account_id ||\n \"N/A\";\n\n// Detect report date\nconst reportDate =\n first.report_date ||\n first.date_start ||\n \"Yesterday\";\n\nlet message = `\ud83d\udcca Meta Ads Daily Summary\\n`;\nmessage += `\ud83d\udc64 Client: ${clientName} (ID: ${clientId})\\n`;\nmessage += `\ud83d\udcc5 Date: ${reportDate}\\n\\n`;\n\nlet totalSpend = 0;\nlet totalImpressions = 0;\nlet totalClicks = 0;\n\nfor (const r of rows) {\n totalSpend += Number(r.json.spend || 0);\n totalImpressions += Number(r.json.impressions || 0);\n totalClicks += Number(r.json.clicks || 0);\n}\n\nconst totalCTR = totalImpressions ? (totalClicks / totalImpressions) * 100 : 0;\nconst totalCPC = totalClicks ? (totalSpend / totalClicks) : 0;\n\nmessage += `\ud83d\udcb0 Total Spend: ${totalSpend.toFixed(1)}\\n`;\nmessage += `\ud83d\udc40 Impressions: ${totalImpressions}\\n`;\nmessage += `\ud83d\uddb1 Clicks: ${totalClicks}\\n`;\nmessage += `\ud83d\udcc8 CTR: ${totalCTR.toFixed(1)}%\\n`;\nmessage += `\ud83d\udcb2 CPC: ${totalCPC.toFixed(2)}\\n\\n`;\nmessage += `-------------------------\\n\\n`;\n\nfor (const r of rows) {\n const name = r.json.campaign_name ?? \"(no campaign_name)\";\n const spend = Number(r.json.spend || 0);\n const ctr = Number(r.json.ctr || 0);\n const cpc = Number(r.json.cpc || 0);\n\n let status = \"\u2705 OK\";\n if (ctr < 1.5) status = \"\u274c Weak creative (low CTR)\";\n else if (cpc > 0.5) status = \"\u26a0 Expensive click (high CPC)\";\n else if (ctr >= 2 && cpc <= 0.5) status = \"\ud83d\udd25 Good candidate to scale\";\n\n message += `\ud83c\udfaf ${name}\\n`;\n message += `\ud83d\udcb0 Spend: ${spend.toFixed(1)}\\n`;\n message += `\ud83d\udcc8 CTR: ${ctr.toFixed(1)}%\\n`;\n message += `\ud83d\udcb2 CPC: ${cpc.toFixed(2)}\\n`;\n message += `\u27a1 ${status}\\n\\n`;\n}\n\nconst reportUrl = first.report_sheet_url || first.ctx?.report_sheet_url;\n\nif (reportUrl) {\n message += `\ud83d\udd17 Report: ${reportUrl}`;\n}\n\nreturn [{ json: { message } }];"
},
"typeVersion": 2
},
{
"id": "092a81b7-82a1-4dd1-bebb-cd00305cceec",
"name": "Send a text message",
"type": "n8n-nodes-base.telegram",
"position": [
2112,
400
],
"parameters": {
"text": "={{$json.message}}",
"chatId": "123456789",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "27b89fb7-7a1b-427b-b834-eca94276b32c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
0,
0
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 10
}
]
}
},
"typeVersion": 1.3
},
{
"id": "e39ddb13-da5c-4a64-b3a2-26de76b9a9aa",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
1088,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f5b502b7-bd6c-44e8-8b0b-2c7d04eddc86",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{$json.data.length}}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.3
},
{
"id": "2b94cfaa-7930-47a7-80b2-1a8b3c8e1c77",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
-272
],
"parameters": {
"width": 288,
"height": 400,
"content": "## How it works\n**Purpose:** Automate daily Meta Ads reporting for multiple clients. \n\n**Flow:** Read client config from Google Sheets \u2192 loop through clients \u2192 request campaign insights from Meta Ads API \u2192 split campaigns into rows \u2192 append to each client\u2019s report sheet \u2192 send Telegram status message. \n\n**Inputs:** client_register sheet (ad_account_id, access_token, report_sheet_url). \n\n**Outputs:** campaign-level rows in Google Sheets + Telegram notification."
},
"typeVersion": 1
},
{
"id": "1d7ce9ea-bd9f-496c-9574-47fd69d78762",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-32,
160
],
"parameters": {
"color": 6,
"width": 166,
"height": 112,
"content": "Runs on a schedule to automate daily/weekly reporting without manual execution."
},
"typeVersion": 1
},
{
"id": "c50d4baa-500b-4b83-8716-38b3b0ce25af",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
-192
],
"parameters": {
"color": 6,
"width": 150,
"content": "Loops through each client from the register sheet so we can generate a report for multiple ad accounts in a single run."
},
"typeVersion": 1
},
{
"id": "6ad09d47-9a14-40de-b40b-c62401ff10d3",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
-192
],
"parameters": {
"color": 6,
"width": 176,
"content": "Builds a context object (ad_account_id, access_token, report_sheet_url, settings) to simplify mapping in the next nodes and keep the workflow readable."
},
"typeVersion": 1
},
{
"id": "ea51a1fb-c5a9-4a51-a198-4599843eb29f",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
896,
-320
],
"parameters": {
"color": 4,
"width": 192,
"height": 224,
"content": "Sends a request to the Meta Ads Insights endpoint for the current ad account and returns campaign-level metrics (spend, impressions, clicks, CTR, CPM, CPC, dates). Uses token from the client context."
},
"typeVersion": 1
},
{
"id": "052f866c-544f-4755-81cb-32d03d7674cc",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
-336
],
"parameters": {
"color": 6,
"width": 208,
"height": 144,
"content": "Merges the client context (where to write) with the campaign data (what to write), so downstream nodes have everything in a single payload."
},
"typeVersion": 1
},
{
"id": "4c49abd6-d72c-4686-b535-2e7ccf78f173",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1920,
176
],
"parameters": {
"color": 5,
"width": 368,
"height": 80,
"content": "Aggregates results (e.g., number of rows written / clients processed) and generates a clean Telegram message indicating success or issues."
},
"typeVersion": 1
},
{
"id": "f3f9a168-3aff-4d7f-83cf-52717f91f890",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1744,
64
],
"parameters": {
"color": 6,
"width": 384,
"height": 96,
"content": "Appends a row for each campaign into the destination Google Sheet. Column mapping matches the report schema (account id, date, campaign name, spend, impressions, clicks, etc.)."
},
"typeVersion": 1
},
{
"id": "de38643c-a982-4349-a7e2-024dff2ce6dd",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1440,
-176
],
"parameters": {
"color": 6,
"width": 304,
"height": 112,
"content": "Splits the API response array into individual items so each campaign becomes one row in Google Sheets. Also normalizes numeric fields (Number()) and maps columns."
},
"typeVersion": 1
},
{
"id": "395ffbd6-5d6c-405f-8b26-47725dea2dbc",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
1584,
-48
],
"parameters": {
"color": 6,
"width": 384,
"height": 96,
"content": "Parses the report_sheet_url and extracts the spreadsheetId (and optionally sheet name/tab) so the Google Sheets node can write to the correct document dynamically."
},
"typeVersion": 1
},
{
"id": "9d6f2f82-d691-49f7-9aa0-85114f84fb06",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
2096,
304
],
"parameters": {
"color": 4,
"width": 384,
"height": 80,
"content": "Sends a Telegram alert with the workflow summary (success, processed clients, total rows appended). Useful for monitoring scheduled runs."
},
"typeVersion": 1
},
{
"id": "3d537eed-7cf9-497e-90f0-15adf67ff6a7",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
784,
-944
],
"parameters": {
"width": 448,
"height": 592,
"content": "## How to Generate a Meta Ads Access Token (Per Ad Account Setup)\nGo to Meta for Developers:\n\ud83d\udc49 https://developers.facebook.com/\n\nOpen your apps dashboard:\n\ud83d\udc49 https://developers.facebook.com/apps/\n\nSelect your app (or click Create App).\n\nOpen Graph API Explorer:\n\ud83d\udc49 https://developers.facebook.com/tools/explorer/\n\nIn Graph API Explorer:\n\nSelect your app\n\nClick Add Permissions\n\nAdd ads_read (and ads_management if needed)\n\nClick Generate Access Token\n\nVerify your token here:\n\ud83d\udc49 https://developers.facebook.com/tools/debug/accesstoken/\n\n(Optional) Create a long-lived token using the OAuth endpoint:\n\ud83d\udc49 https://graph.facebook.com/v18.0/oauth/access_token"
},
"typeVersion": 1
},
{
"id": "8b08350d-e6bc-4380-a426-e6094d067558",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
2352,
528
],
"parameters": {
"color": 7,
"width": 384,
"height": 640,
"content": "\ud83d\udcca Meta Ads Daily Summary\n\ud83d\udc64 Client: Bloom Florals (ID: 781399151515449)\n\ud83d\udcc5 Date: 2026-02-24\n\n\ud83d\udcb0 Total Spend: 320.5\n\ud83d\udc40 Impressions: 18,450\n\ud83d\uddb1 Clicks: 512\n\ud83d\udcc8 CTR: 2.8%\n\ud83d\udcb2 CPC: 0.63\n\n\ud83c\udfaf Valentine Special \u2013 Insta DM\n\ud83d\udcb0 Spend: 180.0\n\ud83d\udcc8 CTR: 3.1%\n\ud83d\udcb2 CPC: 0.58\n\u27a1\ufe0f \ud83d\udd25 Good candidate to scale\n\n\ud83c\udfaf Wedding Bouquet Promo\n\ud83d\udcb0 Spend: 95.5\n\ud83d\udcc8 CTR: 1.2%\n\ud83d\udcb2 CPC: 0.92\n\u27a1\ufe0f \u274c Weak creative (low CTR)\n\n\ud83c\udfaf Same-Day Delivery Offer\n\ud83d\udcb0 Spend: 45.0\n\ud83d\udcc8 CTR: 2.0%\n\ud83d\udcb2 CPC: 0.45\n\u27a1\ufe0f \u2705 OK\n\n\ud83d\udd17 Report: https://docs.google.com/spreadsheets/d/1FJfNoZK6M1z0zsZVK41MnPmZ2Sy0HQEARCf7gojVXVY/edit?usp=sharing"
},
"typeVersion": 1
},
{
"id": "392ca80f-8832-4947-8062-0de03b6ea839",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
2288,
448
],
"parameters": {
"width": 150,
"height": 80,
"content": "The structure of the message that goes to telegram"
},
"typeVersion": 1
},
{
"id": "6c64e739-f8d2-4cef-a982-0db4ba5bdd51",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
2304,
-256
],
"parameters": {
"color": 5,
"width": 496,
"height": 512,
"content": "Status Logic (Campaign Diagnostics)\n\nEach campaign is evaluated based on CTR and CPC thresholds.\n\nThe status is determined using the following logic:\n\nWeak Creative (\u274c)\n\nIf CTR < 1.5%\n\u2192 Indicates low engagement. The ad creative may need improvement.\n\nExpensive Click (\u26a0)\n\nIf CPC > 0.5\n\u2192 Indicates high cost per click. Audience or bidding may need optimization.\n\nGood Candidate to Scale (\ud83d\udd25)\n\nIf CTR \u2265 2% AND CPC \u2264 0.5\n\u2192 Strong performance. The campaign may be suitable for scaling.\n\nOK (\u2705)\n\nIf none of the above conditions are met\n\u2192 Campaign performance is within acceptable range."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "9c660c98-3da9-4a40-a0ba-211545ded2a7",
"connections": {
"If": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
],
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"ctx": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
},
{
"node": "HTTP Request \u0432 ads manager \u043a\u043b\u0438\u0435\u043d\u0442\u0430",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Split campaigns",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "ctx",
"type": "main",
"index": 0
}
]
]
},
"Split campaigns": {
"main": [
[
{
"node": "Extract spreadsheetId",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"Append row in sheet": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Send a text message": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Extract spreadsheetId": {
"main": [
[
{
"node": "Append row in sheet",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request \u0432 ads manager \u043a\u043b\u0438\u0435\u043d\u0442\u0430": {
"main": [
[
{
"node": "If",
"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.
googleSheetsOAuth2ApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
I built this workflow to remove the daily pain of Meta Ads reporting. If you manage multiple ad accounts, you know how time-consuming it is to open Ads Manager, export campaign data, clean spreadsheets, and send updates to clients.
Source: https://n8n.io/workflows/13745/ — 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 transforms your Meta Ads creatives into a rich dataset of actionable insights. It's designed for data-driven marketers, performance agencies, and analysts who want to move beyond basic m
I created this workflow with great care to help you simplify your daily reporting routine. If you manage Meta Ads campaigns, you know how time-consuming it can be to open Ads Manager, filter data, and
This workflow monitors Meta Ads and Google Ads campaigns on a daily schedule to detect performance drops. It fetches yesterday’s campaign data, standardizes metrics, and calculates CTR and ROAS agains
Track companies adopting tools that complement yours and send AI-drafted co-marketing outreach emails to new adopters.
This automation is ideal for sales teams, digital marketers, support agents, or small business owners who collect leads in Google Sheets and want to automatically send WhatsApp welcome messages. It's