{
  "name": "Ads and analytics attribution report",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * *"
            }
          ]
        }
      },
      "id": "853c4820-01ff-4740-ad8a-cd46c7a723bb",
      "name": "Every morning",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        417
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://graph.facebook.com/v21.0/act_REPLACE_ME/insights",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "level",
              "value": "campaign"
            },
            {
              "name": "date_preset",
              "value": "yesterday"
            },
            {
              "name": "fields",
              "value": "campaign_name,spend"
            }
          ]
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api"
      },
      "id": "b6bb142b-f84c-48a8-a368-6b7aa90ba78e",
      "name": "Meta spend",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        512,
        300
      ],
      "credentials": {
        "oAuth2Api": {
          "id": "REPLACE_ME",
          "name": "Meta"
        }
      }
    },
    {
      "parameters": {
        "resource": "report",
        "operation": "get",
        "propertyId": {
          "__rl": true,
          "value": "REPLACE_ME",
          "mode": "id"
        },
        "metricsGA4": {
          "metricValues": [
            {
              "listName": "conversions"
            }
          ]
        },
        "dimensionsGA4": {
          "dimensionValues": [
            {
              "listName": "campaignName"
            }
          ]
        },
        "dateRange": "yesterday"
      },
      "id": "4a8afb1a-e853-4224-a12b-0bb39fb908ac",
      "name": "GA4 conversions",
      "type": "n8n-nodes-base.googleAnalytics",
      "typeVersion": 2,
      "position": [
        512,
        534
      ],
      "credentials": {
        "googleAnalyticsOAuth2": {
          "id": "REPLACE_ME",
          "name": "Google Analytics"
        }
      }
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByFields",
        "fieldsToMatchString": "campaign_name"
      },
      "id": "26f2b015-8c1d-4952-ab2e-b6e36f31f87d",
      "name": "Join on campaign",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        784,
        417
      ]
    },
    {
      "parameters": {
        "jsCode": "const TARGET = 450;\nconst out = $input.all().map(i => {\n  const spend = Number(i.json.spend || 0);\n  const conv = Number(i.json.conversions || 0);\n  const cpc = conv > 0 ? spend / conv : null;\n  return { json: { campaign: i.json.campaign_name, spend, conversions: conv, cost_per_conversion: cpc, over_target: cpc === null ? spend > 0 : cpc > TARGET } };\n});\nreturn out;"
      },
      "id": "333c0b9e-3f59-4c37-a09a-1cb9c48933ec",
      "name": "Cost per conversion",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1056,
        417
      ]
    },
    {
      "parameters": {
        "operation": "upsert",
        "schema": {
          "__rl": true,
          "value": "public",
          "mode": "list"
        },
        "table": {
          "__rl": true,
          "value": "campaign_daily",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [
            "campaign"
          ]
        }
      },
      "id": "196b68ec-d76c-4d1b-a6a3-8961795bdcea",
      "name": "Save to Postgres",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        1328,
        300
      ],
      "credentials": {
        "postgres": {
          "id": "REPLACE_ME",
          "name": "Postgres (self-hosted)"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "o1",
              "leftValue": "={{ $json.over_target }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "1cbc7a50-9f9e-41bd-ad90-6abf5e13c928",
      "name": "Over target?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1328,
        534
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "growth",
          "mode": "name"
        },
        "text": "=Over target: {{ $json.campaign }} spent {{ $json.spend }} for {{ $json.conversions }} conversions.",
        "otherOptions": {}
      },
      "id": "2c26b462-f098-4b9b-a7e0-8ae1f3bfb1e4",
      "name": "Flag in Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1600,
        534
      ],
      "credentials": {
        "slackApi": {
          "id": "REPLACE_ME",
          "name": "Slack"
        }
      }
    }
  ],
  "connections": {
    "Every morning": {
      "main": [
        [
          {
            "node": "Meta spend",
            "type": "main",
            "index": 0
          },
          {
            "node": "GA4 conversions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Meta spend": {
      "main": [
        [
          {
            "node": "Join on campaign",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GA4 conversions": {
      "main": [
        [
          {
            "node": "Join on campaign",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Join on campaign": {
      "main": [
        [
          {
            "node": "Cost per conversion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cost per conversion": {
      "main": [
        [
          {
            "node": "Save to Postgres",
            "type": "main",
            "index": 0
          },
          {
            "node": "Over target?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Over target?": {
      "main": [
        [
          {
            "node": "Flag in Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false,
    "description": "Spend from Meta, sessions and conversions from GA4, joined on the campaign."
  },
  "tags": []
}