AutomationFlowsAI & RAG › Analyze Meta Ads Daily with Google Gemini and Google Sheets

Analyze Meta Ads Daily with Google Gemini and Google Sheets

ByBakdaulet Abdikhan @bakdaulet-abdikhan on n8n.io

Stop manually exporting CSVs and start automating your marketing insights.

Event trigger★★★★☆ complexityAI-powered25 nodesGmailChain LlmGoogle SheetsOutput Parser StructuredGoogle Gemini ChatFacebook Graph ApiError Trigger
AI & RAG Trigger: Event Nodes: 25 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #12416 — we link there as the canonical source.

This workflow follows the Chainllm → 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 →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "fead4f03-9842-47f8-838f-c5137b2f0d5a",
      "name": "Template Guide",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -32
      ],
      "parameters": {
        "width": 486,
        "height": 608,
        "content": "## Analyze Meta ads with Gemini and Google Sheets\n\n**How it works:**\n1.  **Extract:** Fetches Ad and Campaign data from Meta API (Yesterday's data).\n2.  **Process:** Aggregates data by Campaign and Ad Set using Code node.\n3.  **Analyze:** Sends data to Gemini to generate qualitative insights for both Client and Agency.\n4.  **Save:** Exports raw data and AI insights to Google Sheets.\n\n**Setup steps:**\n1.  **Configuration:** Update the `Set Configuration` node with your `Ad Account ID` and `Email`.\n2.  **Credentials:** Authenticate your `Facebook Graph API`, `Google Sheets`, `Gmail`, and `Google Gemini` credentials.\n3.  **Spreadsheet:** Create a Google Sheet and update the `Save...` nodes with your Spreadsheet ID.\n4. **Facebook Graph API** [Guide](https://docs.google.com/document/d/1ydWNom0TUVh5SkU9IymlpnM_NXbTqHeL_YetDLn-9m0/edit?usp=sharing)\n9. **Google sheets** [template](https://docs.google.com/spreadsheets/d/11M6Co13t9t2P7NtFaTm9VXHnzUHXO_RGYf-FRnHkS28/edit?usp=sharing)\n10. Use this format to pull the specific date range: `time_range[since]=YYYY-MM-DD&time_range[until]=YYYY-MM-DD`\n\n\nHappy setup,\nBakdaulet Abdikhan\n\nPS. Feel free to add slack/email nodes to notify alerts/updates ;)"
      },
      "typeVersion": 1
    },
    {
      "id": "8936023f-8462-4525-aca0-1f76203fcbd6",
      "name": "Get Config",
      "type": "n8n-nodes-base.set",
      "position": [
        1552,
        -240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "678b725a-e235-48b1-904d-1fb7ea9ad061",
              "name": "Ad Account ID",
              "type": "string",
              "value": "YOUR_ACT_ID_HERE"
            },
            {
              "id": "b0b6e2b9-6f30-4b53-a61d-485edac8d27b",
              "name": "Email",
              "type": "string",
              "value": "user@example.com"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "193a9ee7-1c12-46cb-b318-f767137a316d",
      "name": "Send Error Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1776,
        -240
      ],
      "parameters": {
        "sendTo": "={{ $('Get Config').first().json.Email }}",
        "message": "=<b>Error:</b> {{ $('Error Trigger').first().json.execution.error.message }}<br/>\n<b>Stack:</b> {{ $('Error Trigger').first().json.execution.error.stack }}<br/>\n<b>Last Node Executed:</b> {{ $('Error Trigger').first().json.execution.lastNodeExecuted }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=N8N ERROR: Daily Ad Pulse for Ad Account {{ $('Get Config').first().json['Ad Account ID'] }} Failed"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a9d35f35-e8c1-42f9-bb5b-8ca26eefc6be",
      "name": "Structure Data Hierarchy",
      "type": "n8n-nodes-base.code",
      "position": [
        784,
        128
      ],
      "parameters": {
        "jsCode": "// Get all items from previous node\nconst allItems = $input.all();\n\n// Flatten everything into one array (each item.json is an ad)\nconst ads = allItems.map(item => item.json);\n\n// Prepare campaign grouping\nconst campaigns = {};\n\nfor (const ad of ads) {\n  const {\n    campaign_id,\n    campaign_name,\n    adset_id,\n    adset_name,\n    ad_id,\n    ad_name,\n    spend,\n    reach,\n    impressions,\n    clicks,\n    ctr,\n    cpc,\n    cpm,\n    date_start,\n    date_stop,\n    results\n  } = ad;\n\n  // --- Group by Campaign ---\n  if (!campaigns[campaign_id]) {\n    campaigns[campaign_id] = {\n      campaign_id,\n      campaign_name,\n      adsets: {}\n    };\n  }\n\n  // --- Group by Adset ---\n  if (!campaigns[campaign_id].adsets[adset_id]) {\n    campaigns[campaign_id].adsets[adset_id] = {\n      adset_id,\n      adset_name,\n      ads: []\n    };\n  }\n\n  // --- Add Ad ---\n  campaigns[campaign_id].adsets[adset_id].ads.push({\n    ad_id,\n    ad_name,\n    metrics: {\n      spend,\n      reach,\n      impressions,\n      clicks,\n      ctr,\n      cpc,\n      cpm\n    },\n    results,\n    date: {\n      start: date_start,\n      stop: date_stop\n    }\n  });\n}\n\n// Convert nested objects to arrays\nconst output = Object.values(campaigns).map(campaign => ({\n  ...campaign,\n  adsets: Object.values(campaign.adsets)\n}));\n\n// Return final grouped data\nreturn [{ json: { campaigns: output } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "29c78e97-ea13-4ff3-9a9e-329a9ac3eb7d",
      "name": "Write Insights",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1216,
        128
      ],
      "parameters": {
        "text": "=Analyze the following Meta Ads data and return structured insights.\n\nData:\n{{ JSON.stringify($json.campaigns, null, 2) }}\n\nRules:\n- Always include both campaign-level and adset-level insights.\n- Write in a professional, concise tone suitable for client reports.\n- For each adset, identify:\n  - best_performing_ad\n  - worst_performing_ad\n  - adset_suggestion (1\u20132 short sentences)\n- For each campaign, summarize overall campaign performance with campaign_suggestion (1\u20132 sentences).\n\nReturn only valid JSON following this schema:\n\n[\n  {\n    \"campaign_name\": \"\",\n    \"campaign_id\": \"\",\n    \"adsets\": [\n      {\n        \"adset_name\": \"\",\n        \"adset_id\": \"\",\n        \"best_performing_ad\": \"\",\n        \"worst_performing_ad\": \"\",\n        \"adset_suggestion\": \"\"\n      }\n    ],\n    \"campaign_suggestion\": \"\"\n  }\n]\n",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are MetaInsightsGPT \u2014 an expert Meta Ads performance analyst AI working inside a marketing agency automation system.\n\nYour responsibilities:\n- Read structured JSON ad performance data (campaigns \u2192 adsets \u2192 ads).\n- Evaluate ads objectively using spend, CTR, CPC, CPM, and conversions (if available).\n- Identify the best- and worst-performing ads per adset.\n- Generate useful, data-driven insights:\n  - For the agency \u2192 what to optimize or scale.\n  - For the client \u2192 what\u2019s working and why.\n- Write in English.\n\nPerformance logic:\n- Prioritize CTR and conversions as success indicators.\n- If conversions missing, use CTR/CPC ratio.\n- Consider spend and impressions for significance.\n- Ignore zero-impression ads.\n- Never use vague words like \u201cgood\u201d, \u201cbad\u201d, \u201ctry more\u201d.\n- Always quantify insights (e.g., \u201cCTR 2.3% vs. 0.7%\u201d).\n- Output must be strictly valid JSON (no markdown, no commentary).\n\nYou output insights in a consistent JSON structure so they can be parsed into Google Sheets.\n"
            },
            {
              "type": "AIMessagePromptTemplate",
              "message": "=[\n  {\n    \"campaign_name\": \"Engagement Campaign\",\n    \"campaign_id\": \"1234567890\",\n    \"adsets\": [\n      {\n        \"adset_name\": \"Broad Targeting\",\n        \"adset_id\": \"0987654321\",\n        \"best_performing_ad\": \"Video_Variant_A\",\n        \"worst_performing_ad\": \"Image_Variant_B\",\n        \"adset_suggestion\": \"Video_Variant_A achieved 0.9% CTR with 32 clicks. Image_Variant_B underperformed with 0 clicks; consider pausing.\"\n      }\n    ],\n    \"campaign_suggestion\": \"This campaign performs efficiently (CTR ~0.9%) but has uneven engagement across adsets. Reallocate budget toward higher-performing ads.\"\n  }\n]\n"
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "8ccc0b9f-d870-4e5f-a0d0-469bb2bfecc0",
      "name": "Save AI Insights",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2032,
        128
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $now.minus({ days: 1 }).toFormat('yyyy-MM-dd') }}",
            "Ad Set": "={{ $json.adsets[0].adset_name }}",
            "Best Ad": "={{ $json.adsets[0].best_performing_ad }}",
            "Campaign": "={{ $json.campaign_name }}",
            "Worst Ad": "={{ $json.adsets[0].worst_performing_ad }}",
            "Agency Suggestion": "={{ $json.adsets[0].suggestion_for_agency }}",
            "Client Suggestion": "={{ $json.adsets[0].suggestion_for_client }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Campaign",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Campaign",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Ad Set",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Ad Set",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Best Ad",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Best Ad",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Worst Ad",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Worst Ad",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Agency Suggestion",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Agency Suggestion",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Client Suggestion",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Client Suggestion",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "AI_Insights"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1980b51b-fb7a-4b18-95aa-9cb02ec16158",
      "name": "Save Ad Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        784,
        304
      ],
      "parameters": {
        "columns": {
          "value": {
            "cpc": "={{ $json.cpc }}",
            "cpm": "={{ $json.cpm }}",
            "ctr": "={{ $json.ctr }}",
            "date": "={{ $json.date_stop }}",
            "ad_id": "={{ $json.ad_id }}",
            "reach": "={{ $json.reach }}",
            "spend": "={{ $json.spend }}",
            "clicks": "={{ $json.clicks }}",
            "ad_name": "={{ $json.ad_name }}",
            "results": "={{ $json.results[0].values[0].value }}",
            "adset_id": "={{ $json.adset_id }}",
            "adset_name": "={{ $json.adset_name }}",
            "campaign_id": "={{ $json.campaign_id }}",
            "impressions": "={{ $json.impressions }}",
            "campaign_name": "={{ $json.campaign_name }}"
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "campaign_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "campaign_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "campaign_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "campaign_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "adset_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "adset_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "adset_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "adset_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ad_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ad_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ad_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ad_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "spend",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "spend",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "results",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "results",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reach",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reach",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "impressions",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "impressions",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "clicks",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "clicks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ctr",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ctr",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "cpc",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "cpc",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "cpm",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "cpm",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Ads"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "dd95a46b-39ff-49b4-8d34-516a19a8ea73",
      "name": "Save Campaign Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1008,
        -240
      ],
      "parameters": {
        "columns": {
          "value": {
            "CPL": "={{ $json.cost_per_result[0].values[0].value }}",
            "CTR": "={{ $json.ctr }}",
            "Date": "={{ $json.date_start }}",
            "Reach": "={{ $json.reach }}",
            "Spend": "={{ $json.spend }}",
            "Clicks": "={{ $json.clicks }}",
            "Campaign ID": "={{ $json.campaign_id }}",
            "Impressions": "={{ $json.impressions }}",
            "Campaign Name": "={{ $json.campaign_name }}",
            "Conversations Started": "={{ $json.results[0].values[0].value }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Campaign ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Campaign ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Campaign Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Campaign Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reach",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Reach",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Impressions",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Impressions",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Conversations Started",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Conversations Started",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CPL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CPL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Clicks",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Clicks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CTR",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CTR",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Spend",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Spend",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Campaigns"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SPREADSHEET_ID_HERE"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "574a9644-05f3-4df0-a9d8-4fea57a8f562",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -16,
        -240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "678b725a-e235-48b1-904d-1fb7ea9ad061",
              "name": "Ad Account ID",
              "type": "string",
              "value": "YOUR_ACT_ID_HERE"
            },
            {
              "id": "b0b6e2b9-6f30-4b53-a61d-485edac8d27b",
              "name": "Email",
              "type": "string",
              "value": "user@example.com"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e86432fc-a55d-41f6-ad7f-270129ae2f7e",
      "name": "Split AI Insights",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1840,
        128
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "output"
      },
      "typeVersion": 1
    },
    {
      "id": "20e6389f-3feb-4b96-bb12-eaedb5c6cc6a",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1392,
        352
      ],
      "parameters": {
        "jsonSchemaExample": "[\n  {\n    \"campaign_name\": \"string\",\n    \"adsets\": [\n      {\n        \"adset_name\": \"string\",\n        \"best_performing_ad\": \"string\",\n        \"worst_performing_ad\": \"string\",\n        \"suggestion_for_agency\": \"string\",\n        \"suggestion_for_client\": \"string\"\n      }\n    ]\n  }\n]\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "482dd147-d952-4915-adf9-1b7766e47741",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1216,
        352
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "3650d021-a1db-494c-9869-027994b0131a",
      "name": "Get Ad Insights - Ad Level",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        368,
        128
      ],
      "parameters": {
        "edge": "insights?fields=ad_id,ad_name,adset_id,adset_name,campaign_id,campaign_name,spend,reach,impressions,clicks,results,ctr,cpc,cpm&level=ad&date_preset=yesterday",
        "node": "=act_{{ $('Set Configuration').first().json['Ad Account ID'] }}",
        "options": {},
        "graphApiVersion": "v24.0"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "131c45ee-14b8-457f-b6ea-aabe65961104",
      "name": "Get Ad Insights - Campaign Level",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        352,
        -240
      ],
      "parameters": {
        "edge": "=insights?fields=campaign_id,campaign_name,spend,impressions,clicks,results,marketing_messages_delivered,actions,reach,ctr,cost_per_result&level=campaign&date_preset=yesterday",
        "node": "=act_{{ $('Set Configuration').first().json['Ad Account ID'] }}",
        "options": {},
        "graphApiVersion": "v24.0"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "90e8a0dc-3788-4925-94b1-9fbac67d91f4",
      "name": "Split Ad Data",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        592,
        128
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "132888b7-a5ee-4985-bb70-184345e2eb9a",
      "name": "Filter Zero Spend",
      "type": "n8n-nodes-base.filter",
      "position": [
        800,
        -240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "066d6215-ac80-4510-9061-bd121fcae8ff",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.spend }}",
              "rightValue": "0"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b6db113e-a4e3-48b6-baaf-48a6050b3490",
      "name": "Split Campaign Data",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        592,
        -240
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "91b6916f-c095-4961-8c12-f4c51dc33453",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        1328,
        -240
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "39328528-4432-41cb-9928-db5520f8ea1d",
      "name": "Schedule - Once per day",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -320,
        -240
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1c62cf57-7a30-4c82-be4e-f5ee409419e8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 288,
        "content": "## Configuration & schedule\n\u2022 Define run frequency\n\u2022 Set account and reporting parameters\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5990642f-977b-4e46-9ad6-04557dfb58c7",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 880,
        "height": 288,
        "content": "## Campaign-level data collection\n\u2022 Fetch campaign performance data\n\u2022 Remove zero-spend campaigns\n\u2022 Store clean campaign metrics\n"
      },
      "typeVersion": 1
    },
    {
      "id": "23cf66be-16d5-45fb-bd5e-061ac14560ca",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 496,
        "content": "## Ad-level data collection\n\u2022 Fetch ad-level performance data\n\u2022 Normalize and structure records\n\u2022 Persist raw ad metrics\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e9927923-b091-4dfc-8b71-026663ca5f86",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 512,
        "content": "## AI analysis & insights\n\u2022 Analyze performance with Gemini\n\u2022 Detect winners and underperformers\n\u2022 Generate actionable recommendations\n"
      },
      "typeVersion": 1
    },
    {
      "id": "cb8b95e6-7967-4c67-9f7b-cfe41f2362c1",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1728,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 512,
        "content": "## Insights storage\n\u2022 Split structured AI output\n\u2022 Save insights for reporting\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e5dcc793-68a0-4f4f-8f1d-2d8a86f710cf",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        -368
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 288,
        "content": "## Error handling\n\u2022 Catch workflow failures\n\u2022 Send notification email\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Get Config": {
      "main": [
        [
          {
            "node": "Send Error Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Trigger": {
      "main": [
        [
          {
            "node": "Get Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Ad Data": {
      "main": [
        [
          {
            "node": "Save Ad Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Structure Data Hierarchy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Insights": {
      "main": [
        [
          {
            "node": "Split AI Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Zero Spend": {
      "main": [
        [
          {
            "node": "Save Campaign Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Get Ad Insights - Campaign Level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split AI Insights": {
      "main": [
        [
          {
            "node": "Save AI Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Campaign Data": {
      "main": [
        [
          {
            "node": "Filter Zero Spend",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule - Once per day": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Ad Insights - Ad Level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Write Insights",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structure Data Hierarchy": {
      "main": [
        [
          {
            "node": "Write Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Write Insights",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Get Ad Insights - Ad Level": {
      "main": [
        [
          {
            "node": "Split Ad Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Ad Insights - Campaign Level": {
      "main": [
        [
          {
            "node": "Split Campaign Data",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Stop manually exporting CSVs and start automating your marketing insights.

Source: https://n8n.io/workflows/12416/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

HTTP Request, Google Sheets, OpenRouter Chat +5
AI & RAG

Automate your lead intake, scoring, and outreach pipeline. This workflow collects leads from forms, enriches and scores them using Relevance AI, routes them by quality, and triggers the right follow-u

Form Trigger, HTTP Request, Chain Llm +6
AI & RAG

This workflow creates a sophisticated, self-improving customer support system that automatically handles incoming emails. It's designed to answer common questions using an AI-powered knowledge base an

Text Classifier, Chain Llm, Gmail Trigger +4
AI & RAG

Perfect for use cases such as: 💼 Finance teams managing vendor invoices 📊 Bookkeeping workflows 🔄 Automating monthly reconciliation

Output Parser Structured, HTTP Request, Gmail Trigger +4
AI & RAG

Community nodes are used, and template can only be used on self-hosted n8n instances.

@Apify/N8N Nodes Apify, Google Sheets, Gmail +3