{
  "name": "AdCritter Daily Campaign Briefing",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * *"
            }
          ]
        }
      },
      "id": "0e1919af-4211-4caa-9567-cf562808bfb3",
      "name": "Every day at 8am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        1872,
        -96
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "cfg-advertiser-id",
              "name": "advertiserId",
              "value": "REPLACE_WITH_YOUR_ADVERTISER_ID",
              "type": "string"
            },
            {
              "id": "cfg-lookback-hours",
              "name": "lookbackHours",
              "value": 168,
              "type": "number"
            },
            {
              "id": "cfg-email-to",
              "name": "emailTo",
              "value": "you@yourcompany.com",
              "type": "string"
            },
            {
              "id": "cfg-email-from",
              "name": "emailFrom",
              "value": "you@yourcompany.com",
              "type": "string"
            },
            {
              "id": "cfg-email-subject-prefix",
              "name": "emailSubjectPrefix",
              "value": "AdCritter daily briefing",
              "type": "string"
            },
            {
              "id": "cfg-llm-model",
              "name": "llmModel",
              "value": "claude-sonnet-4-5",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "7b50c81b-9055-4540-bd1e-c042df8fbc2e",
      "name": "Setup (edit this)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2096,
        -96
      ],
      "notes": "Single config surface for this workflow.\n\nadvertiserId: UUID of the AdCritter advertiser to monitor. Find it in your AdCritter dashboard URL or via GET /v1/advertisers.\nlookbackHours: How far back to look for live campaigns. 168 = 7-day rolling window (recommended); drop to 24 for a strict next-day cadence on newly-launched campaigns only.\nemailTo / emailFrom: Recipient and sender for the briefing email.\nemailSubjectPrefix: Leading text in the email subject line.\nllmModel: Claude model id used by the agent. If you change this, also update the model in the Anthropic Chat Model node."
    },
    {
      "parameters": {
        "url": "=https://api.adcritter.com/v1/advertisers/{{$json.advertiserId }}/campaigns",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "activatedFrom",
              "value": "={{ $now.minus({ hours: $('Setup (edit this)').first().json.lookbackHours }).toISO() }}"
            },
            {
              "name": "status",
              "value": "Live"
            }
          ]
        },
        "options": {}
      },
      "id": "c6576d3e-86c2-4e34-a993-5c83340ac65d",
      "name": "List newly-live campaigns",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2320,
        -96
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "data.items",
        "options": {}
      },
      "id": "2b5c1286-e3dd-4f97-9b78-d53b69b002fc",
      "name": "Split into individual campaigns",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        2544,
        -96
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "eec2c5b4-6d6a-4abd-abe1-306d8e73c1e7",
      "name": "Skip if no new campaigns",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        2768,
        -96
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Investigate this campaign and write a briefing.\n\nCampaign:\n- id: {{ $json.id }}\n- name: {{ $json.name }}\n- advertiserId: {{ $('Setup (edit this)').first().json.advertiserId }}\n- activatedDate: {{ $json.activatedDate }}\n\nDo NOT skip straight to writing. Investigate first by calling tools. You have the full AdCritter agent MCP available. At a MINIMUM, do all of the following before you write:\n\n1. Call the campaign 'get' action for this campaign id, scoped to this advertiser. Note the budget, budgetFrequency, geo tier and values, audience type and segments, attached adIds, and any dayparting or frequency cap.\n\n2. Call the report 'snapshot' action for this advertiser. Find the row whose campaignId matches and read its pacing, todaySpend, intervalBudget, averageSpendPerDay, intervalCpm, and intervalTotalClicks.\n\n3. Call the report 'campaignDetailed' action for this campaign, with start = the activatedDate and end = today (ISO 8601). Read the totals (impressions, clicks, spend, ctr, cpc, cpm) and scan the daily timeSeries. Even one or two days of data is informative for a brand-new campaign.\n\n4. If anything in steps 1 to 3 raises a question, follow it. Examples of legitimate follow-ups: if there are zero impressions, look at the ads to see whether any are actually attached and approved; if pacing is far above 1.0, check the geo tier to see whether targeting is narrow enough to burn budget; if CTR is unusually high or low, check the audience segments. You decide what to chase.\n\nOnly after you have the data, write a briefing. Rules for the briefing:\n- 4 to 8 sentences of plain prose. No markdown, no headers, no bullet lists.\n- Lead with the single most notable observation. Anchor it in a specific number from the report.\n- Then give one or two sentences of context (what the campaign is configured to do, who it is targeting).\n- End with one concrete suggestion only if a real one is warranted. If the campaign looks healthy and uneventful, say so plainly. Do not invent concerns to seem useful.\n- Never state a number you did not see in a tool result. If a tool errored or returned empty, say what was missing rather than guessing.\n- use names, not ids or indexes for references.\n\nReturn ONLY the briefing prose. No preamble like 'Here is the briefing'.",
        "options": {
          "systemMessage": "You are a marketing analyst investigating one AdCritter campaign at a time. You think by calling tools. You do NOT write your final answer until you have actually inspected the campaign config, the snapshot report, and the detailed campaign report. Three tool calls is a floor, not a ceiling. When a result surprises you, you make another tool call to understand why. Every claim in your final briefing must be traceable to a specific tool result. If a tool fails, you say what failed; you do not invent the data.",
          "maxIterations": 12
        }
      },
      "id": "00d02a8c-add9-4ad9-b717-3eff85b052b1",
      "name": "AI: brief this campaign",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        2992,
        -96
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-5"
        },
        "options": {
          "temperature": 0.3
        }
      },
      "id": "77f28692-4917-4859-98b2-e452084c0eca",
      "name": "Anthropic Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.3,
      "position": [
        3008,
        128
      ]
    },
    {
      "parameters": {
        "endpointUrl": "https://mcp.adcritter.com/mcp/agent",
        "authentication": "headerAuth",
        "options": {}
      },
      "id": "79617a01-03f7-43b4-8846-f1847a6dd954",
      "name": "AdCritter Agent MCP",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "typeVersion": 1.2,
      "position": [
        3200,
        128
      ]
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "e53eb360-0e6c-4c1b-b17b-eafe4ac15fd4",
      "name": "Combine briefings",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        3344,
        -96
      ]
    },
    {
      "parameters": {
        "toRecipients": "={{ $(\"Setup (edit this)\").first().json.emailTo }}",
        "subject": "={{ $json.output.subject }}",
        "bodyContent": "={{ $json.output.html }}",
        "additionalFields": {
          "bodyContentType": "html",
          "saveToSentItems": true
        }
      },
      "id": "b61ad2f0-b826-4147-98be-eb9b55e6688e",
      "name": "Send briefing email",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        4032,
        -96
      ]
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-4-6",
          "cachedResultName": "Claude Sonnet 4.6"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "typeVersion": 1.4,
      "position": [
        3568,
        128
      ],
      "id": "6c52f16e-2cea-4dcd-b0ab-8dbd08a23a70",
      "name": "Anthropic Chat Model1"
    },
    {
      "parameters": {
        "endpointUrl": "https://mcp.adcritter.com/mcp/agent",
        "authentication": "headerAuth",
        "options": {}
      },
      "id": "8a5c5891-0c59-4753-9c0b-b259d347cd31",
      "name": "AdCritter Agent MCP1",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "typeVersion": 1.2,
      "position": [
        3696,
        128
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.data.map(d => d.output).join('\n\n---\n\n') }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "You are an email drafting professional. Format this content into a nice email format that we can send out for daily reporting.\n\nThe content you will be receiving is a Claude analysis of campaigns in an ad management platform. It will provide its own insights, which you should use, but format it all into an easy to understand daily report email.\n\nYou must return a JSON object with two fields:\n- subject: A concise email subject line (e.g., \"Daily Campaign Report - May 8, 2026\")\n- html: The full HTML email body with proper formatting",
          "maxIterations": 12
        }
      },
      "id": "a795f500-9280-432b-8ab0-2bb24fdca607",
      "name": "Write Email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        3632,
        -96
      ]
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"subject\":\"Daily Campaign Report - May 8, 2026\",\n  \"html\":\"<html>...</html>\"\n}"
      },
      "id": "e5188fc4-ec1d-4299-8dcd-d2a9d708aac7",
      "name": "Email Format Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        3824,
        128
      ]
    }
  ],
  "pinData": {},
  "connections": {
    "Every day at 8am": {
      "main": [
        [
          {
            "node": "Setup (edit this)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Setup (edit this)": {
      "main": [
        [
          {
            "node": "List newly-live campaigns",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List newly-live campaigns": {
      "main": [
        [
          {
            "node": "Split into individual campaigns",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split into individual campaigns": {
      "main": [
        [
          {
            "node": "Skip if no new campaigns",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip if no new campaigns": {
      "main": [
        [
          {
            "node": "AI: brief this campaign",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI: brief this campaign",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AdCritter Agent MCP": {
      "ai_tool": [
        [
          {
            "node": "AI: brief this campaign",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "AI: brief this campaign": {
      "main": [
        [
          {
            "node": "Combine briefings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine briefings": {
      "main": [
        [
          {
            "node": "Write Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Write Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AdCritter Agent MCP1": {
      "ai_tool": [
        [
          {
            "node": "Write Email",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Write Email": {
      "main": [
        [
          {
            "node": "Send briefing email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Format Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Write Email",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "meta": {},
  "tags": []
}
