{
  "name": "Generate Meta Ads campaign reports in Google Sheets and send Telegram alerts",
  "nodes": [
    {
      "id": "a0d67daf-1c5d-4d17-986b-d46fec916cdd",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        208,
        0
      ]
    },
    {
      "id": "910c7dd6-b90a-48e9-8c75-b29fbc06f65a",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        416,
        0
      ]
    },
    {
      "id": "aab68f51-d8a7-4742-af9b-bf155dc776a8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -192
      ],
      "parameters": {
        "width": 176,
        "height": null,
        "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"
      }
    },
    {
      "id": "d807ee28-2c2c-4d88-ac09-509d252c766a",
      "name": "HTTP Request в ads manager клиента",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        944,
        0
      ]
    },
    {
      "id": "a920ef57-a601-4f8c-a4fb-3e5a0c6f2eab",
      "name": "Split campaigns",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        -32
      ]
    },
    {
      "id": "500061bf-198c-4e45-b503-3813cba84daf",
      "name": "Extract spreadsheetId",
      "type": "n8n-nodes-base.code",
      "position": [
        1584,
        64
      ]
    },
    {
      "id": "da8344be-b467-4ec8-a330-4b1b9d2235b9",
      "name": "ctx",
      "type": "n8n-nodes-base.code",
      "position": [
        624,
        0
      ]
    },
    {
      "id": "527145ad-9971-48f7-a084-9fec00b96655",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1280,
        -160
      ]
    },
    {
      "id": "b403d77c-c2fb-44be-9097-9ed39ecdb9f4",
      "name": "Append row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1760,
        176
      ]
    },
    {
      "id": "a1943933-f0f1-43de-9117-d87a41921d29",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        1920,
        272
      ]
    },
    {
      "id": "092a81b7-82a1-4dd1-bebb-cd00305cceec",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2112,
        400
      ]
    },
    {
      "id": "27b89fb7-7a1b-427b-b834-eca94276b32c",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ]
    },
    {
      "id": "e39ddb13-da5c-4a64-b3a2-26de76b9a9aa",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        1088,
        0
      ]
    },
    {
      "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 → loop through clients → request campaign insights from Meta Ads "
      }
    },
    {
      "id": "1d7ce9ea-bd9f-496c-9574-47fd69d78762",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        160
      ],
      "parameters": {
        "width": 166,
        "height": 112,
        "content": "Runs on a schedule to automate daily/weekly reporting without manual execution."
      }
    },
    {
      "id": "c50d4baa-500b-4b83-8716-38b3b0ce25af",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -192
      ],
      "parameters": {
        "width": 150,
        "height": null,
        "content": "Loops through each client from the register sheet so we can generate a report for multiple ad accounts in a single run."
      }
    },
    {
      "id": "6ad09d47-9a14-40de-b40b-c62401ff10d3",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -192
      ],
      "parameters": {
        "width": 176,
        "height": null,
        "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."
      }
    },
    {
      "id": "ea51a1fb-c5a9-4a51-a198-4599843eb29f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        -320
      ],
      "parameters": {
        "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."
      }
    },
    {
      "id": "052f866c-544f-4755-81cb-32d03d7674cc",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        -336
      ],
      "parameters": {
        "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."
      }
    },
    {
      "id": "4c49abd6-d72c-4686-b535-2e7ccf78f173",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1920,
        176
      ],
      "parameters": {
        "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."
      }
    },
    {
      "id": "f3f9a168-3aff-4d7f-83cf-52717f91f890",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1744,
        64
      ],
      "parameters": {
        "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.)."
      }
    },
    {
      "id": "de38643c-a982-4349-a7e2-024dff2ce6dd",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        -176
      ],
      "parameters": {
        "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."
      }
    },
    {
      "id": "395ffbd6-5d6c-405f-8b26-47725dea2dbc",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        -48
      ],
      "parameters": {
        "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."
      }
    },
    {
      "id": "9d6f2f82-d691-49f7-9aa0-85114f84fb06",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2096,
        304
      ],
      "parameters": {
        "width": 384,
        "height": 80,
        "content": "Sends a Telegram alert with the workflow summary (success, processed clients, total rows appended). Useful for monitoring scheduled runs."
      }
    },
    {
      "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👉 https://developers.facebook.com/\n\nOpen your apps dashboard:\n👉 https://developers.facebook.com/apps/\n\nSele"
      }
    },
    {
      "id": "8b08350d-e6bc-4380-a426-e6094d067558",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2352,
        528
      ],
      "parameters": {
        "width": 384,
        "height": 640,
        "content": "📊 Meta Ads Daily Summary\n👤 Client: Bloom Florals (ID: 781399151515449)\n📅 Date: 2026-02-24\n\n💰 Total Spend: 320.5\n👀 Impressions: 18,450\n🖱 Clicks: 512\n📈 CTR: 2.8%\n💲 CPC: 0.63\n\n🎯 Valentine Special – Insta"
      }
    },
    {
      "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"
      }
    },
    {
      "id": "6c64e739-f8d2-4cef-a982-0db4ba5bdd51",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        -256
      ],
      "parameters": {
        "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 (❌)\n\nIf CTR < 1.5%\n→ Indicates low "
      }
    }
  ],
  "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 в ads manager клиента",
            "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 в ads manager клиента": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}