발행일: 2026-10-06(화) 11:44
← 목차로 돌아가기|하루 30분 n8n 시리즈 ② 실무 자동화 레시피 100
RECIPE 013

광고 성과 일간 리포트 자동 생성

  • ▸Webhook 또는 Google Forms Trigger로 폼 응답을 수신할 수 있다
  • ▸응답 내용을 기준으로 IF/Switch 노드로 담당자를 자동 배정할 수 있다
  • ▸담당자에게 배정 알림 이메일과 Slack 메시지를 동시에 발송할 수 있다

✅사전 준비

  • □Google Forms 또는 Typeform 자격증명 연결 완료
  • □담당자별 이메일/Slack ID 목록 준비
  • □Gmail + Slack 자격증명 연결 완료
  • □Google Sheets에 배정 이력 저장용 시트 생성

담당자 배정 로직 — Code 노드

const category = $input.first().json.category; // 폼 응답의 카테고리 필드

const assignees = {
  "기술 문의":  { name: "김개발", email: "dev@company.com",   slack: "U012345" },
  "결제 문의":  { name: "이결제", email: "pay@company.com",   slack: "U023456" },
  "일반 문의":  { name: "박지원", email: "cs@company.com",    slack: "U034567" },
};

const assignee = assignees[category] ?? assignees["일반 문의"];

return [{ json: { ...assignee, category, formData: $input.first().json } }];

Gmail — 담당자 배정 알림 메일

<h3>📬 새 문의가 배정되었습니다</h3>
<p><b>카테고리:</b> {{ $json.category }}</p>
<p><b>문의 내용:</b> {{ $json.formData.message }}</p>
<p><b>제출자:</b> {{ $json.formData.name }} ({{ $json.formData.email }})</p>
<p><b>제출 시각:</b> {{ $now.toFormat("yyyy-MM-dd HH:mm") }}</p>
💡 TIPGoogle Forms의 응답을 Trigger로 받으려면 Apps Script에서 Webhook을 연결하거나, Sheets에 응답이 기록되는 것을 Google Sheets Trigger로 감지하는 방법이 더 안정적입니다.
⚡

워크플로우 JSON

아래 JSON을 복사해 n8n에 바로 임포트하세요

📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
  "name": "recipe013_ad_daily_report",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "30 7 * * *"
            }
          ]
        }
      },
      "id": "schedule-013-01",
      "name": "매일 오전 7시 30분",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        200,
        400
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://googleads.googleapis.com/v17/customers/{{ $env.GOOGLE_ADS_CUSTOMER_ID }}/googleAds:search",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "SELECT campaign.name, metrics.impressions, metrics.clicks, metrics.conversions, metrics.cost_micros FROM campaign WHERE segments.date DURING YESTERDAY"
            }
          ]
        },
        "options": {}
      },
      "id": "http-013-02",
      "name": "Google Ads 전일 성과 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        420,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const results = $json.results || [];\nlet impressions = 0, clicks = 0, conversions = 0, costMicros = 0;\nresults.forEach(r => {\n  impressions += parseInt(r.metrics?.impressions || 0);\n  clicks += parseInt(r.metrics?.clicks || 0);\n  conversions += parseFloat(r.metrics?.conversions || 0);\n  costMicros += parseInt(r.metrics?.cost_micros || 0);\n});\nconst cost = Math.round(costMicros / 1000000);\nconst ctr = impressions > 0 ? (clicks / impressions * 100).toFixed(2) : '0.00';\nconst cpa = conversions > 0 ? Math.round(cost / conversions) : 0;\nreturn [{ json: { impressions, clicks, conversions: Math.round(conversions), cost, ctr, cpa, date: $now.minus({days:1}).format('YYYY-MM-DD') } }];"
      },
      "id": "code-013-03",
      "name": "성과 데이터 집계",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        640,
        400
      ]
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "value": "={{ $env.ADS_REPORT_SHEET_ID }}"
        },
        "sheetName": {
          "value": "google_ads"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "date": "={{ $json.date }}",
            "impressions": "={{ $json.impressions }}",
            "clicks": "={{ $json.clicks }}",
            "ctr": "={{ $json.ctr }}",
            "conversions": "={{ $json.conversions }}",
            "cost": "={{ $json.cost }}",
            "cpa": "={{ $json.cpa }}"
          }
        },
        "options": {
          "upsertOptions": {
            "upsertKey": "date"
          }
        }
      },
      "id": "sheets-013-04",
      "name": "Google Sheets 누적 기록",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        860,
        400
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": "#marketing-ads",
        "text": "=📊 어제의 광고 성과 요약 ({{ $json.date }})\n노출수: {{ $json.impressions.toLocaleString() }}회\n클릭수: {{ $json.clicks.toLocaleString() }}회 (CTR {{ $json.ctr }}%)\n전환수: {{ $json.conversions }}건\n광고비: ₩{{ $json.cost.toLocaleString() }}\nCPA: ₩{{ $json.cpa.toLocaleString() }}"
      },
      "id": "slack-013-05",
      "name": "Slack 리포트 발송",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1080,
        400
      ]
    }
  ],
  "connections": {
    "매일 오전 7시 30분": {
      "main": [
        [
          {
            "node": "Google Ads 전일 성과 가져오기",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Ads 전일 성과 가져오기": {
      "main": [
        [
          {
            "node": "성과 데이터 집계",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "성과 데이터 집계": {
      "main": [
        [
          {
            "node": "Google Sheets 누적 기록",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets 누적 기록": {
      "main": [
        [
          {
            "node": "Slack 리포트 발송",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "timezone": "Asia/Seoul"
  },
  "meta": {
    "chapter": 2,
    "recipe": "013",
    "title": "광고 성과 일간 리포트 자동 생성",
    "difficulty": "⭐⭐",
    "estimatedTime": "40분",
    "apps": [
      "Google Ads API",
      "Google Sheets",
      "Slack"
    ]
  }
}
← 이전 레시피☰ 목차다음 레시피 →