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 클릭
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"
]
}
}