RECIPE 022
구글 애널리틱스 트래픽 급락 → 자동 경고
- ▸Webhook 또는 Google Drive Trigger로 CSV 파일 업로드를 감지할 수 있다
- ▸CSV 데이터를 파싱해 빈 값, 중복, 형식 오류를 자동 정제할 수 있다
- ▸정제된 데이터를 Google Sheets에 저장하고 오류 행만 별도 시트에 기록할 수 있다
✅사전 준비
- □Google Drive 자격증명 연결 완료
- □Google Sheets 자격증명 연결 완료
- □Sheets에 정제 결과 저장용 시트 2개 생성: '정제완료' / '오류행'
- □처리할 CSV 컬럼 구조 확정 (예: 이름/이메일/전화번호/가입일)
CSV 파싱 — Spreadsheet File 노드 설정
Operation: Read
File Format: CSV
Options:
Header Row: true
Delimiter: , (콤마)
Include Empty: false데이터 정제 — Code 노드
const items = $input.all();
const clean = [];
const errors = [];
items.forEach(({ json }) => {
const issues = [];
// 이메일 형식 검증
if (!json.이메일?.match(/^[^@]+@[^@]+\.[^@]+$/)) {
issues.push('이메일 형식 오류');
}
// 필수값 체크
if (!json.이름?.trim()) issues.push('이름 누락');
// 전화번호 정제 (숫자+하이픈만)
if (json.전화번호) {
json.전화번호 = json.전화번호.replace(/[^0-9-]/g, '');
}
if (issues.length > 0) {
errors.push({ ...json, 오류내용: issues.join(', ') });
} else {
clean.push(json);
}
});
return [
...clean.map(j => ({ json: { ...j, _type: 'clean' } })),
...errors.map(j => ({ json: { ...j, _type: 'error' } })),
];정제완료/오류 분기 — IF 노드
조건: {{ $json._type === 'clean' }}
True → Sheets '정제완료' 시트에 Append
False → Sheets '오류행' 시트에 Append💡 TIP중복 제거가 필요하다면 Code 노드에서 이메일 기준으로 Map을 만들어 마지막 값만 남기는 방식을 쓰세요. const unique = Object.values(Object.fromEntries(items.map(i => [i.이메일, i]))) 한 줄로 처리됩니다.
⚡
워크플로우 JSON
아래 JSON을 복사해 n8n에 바로 임포트하세요
📥 n8n 임포트 방법
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
n8n 화면 우측 상단 메뉴 (⋮) → Import from JSON → 아래 JSON 전체 복사 후 붙여넣기 → Import 클릭
{
"name": "recipe022_ga_traffic_drop_alert",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * *"
}
]
}
},
"id": "schedule-022-01",
"name": "매일 오전 9시",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
200,
400
]
},
{
"parameters": {
"method": "POST",
"url": "https://analyticsdata.googleapis.com/v1beta/properties/{{ $env.GA4_PROPERTY_ID }}:runReport",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "dateRanges",
"value": "=[{\"startDate\": \"yesterday\", \"endDate\": \"yesterday\"}, {\"startDate\": \"7daysAgo\", \"endDate\": \"7daysAgo\"}]"
},
{
"name": "metrics",
"value": "[{\"name\": \"sessions\"}]"
}
]
},
"options": {}
},
"id": "http-022-02",
"name": "GA4 세션 데이터 가져오기",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
420,
400
]
},
{
"parameters": {
"jsCode": "const rows = $json.rows || [];\nconst yesterday = parseInt(rows[0]?.metricValues?.[0]?.value || 0);\nconst lastWeek = parseInt(rows[1]?.metricValues?.[0]?.value || 0);\nconst dropRate = lastWeek > 0 ? ((lastWeek - yesterday) / lastWeek * 100).toFixed(1) : 0;\nconst isAlert = parseFloat(dropRate) >= 30;\nreturn [{ json: { yesterday, lastWeek, dropRate, isAlert } }];"
},
"id": "code-022-03",
"name": "트래픽 감소율 계산",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
640,
400
]
},
{
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.isAlert }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
]
}
},
"id": "if-022-04",
"name": "30% 이상 급락 여부 확인",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
860,
400
]
},
{
"parameters": {
"resource": "message",
"operation": "post",
"channel": "#marketing-alerts",
"text": "=🚨 트래픽 이상 감지!\n어제 세션: {{ $json.yesterday.toLocaleString() }}\n전주 동일: {{ $json.lastWeek.toLocaleString() }}\n감소율: -{{ $json.dropRate }}%\n→ SEO 또는 서버 문제 가능성을 확인해주세요."
},
"id": "slack-022-05",
"name": "Slack 경고 발송",
"type": "n8n-nodes-base.slack",
"typeVersion": 2.2,
"position": [
1080,
300
]
}
],
"connections": {
"매일 오전 9시": {
"main": [
[
{
"node": "GA4 세션 데이터 가져오기",
"type": "main",
"index": 0
}
]
]
},
"GA4 세션 데이터 가져오기": {
"main": [
[
{
"node": "트래픽 감소율 계산",
"type": "main",
"index": 0
}
]
]
},
"트래픽 감소율 계산": {
"main": [
[
{
"node": "30% 이상 급락 여부 확인",
"type": "main",
"index": 0
}
]
]
},
"30% 이상 급락 여부 확인": {
"main": [
[
{
"node": "Slack 경고 발송",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"timezone": "Asia/Seoul"
},
"meta": {
"chapter": 2,
"recipe": "022",
"title": "구글 애널리틱스 트래픽 급락 → 자동 경고",
"difficulty": "⭐⭐⭐",
"estimatedTime": "45분",
"apps": [
"Google Analytics API",
"Google Sheets",
"Slack"
]
}
}