기술 포스트 · Analytics Ops (GA4·GTM)
GA4 + BigQuery로 ROAS 파이프라인 직접 만들기 — 플랫폼 대시보드 못 믿을 때
Meta 광고 매니저 ROAS와 GA4 ROAS가 30% 차이 납니다. 둘 다 거짓말은 아닌데 어느 쪽도 믿기 어려워요. 원천 이벤트로 직접 ROAS 파이프라인을 만드는 SQL 4단계.
“Meta는 ROAS 5.2라는데, GA4는 3.8이고, BigQuery 우리 자체 집계는 4.5예요. 어느 게 맞는 거죠?” — 데이터 분석가가 회의에서 이런 답을 내놓으면 마케터는 멘붕이에요. 사실 셋 다 다른 데이터·다른 정의로 답하고 있어서 모두 틀리지 않아요. 이 글은 그 혼란을 끝내는 가장 깔끔한 답 — GA4 → BigQuery 익스포트로 직접 ROAS 파이프라인을 만드는 4단계 SQL입니다.
왜 직접 만들어야 하나
플랫폼·도구별 ROAS의 한계:
| 출처 | 장점 | 한계 |
|---|---|---|
| Meta/Google Ads UI | 실시간, 캠페인 분해 쉬움 | last-click + view-through, 본인 플랫폼 광고만 |
| GA4 UI | 채널 통합, last-click 또는 data-driven | 표본 추출 적용, 14개월 보관, 수정 불가 |
| BigQuery raw export | 원천 데이터, 무한 보관, 자유 정의 | SQL 직접 짜야 함 |
자체 파이프라인의 진짜 가치는 “플랫폼이 안 보여주는 정의”를 자유롭게 만들 수 있다는 거예요.
- “브랜드 검색 제외 ROAS”
- “신규 vs 기존 분리 ROAS”
- “베이지안 신뢰구간 ROAS”
- “incrementality 보정된 ROAS”
플랫폼 UI에서는 절대 안 나오는 뷰들. 한 번 만들어두면 매주 자동으로 돌아갑니다.
1단계 — GA4 → BigQuery 익스포트 활성화
GA4 속성 설정 → BigQuery 연결 → “매일 익스포트” 옵션 켜기. 다음 날부터 다음 형식의 테이블이 자동 생성됩니다:
project.analytics_<property_id>.events_YYYYMMDD각 row가 한 이벤트(page_view, purchase, click 등). 가장 자주 쓰는 컬럼들:
| 컬럼 | 타입 | 의미 |
|---|---|---|
event_date | STRING | YYYYMMDD 형식 |
event_timestamp | INT64 | 마이크로초 단위 |
event_name | STRING | page_view, purchase 등 |
event_params | REPEATED | key-value 배열 (URL, source, campaign 등) |
ecommerce | RECORD | purchase일 때 transaction_id, purchase_revenue |
traffic_source | RECORD | source, medium, name |
device | RECORD | category, os, mobile_brand_name |
geo | RECORD | country, region, city |
user_pseudo_id | STRING | 클라이언트 ID (사용자 식별 핵심) |
가장 헷갈리는 게 event_params예요. 배열이라 SQL에서 펼쳐야(UNNEST) 합니다. “4월 구매 이벤트의 utm_source 분포는?” 같은 단순 질문도 결국 UNNEST 한 번 거쳐야 답이 나와요.
2단계 — 광고비 + 매출 일별 join
광고비는 별도로 적재해야 합니다. Google Ads는 BigQuery Data Transfer Service를 켜면 자동, 다른 채널(Meta/TikTok/Naver 등)은 매일 한 번 API로 가져와 ads_spend(date, channel, campaign_id, campaign_name, spend) 테이블에 적재.
이제 GA4 raw event에서 일별 매출을 채널·캠페인 단위로 집계해 광고비와 join하면 됩니다. SQL의 큰 흐름은 세 단계예요.
-- 단계 1: GA4 purchase 이벤트에서 utm + 매출 추출WITH purchases AS ( SELECT PARSE_DATE('%Y%m%d', event_date) AS date, ecommerce.transaction_id, ecommerce.purchase_revenue AS revenue, (SELECT value.string_value FROM UNNEST(event_params) WHERE key='source') AS utm_source, (SELECT value.string_value FROM UNNEST(event_params) WHERE key='medium') AS utm_medium, (SELECT value.string_value FROM UNNEST(event_params) WHERE key='campaign') AS utm_campaign FROM `project.analytics_<id>.events_*` WHERE event_name='purchase' AND _TABLE_SUFFIX BETWEEN '20260401' AND '20260430')-- 단계 2: utm을 채널로 매핑 (CASE WHEN으로 통일)-- 단계 3: ads_spend와 (date, channel, campaign_name) 키로 LEFT JOIN-- 결과: date | channel | campaign_name | spend | revenue | orders | roas이 한 쿼리로 “우리만의 ROAS”가 나옵니다. 정의는 마케터가 정한 last-touch utm 매칭이고, 매출은 GA4가 잡은 transaction_id 기반. 플랫폼별 임의 정의가 아니라 우리 데이터팀이 합의한 정의가 들어간 숫자예요.
3단계 — 베이지안 신뢰구간 한 칸 추가
전 글에서 다룬 Beta-Binomial을 BigQuery에서도 직접 계산할 수 있어요. 단순한 푸아송 근사(주문수가 많을 때 정규분포로 근사)로 ROAS 신뢰구간을 한 줄에:
- = 주문 수 (푸아송으로 근사)
- = 평균 객단가 (revenue / orders)
결과 예시:
| 채널 | 광고비 | 매출 | ROAS 평균 | 90% CI | 의사결정 가능? |
|---|---|---|---|---|---|
| google_ads (브랜드) | 4,500,000 | 28,800,000 | 6.40 | [6.10, 6.70] | ✅ |
| meta (prospecting) | 3,200,000 | 9,600,000 | 3.00 | [2.45, 3.55] | ✅ |
| naver (search) | 2,100,000 | 10,500,000 | 5.00 | [4.65, 5.35] | ✅ |
| tiktok (creative test) | 800,000 | 2,400,000 | 3.00 | [1.85, 4.15] | ⚠️ 폭 큼, 더 봐야 |
이 표 한 장이 마케터의 진짜 무기가 됩니다. ROAS 평균뿐 아니라 “얼마나 신뢰할 만한 추정인가”까지 한 줄에. 회의에서 “틱톡 ROAS 3”이 아니라 “틱톡 ROAS 3 (신뢰구간 1.85~4.15, 데이터 부족, 의사결정 보류)“가 나오면 토론의 차원이 달라져요.
4단계 — 일별·세그먼트별 뷰 자동화
매일 새벽 자동 실행되는 BigQuery scheduled query로 결과 테이블을 만들어두면, 마케터가 SQL 모르고도 쓸 수 있는 대시보드 테이블이 됩니다. 컬럼 구성은 다음 정도가 베이스:
| 컬럼 | 의미 |
|---|---|
date | 집계 일자 |
channel | google_ads / meta / tiktok / naver / other |
campaign_name | 캠페인 |
is_new_user | 신규 vs 기존 분리 (Simpson’s Paradox 차단) |
device_category | mobile / desktop / tablet |
spend, revenue, orders | 기본 메트릭 |
roas_mean, roas_lo, roas_hi | 신뢰구간 포함 ROAS |
status_flag | low_confidence / unprofitable / ok 자동 분류 |
이 테이블을 Looker Studio·Tableau·내부 BI로 연결하면, 마케터는 그저 필터를 바꿔가며 자기 채널·자기 캠페인 ROAS를 신뢰구간과 함께 봅니다. 이 한 테이블이 “우리 회사의 진실”이 되고, 회의에서 더 이상 “플랫폼 ROAS 5인데 GA4는 3.8” 같은 충돌이 사라져요.
잘 빠지는 함정 — 직접 만들 때만 발생하는 것들
1) Cross-day attribution 손실
GA4의 default attribution은 “last-click” 모델인데, 사용자가 4월 30일에 클릭하고 5월 1일에 결제하면 매출이 5월에 잡힙니다. 광고비는 4월 30일 spent. 일별 ROAS 계산 시 이 mismatch가 노이즈가 돼요. 해결: 월간 합계로 보거나, 7일 lag join.
2) Cross-device 이슈
같은 사람이 모바일에서 클릭하고 데스크탑에서 결제하면 user_pseudo_id가 달라져 별개 사용자로 잡힙니다. GA4 user_id(로그인 ID) 매칭을 켜뒀으면 일부 회복.
3) UTM 스펠링 차이
utm_source=facebook vs Facebook vs fb 같은 케이스. 채널 매핑 CASE WHEN을 오랜 시간 정비해야 해요. 광고팀과 “UTM 표기 가이드” 한 장 합의해두는 게 결국 가장 큰 절약.
4) 환불·캐시백 빠뜨리기
GA4 purchase 이벤트는 결제 시점이고, 환불·캐시백·할인 쿠폰은 별개 이벤트. 진짜 매출은 “purchase - refund”를 일별로 차감해야 정확.
운영 팁 — 마케터 데이터 팀이 자주 묻는 것
1) BigQuery 비용
GA4 export는 무료고, 쿼리 비용은 데이터량 기준. 한 달치 events 테이블 풀스캔 대신 _TABLE_SUFFIX BETWEEN으로 날짜 필터를 거는 게 가장 큰 절약. scheduled query 결과 테이블만 BI에 연결하고, raw events는 분석 시에만 쿼리.
2) 1차 모델은 단순하게
처음부터 “멀티터치 + 베이지안 + incrementality 보정” 다 넣으려고 하면 6개월 걸려요. 1차는 last-click + 신뢰구간 한 가지만. 2~3개월 데이터 쌓이고 마케터가 익숙해지면 그 다음 정의 추가.
3) 정의를 한 페이지 wiki로
“우리 회사의 ROAS 정의: utm_medium = (cpc|sa) 한정, 결제 후 7일 환불 차감, 채널 매칭은 ___표 따름” — 이 한 페이지가 가장 큰 운영 자산이에요. 분기마다 갱신.
4) 실험 분석에도 같은 파이프라인
A/B 테스트나 geo-lift 결과도 BigQuery raw event에서 직접 분석하면, 플랫폼 도구별 결과 차이로 시간 낭비할 일이 없어요. 한 분석가가 만든 SQL을 모두가 재사용.
마치며
플랫폼 대시보드 ROAS는 “플랫폼이 자기 광고에 좋게 보이도록 정의한 숫자”예요. 그 정의를 받아들이는 한, 마케터의 분석 능력은 항상 플랫폼에 종속됩니다. GA4 raw event + BigQuery + SQL 세 가지로 자체 파이프라인을 만들면, 정의의 주도권이 마케터·데이터팀으로 돌아옵니다. 첫 SQL 200줄을 짜는 일주일이 그다음 1년의 모든 분석을 좌우해요.
이 글로 “마케터를 위한 데이터 시리즈” 10편이 마무리됩니다. 베이지안 어트리뷰션부터 GA4 자체 파이프라인까지, 광고·실험·CRM·LLM·BI를 관통하는 마케터의 데이터 무기들을 같이 정리해봤어요.
참고
- GA4 BigQuery Export 공식 문서 — 익스포트 활성화·스키마
- BigQuery — events_* 테이블 스키마 — 모든 컬럼 정의
- GA4 dimensions and metrics — UNNEST 패턴 — event_params 펼치기
- Looker Studio + BigQuery 연결 — BI 시각화
- The Data Warehouse Toolkit — Kimball — 마케팅 데이터 모델링 표준서
Analytics Ops (GA4·GTM) 카테고리의 다른 글
전체 보기 →-
2026·05·16
광고 SQL·BI 안티패턴 7가지 — ROAS 보고서를 거짓말로 만드는 SQL 함정
광고 데이터를 SQL로 집계할 때 반복적으로 깨지는 7가지 패턴 — 중복 조인·attribution window 누락·시간대 미스·conversion lag·환율·채널 매핑·dedup. 마케터·BI팀이 실무에서 만나는 함정을 실제 SQL 반례와 함께 정리합니다.
-
2026·05·09
Marketing analytics maturity model — last-click부터 triangulation까지 5단계
마케팅 측정의 성숙도는 5단계로 나뉩니다. last-click → multi-touch → MMM → lift study → triangulation. 우리 팀이 어디 있는지 진단하고 다음 단계 로드맵을 잡는 한 가지 모델.
-
2026·05·08
Server-side Tagging과 Conversion API — 1st-party 데이터를 직접 운영하는 법
브라우저에서 보내는 픽셀이 30~50% 차단되는 시대에, 서버에서 광고 플랫폼으로 직접 이벤트를 보내는 server-side tagging과 Meta CAPI·GA4 Measurement Protocol·TikTok Events API의 핵심을 마케터 시선에서 정리합니다.
-
2026·05·06
CDP 시대의 ID 그래프 — 쿠키 없이 유저를 어떻게 잇나
3rd party cookie 종말과 iOS 14.5 이후 유저 식별이 어떻게 바뀌었는지, ID 그래프가 deterministic·probabilistic 매칭으로 어떻게 동작하는지 마케터 시각으로 정리.