Q. 이벤트 택소노미는 무엇부터 정해야 하나?
이벤트 이름이 아니라 비즈니스 질문부터다. 질문이 정해지면 이벤트 목록은 따라 나오고, 그다음 진짜 결정은 각 값을 파라미터로 보낼지 아니면 안 보내고 나중에 조인으로 되살릴지다. 이벤트 46개를 정리한 표에서 안 보내기로 한 파라미터가 14개였고, 안 보내는 이유는 다섯 갈래로 갈렸다.
오늘 바로 쓸 핵심 3줄
- 이벤트가 답하는 질문을 한 문장으로 못 쓰면 그 이벤트는 만들지 마라
- 안 보내는 파라미터도 행으로 남겨라, 이유마다 되살리는 방법이 다르다
- 전진 이벤트를 만들 때 후퇴 이벤트를 같은 자리에서 같이 만들어라
정의서엔 있는데 화면엔 없었다
이미 만들어져 돌고 있던 이벤트 정의서를 코드와 화면에 하나씩 대 본 적이 있다. 40여 개 이벤트였고 문서상으로는 깔끔했지. 대조를 끝내고 나니 이런 것들이 나왔다.
- 상담 버튼 클릭 이벤트가 정의돼 있는데, 그 버튼 컴포넌트를 렌더하는 페이지가 사이트에 하나도 없었다
- 이름이
open_..._modal인데 실제 동작은 모달이 아니라 다른 주소로 넘어가는 라우트 진입이었다 - 요금 요약을 봤다는 이벤트가 화면폭 1024px 미만에서는 아예 발화하지 않았다, 그 컴포넌트가 모바일에서 다른 것으로 대체되니까
- 파라미터 이름은 정의서와 코드가 100% 일치했는데,
item_category가 읽는 변수가category였고 거기엔 서비스 유형이 아니라 카테고리 번호가 들어 있었다
넷 다 개별 버그처럼 보이지. 그런데 원인은 하나. 이벤트를 먼저 정의하고 화면 확인을 마지막에 했다. 순서를 뒤집으면 저 넷이 전부 안 생긴다.
그래서 이 글은 이름 짓기 규칙집이 아니다. 답할 질문은 셋. 무엇부터 정하나. 마흔 개가 넘는 이벤트를 한 장에 어떻게 담나. 그리고 가장 손이 많이 가는 것, 보낼 값과 안 보낼 값을 어떻게 가르나.
겪은 것과 조사한 것. 위 증상 넷과 뒤에 나오는 표 구조는 실제로 운영하고 검수한 것이다. 반면 GA4의 각종 한도는 내가 부딪혀 본 게 아니라 구글 공식 문서에서 확인한 숫자이고, 마지막 절의 오프페이지 이벤트는 아직 구현하지 않은 설계 제안이다. 어느 쪽인지 그때그때 밝혀 두었다.
최상류는 이벤트 이름이 아니라 질문이다
택소노미(taxonomy)라는 말이 어렵게 들리지만 뜻은 단순하다. 무엇을 어떤 이름으로 어떤 값과 함께 기록할지 정해 둔 분류 체계다. 도서관 분류표와 같은 것.
여기서 대부분이 이벤트 목록부터 만든다. 화면을 훑으며 클릭할 만한 걸 세고, 그럴듯한 이름을 붙이고, 나중에 "이건 왜 재나" 칸을 채운다. 순서가 정확히 거꾸로다.
1번과 2번은 코드에도 화면에도 안 적혀 있다. 사람이 정해야 해서 상류다.
1번을 답이 나오는 형태로 쓰는 게 전부라고 해도 과장이 아니다. "관심도를 분석한다"는 질문이 아니다. 그건 문장 부호만 붙인 소망이지. "상품 상세를 본 사람 중 몇 퍼센트가 상담을 신청하나"가 질문이다. 앞의 것으로는 어떤 이벤트도 폐기할 수 없고, 뒤의 것으로는 필요한 이벤트가 정확히 둘이라는 게 바로 나온다.
업계 표준도 같은 순서지. Amplitude의 트래킹 플랜 가이드는 사용자와 제품 사용에 대해 지금 가장 알고 싶은 질문들을 적어 내려가는 것에서 시작하라고 하고, 이벤트 목록은 활성화 경로를 이해하는 데 필요한 핵심 소수로 시작해 나머지는 무시하라고 범위를 좁힌다.
2번, 화면 매핑을 건너뛰면 어떻게 되는지는 이 글 첫머리에 이미 나왔다. 화면에 없는 UI에 이벤트가 생긴다. 그래서 검수 규칙을 하나만 둔다면 이거지. 각 이벤트에 대해 "이 화면 이 요소"를 지목할 수 있어야 한다.
못 지목하면 셋 중 하나지. 화면 진입이나 노출을 재는 이벤트라 요소가 없는 게 정상이거나, 서버에서 쏘는 이벤트라 웹에 요소가 없는 게 정상이거나, 아니면 설계가 화면보다 앞서 있는 것. 앞의 둘이면 그렇게 적어 두고, 셋째면 UI를 만들 계획이 실제로 있는지 확인하거나 이벤트를 뺀다.
한 문장으로 질문을 못 쓰는 이벤트는 만들지 않는다.
이벤트 하나가 한 행이 아니라, 이벤트와 파라미터 한 쌍이 한 행이다
질문과 화면이 정리되면 표를 만들 차례. 여기서 형태를 잘못 잡으면 뒤가 전부 고생이지.
가장 흔한 형태는 이벤트 하나에 한 행을 주고 파라미터를 한 칸에 쉼표로 나열하는 것이다. 처음엔 읽기 좋다. 이벤트가 마흔 개를 넘어가는 순간 무너지지.
파라미터를 셀 안에 나열하면 그 파라미터의 상태·타입·출처를 적을 자리가 사라진다.
이 구조를 쓰면 이벤트 46개짜리 표가 179행이 된다. 길어 보이지만 얻는 게 크지. 파라미터 이름으로 검색이 되고, 상태로 필터가 되고, 무엇보다 스크립트가 이 표를 읽어 다른 산출물을 만들 수 있다.
마지막 항목이 실은 제일 중요하지. 정의서와 GTM 컨테이너와 프론트엔드 타입 정의를 사람이 손으로 세 군데 맞추면 반드시 어긋난다. 한 소스에서 셋을 생성하면 어긋날 수가 없지. 표가 기계도 읽을 수 있는 모양이어야 그게 가능하다.
컬럼은 "없으면 사람이 매번 답해야 하는가"로 정한다
컬럼을 늘리는 건 공짜가 아니다. 채워야 하고, 안 채우면 거짓말이 된다. 그래서 기준을 하나 두면 편하지. 이 칸이 비어 있을 때 사람이 매번 손으로 답하게 되는가. 그렇다면 컬럼으로 만든다.
| 컬럼 | 없으면 매번 사람이 답해야 하는 질문 | 값 예시 |
|---|---|---|
| 구현 담당 | 이게 안 뜨는데 누가 고치나? | FE / BE / GTM / GA4 자동 |
| 관리 상태 | 이건 이미 돌고 있나, 만들어야 하나? | 운영 / 구현 필요 / 수정 필요 / 백로그 |
| 우선순위 | 다음 스프린트에 뭘 넣나? | 1~5 |
| GA4 스코프·타입 | 맞춤 측정기준을 어느 스코프로 등록하나? | event · string · custom |
| 파라미터 상태 | 이 값이 비면 버그인가 정상인가? | 필수 / 선택 / 제외 / 분기 전용 |
| 수집 시점·조건 | 언제 찍히는 숫자로 읽어야 하나? | 서버 성공 응답 직후 |
| PII 규칙 | 이 이벤트에 개인정보가 실려도 되나? | 원문 금지, 비식별 조인키만 |
| 중복·품질 | 같은 행동이 두 번 세어지지 않나? | 아이템당 1건, event_id로 제거 |
이 중 구현 담당이 실무에서 제일 자주 값을 한다. 결함 하나가 나올 때마다 고칠 곳이 네 갈래로 갈리는데, 표를 재생성하면 끝나는 것과 GTM 컨테이너를 발행해야 하는 것과 프론트엔드 배포가 필요한 것과 백엔드 팀에 넘겨야 하는 것이 전혀 다른 일정이기 때문이다. 담당 컬럼이 있으면 이 분류가 회의가 아니라 조회로 끝난다.
예시값은 실제 형식으로 적어라. 어느 식별자의 예시값이 DB-20260608-001로 적혀 있었는데 실제로는 정수 7이었다. 그대로 구현하면 틀린다. 같은 이유로 결정값인지 랜덤인지도 밝힌다. evt_ab12cd34처럼 적어 두면 개발자는 랜덤 문자열을 만들고, 그러면 뒤에 나올 서버 중복 제거가 통째로 깨진다.
진짜 결정은 "이 값을 보낼까 말까"다
여기가 이 글의 갈림길이고, 표를 만들면서 가장 오래 붙잡고 있던 지점이다. 값 하나를 앞에 두고 매번 같은 판단을 한다. 이걸 파라미터로 실어 보낼까, 안 보내고 나중에 다른 테이블과 붙여서 되살릴까.
먼저 왜 이 판단을 아예 건너뛸 수는 없는지. GA4에는 한도가 있고 숫자는 이렇다. 아래는 구글 공식 문서에서 확인한 값이다.
| 한도 | 표준 속성 | Analytics 360 |
|---|---|---|
| 이벤트당 이벤트 파라미터 | 25개 | 동일 |
| 이벤트 스코프 맞춤 측정기준 | 50개 | 125개 |
| 사용자 스코프 맞춤 측정기준 | 25개 | 100개 |
| 아이템 스코프 맞춤 측정기준 | 10개 | 25개 |
| 사용자 속성 | 속성당 25개 | 동일 |
| 파라미터 값 길이 | 100자 | 동일 |
이벤트당 25개는 웬만해선 안 부딪힌다. 진짜로 조이는 건 맞춤 측정기준 슬롯이지. 이벤트 스코프 50개는 이벤트가 마흔 개를 넘는 계정에서 생각보다 빨리 찬다. 게다가 한도에 걸려 지우고 다시 등록하려면 48시간을 기다려야 한다. 잘못 등록했을 때 되돌리는 비용이 이틀이라는 뜻.
그런데 한도는 이 판단의 진짜 이유가 아니다. 진짜 이유는 따로 있지. 보낸 값은 그 이벤트에 계속 붙어 다니고, 안 보낸 값은 되살릴 방법이 반드시 필요하다. 그래서 표에서 제외로 표시한 파라미터도 지우지 않고 행으로 남긴다. 안 보낸다는 사실 자체가 정보라서.
안 보내는 이유는 다섯 갈래다
46개 이벤트 표에서 전송하지 않기로 표시된 파라미터가 14개였는데(제외 12개 + 트리거 분기 전용 2개), 세어 보니 이유가 한 종류가 아니었다. 다섯이었고, 이유마다 나중에 되살리는 방법이 다르다.
제외는 한 덩어리가 아니다. 왜 제외했는지에 따라 나중에 할 일이 완전히 달라진다.
1번부터 4번은 사실상 무료지. 안 보내도 잃는 게 없고, 정보가 이미 다른 경로에 있거나 애초에 정보가 아니었으니까. 2번이 특히 헷갈리기 쉬운데, 콘텐츠 정독 이벤트가 "본문 50% 도달과 활성 체류 30초"를 조건으로 발화한다면 그 이벤트에 실린 50과 30은 언제나 50과 30이다. 변하지 않는 값을 백만 번 보내는 셈이지.
문제는 5번 하나. 그리고 여기가 실무에서 제일 자주 잘못 판단되는 자리.
조인키가 결정적인가, 시간창인가
상속의 대표적인 사례. 사용자가 상품 페이지에서 전화 버튼을 눌렀다고 하자. 이때 버튼 위치와 페이지 경로가 웹 이벤트에 실린다. 몇 초 뒤 실제로 통화가 연결되면 그건 웹이 아니라 전화 시스템 쪽에서 서버가 쏘는 이벤트다.
서버는 버튼 위치를 모른다. 브라우저 안에서 벌어진 일이니까. 여기서 두 갈래가 생기지. 프론트엔드가 버튼 위치를 서버까지 실어 보내게 하거나, 아니면 안 보내고 나중에 두 테이블을 붙여서 되살리거나.
이미지: 같은 거리를 건너도 다리로 건너는 것과 넓은 띠 위로 건너는 것은 다르다. 후자는 도착점이 하나로 정해지지 않는다.
후자를 택할 때 결과를 가르는 건 무엇으로 붙이느냐 하나뿐이다. 그리고 조인키에는 성질이 다른 두 종류가 있다.
같은 표 안에 두 종류의 조인이 섞여 있는데, 표만 보면 둘 다 그냥 조인이라고 적혀 있다.
결정적 키는 리드 식별자처럼 한 값이 한 대상을 유일하게 가리키는 것이다. 웹 제출 이벤트에 리드 번호가 실려 있고 개통 확정 이벤트에도 같은 리드 번호가 실려 있으면, 상담을 시작시킨 버튼이 무엇이었는지는 조인 한 번으로 되살아난다. 손실이 없지.
시간창 조인은 다르지. 노출한 전화번호와 클릭 시각으로 붙이는 방식인데, 같은 번호를 두 사람이 1분 안에 누르면 어느 클릭이 어느 통화인지 알 방법이 없다. 그리고 이때 쿼리는 오류를 내지 않는다. 그냥 둘 중 하나를 고르거나 둘 다 붙여 버리고, 리포트에는 멀쩡한 숫자가 뜬다. 오프라인 전환을 이을 때 겪는 문제와 정확히 같은 구조다.
그래서 결정 규칙은 이렇게 굳었다.
| 이 값을 잇는 조인키 | 판단 | 표에 적을 것 |
|---|---|---|
| 결정적 키가 이미 두 이벤트에 다 실린다 | 안 보낸다 | 조인키 이름과 어느 이벤트에서 상속하는지 |
| 결정적 키를 만들 수 있다 (클릭 번호 발급 등) | 먼저 키를 만든다 | 키 발급 주체와 전달 경로 |
| 시간창밖에 없다 | 보낸다 | 보내는 이유, 나중에 빼자는 제안 차단용 |
| 조인할 상대 테이블이 아직 없다 | 보낸다 | 조인 대상이 생기면 재검토 |
세 번째 줄이 중요하지. 보내기로 한 이유를 적어 두지 않으면 반년 뒤에 누군가 "이거 중복 아니냐"며 빼자고 한다. 그때 맞설 근거가 표 안에 있어야 한다.
같은 규칙을 사용자 속성에도 적용한다. 사용자 속성 후보가 아홉 개였는데 실제로 GA4로 보내기로 한 건 가입 방식 하나였다. 로그인 여부는 User-ID를 설정하면 GA4 기본 차원이 이미 답한다. 기기 식별자는 값 종류가 너무 많으니 BigQuery 조인용으로만. 마케팅 동의 여부는 분석 차원이 아니라 서버 액션을 켜고 끄는 제어 신호다. 누적 전환 수는 계속 변하는 값이라 조회 시점에 계산하는 게 맞다. 이유가 전부 다르지. 사용자 속성이 undefined로 찍히는 문제는 대개 이 정리를 안 한 상태에서 값을 넣어 줄 곳 없이 속성만 등록해 생긴다.
이름 컬럼이 두 개인 이유
표를 만들다 보면 컬럼이 하나 더 필요해지는 순간이 온다. 이미 코드에 박혀 돌고 있는 이름과 앞으로 GA4에서 쓰고 싶은 이름이 다를 때.
실제로 그랬지. 사이트에 이미 view_product, click_content, view_category 같은 이름이 깔려 있었는데, GA4 권장 이벤트에는 같은 뜻의 표준 이름이 따로 있었다. 표준 이름을 쓰면 GA4 기본 리포트와 상품 퍼널이 그냥 켜진다. 안 쓰면 전부 맞춤으로 만들어야 하고.
이름을 바꾸려면 프론트엔드를 고치고 배포해야 한다. 그런데 GTM이 중간에 있으면 배포 없이 해결되지. 코드가 쏘는 이름은 그대로 두고, GTM이 GA4로 내보낼 때만 이름을 바꿔 준다.
원본 이벤트명 GA4 출력 이벤트명
-------------------- --------------------
view_product -> view_item
view_category -> view_item_list
click_content -> select_content
click_event_banner -> select_promotion
share_referral -> share
submit_accepted -> qualify_lead
order_canceled -> close_unconvert_lead
코드처럼 보여도 그냥 이름 대응표다. 왼쪽은 브라우저 안에서 실제로 발생하는 이름, 오른쪽은 GA4 리포트에 뜨는 이름. 프론트엔드 배포 없이 세 세대에 걸쳐 쌓인 이름 혼재를 흡수한 것이고, 이건 공짜가 아니다.
대가는 이름 두 개가 세상에 존재한다는 사실 자체다. 개발자가 브라우저 콘솔에서 보는 이름과 마케터가 GA4에서 보는 이름이 다르다. 누군가는 반드시 왼쪽 이름으로 퍼널을 짜려다 리포트에서 그 이벤트를 못 찾는다. 그래서 두 컬럼을 나란히 두고, 어느 쪽이 어느 쪽인지 표 머리에 한 줄 적어 둔다.
같은 자리에 함정이 하나 더 있지. GTM은 이름을 바꾸는 김에 이벤트 하나를 둘로 가를 수도 있다. 상담 신청 하나에 일반 상담과 셀프 가입이 섞여 있으면, 프론트엔드는 한 번만 쏘고 GTM이 유형 값을 보고 상호배타적으로 두 태그 중 하나만 발화시킨다.
이때 프론트엔드가 두 번 쏘면 안 된다. "가르기로 했다"는 말을 들은 개발자가 친절하게 두 번째 이벤트를 추가로 push하면, GTM이 이미 가르고 있으니 전환이 두 배로 잡힌다. 그래서 표의 프론트엔드 작업 칸에 "별도 push 금지, 원본 하나만 유지"를 명시적으로 적는다. 안 적으면 반드시 누가 친절을 베푼다.
전진 옆에 후퇴를 같이 놓는다
전환 이벤트를 설계할 때 거의 모두가 전진만 만든다. 상담 제출, 자격 확정, 개통 완료. 여기서 끝내면 광고 플랫폼이 이상한 걸 학습한다.
전진만 재고 후퇴를 안 재면, 광고는 전환은 되는데 결국 취소되는 리드를 잘 만드는 법을 배운다.
커머스로 치면 구매만 보내고 환불을 안 보내는 상태지. 커머스에서는 이게 상식인데, 리드 기반 비즈니스에서는 후퇴 이벤트가 통째로 빠진 계정을 자주 본다. 취소가 CRM 안에서만 일어나서 그렇지.
후퇴 이벤트는 나중에 붙이는 부록이 아니라, 전진 이벤트를 정의하는 그 자리에서 같이 정하는 짝이다.
전환 단위를 먼저 못박는다
위 도해에서 제일 중요한 건 마지막 칸 색깔이 다르다는 점이다. 상담 신청 하나가 여러 상품을 담을 수 있고, 각 상품이 따로 개통되고 따로 취소된다. 그러면 전환 단위가 중간에 리드에서 아이템으로 바뀐다.
이걸 안 정하면 광고 플랫폼에 보내는 건수와 백엔드 집계 건수가 영구히 안 맞는다. 한쪽은 고객 수를 세고 한쪽은 계약 건수를 세니까. 어느 쪽이 맞느냐가 아니라 어느 쪽으로 정했는지를 적어 두는 게 답이다.
정하고 나면 중복 제거 키가 따라 나온다. 서버에서 전환을 보낼 때 같은 전환이 두 번 도착하는 걸 막는 키다.
# 중복 제거 키는 랜덤이 아니라 결정값이다.
# 같은 사건을 다시 보내면 반드시 같은 키가 나와야 한다.
리드 단위 전환
event_id = evt_{리드번호}
아이템 개통
event_id = activation_{리드번호}_{아이템번호}
아이템 개통 취소
event_id = activation_cancel_{리드번호}_{아이템번호}
리드 자격 제외
event_id = disqualify_{리드번호}_{사유코드}
연결콜
event_id = call_{통화레코드번호}
규칙 하나만 기억하면 된다. 같은 사건을 다시 보내면 같은 키가 나와야 한다. 랜덤 문자열을 쓰면 재전송할 때마다 새 전환이 생긴다. 그래서 정의서에 예시값을 적을 때 evt_ab12cd34처럼 쓰면 안 되고, evt_7처럼 실제 형식 그대로 적어야 한다.
상태 체계가 하나가 아닐 수 있다. 웹 신청서의 상태, CRM 상담의 상태, CRM 개통의 상태가 각각 따로 돌고 값 집합이 서로 겹치지 않는 경우를 봤다. 하나의 상태 필드로 전체 퍼널을 표현하려던 설계가 그래서 깨졌다. 전환 이벤트를 설계하기 전에 각 상태를 누가 기록하는지부터 확인한다. 그리고 문서에 적힌 상태 값 목록을 그대로 믿지 마라. 어느 문서의 예시 상태 일곱 종이 실제 시스템 세 곳 어디에도 없었고, 철자마저 달랐다.
사이트 밖 한 층을 택소노미 안에 넣는다
여기까지는 전부 사이트 안 이야기였지. 그런데 사이트 밖을 재는 추적 링크 편에서 이벤트 두 개가 나왔다. 우리가 운영하는 네이버 블로그나 유튜브 채널처럼 플랫폼은 남의 것이지만 들고 나는 링크는 내가 심을 수 있는 자리에 체크포인트를 박는 이벤트다.
이 둘을 그냥 만들어 붙이면 안 된다. 택소노미 바깥에 두면 컬럼 규칙이 하나도 안 붙고, 반년 뒤엔 아무도 왜 있는지 모른다. 정식으로 표 안에 자리를 준다.
표 안에 넣는다는 건 자리만 주는 게 아니라, 나머지 이벤트와 같은 컬럼 규칙을 적용받는다는 뜻이다.
넣어 보니 컬럼 하나가 새 값을 요구했다. 바로 구현 담당. 프론트엔드도 백엔드도 GTM도 아니고 리다이렉트 서버가 기록 주체다. 46개 이벤트를 정리할 때는 담당 값이 넷이면 충분했는데, 사이트 밖 한 층을 들이자 다섯째가 생긴 것.
| 이벤트 | 파라미터 | 상태 | 의미 |
|---|---|---|---|
owned_media_enter외부 링크로 오운드 미디어에 들어감 | media_type | 필수 | 어느 종류의 오운드 미디어인가 |
content_id | 필수 | 그중 어느 게시물인가 | |
entry_source | 필수 | 이 링크를 어디에 붙여 뒀나 | |
link_id | 제외 | 입구에는 나가는 링크 개념이 없다 | |
owned_media_exit오운드 미디어에서 우리 사이트로 나옴 | media_type | 필수 | 어느 종류의 오운드 미디어인가 |
content_id | 필수 | 그중 어느 게시물에서 나왔나 | |
link_id | 필수 | 그 안의 어느 링크가 눌렸나 | |
entry_source | 제외 | 같은 방문자 번호의 입구 이벤트에서 상속 |
표를 만들며 앞 절의 규칙을 이 두 행에 그대로 적용해 봤다. 출구 이벤트의 유입 출처는 제외다. 같은 방문자 번호가 이미 입구 이벤트에 찍혀 있고, 방문자 번호는 결정적 키니까. 앞의 다섯 갈래 중 5번인데 조인키가 시간창이 아니라 결정적 키라서 안전한 쪽이다.
반면 오운드 미디어 종류는 보낸다. 링크 식별자에서 파생할 수 있을 것 같지만, 링크 식별자와 미디어 종류를 잇는 표는 사람이 손으로 만드는 링크 발급표다. 기계가 보증하는 관계가 아니라서 반년 뒤에 반드시 어긋난다. 조인 상대가 사람이 관리하는 표면 조인으로 미루지 않는다.
중복 제거 키도 나머지와 같은 형식으로 맞춘다. 리다이렉트 서버가 클릭마다 발급하는 번호를 그대로 쓰면 된다.
owned_media_enter event_id = owned_in_{클릭번호}
owned_media_exit event_id = owned_out_{클릭번호}
# 두 이벤트를 한 사람으로 묶는 것은 방문자 번호다.
# 클릭번호는 클릭마다 새로 발급되고, 방문자 번호는 유지된다.
이 두 행은 아직 구현하지 않았다. 표에 자리를 잡고 컬럼을 채워 본 설계 제안이고, 실제로 발화시켜 데이터를 본 게 아니다. 관리 상태 칸에는 백로그라고 적혀 있다. 실제로 붙였을 때 연결률이 얼마나 나오는지는 추적 링크 편에 적어 둔 대로 브라우저 정책에 따라 달라지므로 직접 재 봐야 안다.
링크 이름 규칙 자체가 무너지면 이 표도 같이 무너진다. 링크 발급 컨벤션은 UTM 컨벤션 편에서 따로 다룬다.
표를 다 만든 다음에 무너지는 자리
표가 완성되면 끝난 것 같지만, 실제로 어긋나기 시작하는 건 그다음이다. 검수에서 반복적으로 걸린 자리를 추리면 넷.
첫째, 이름은 맞는데 읽는 변수가 다르다. 정의서와 코드의 파라미터 이름을 전수 대조해 불일치 0건이라는 결과를 받은 적이 있는데, 그게 뒤집혔다. 이름은 전부 맞았고 어떤 파라미터가 읽는 변수가 엉뚱한 것이었다. 인벤토리 대조는 이름만 본 것이다. 각 파라미터가 어떤 변수를 읽는지까지 봐야 대조가 끝난다.
둘째, 키를 생략하면 직전 값이 읽힌다. GTM 데이터 영역은 push 사이에 값이 병합되고 유지된다. 그래서 어떤 이벤트에서 키를 안 보내면 직전 이벤트의 값이 그대로 남아 읽힌다. 오류가 안 나고 그럴듯한 값이 들어온다. 정의서에 "값이 없어도 키는 항상 보낸다"를 못박아야 한다.
셋째, 수집 시점이 현실과 다르다. "영상이 재생되기 시작할 때"라고 적었는데 실제로는 화면에 진입하는 시점이었다. 임베드된 재생기라 재생 시작을 감지할 수가 없었으니까. 이럴 때 답은 둘 중 하나지. 코드를 정의서에 맞추거나, 정의서를 현실에 맞추고 그렇게 바꿨다고 기록하거나. 안 정하고 두면 그 지표를 읽는 사람이 통째로 잘못 읽는다.
넷째, 파생물을 손으로 고친다. 표에서 생성한 GTM 컨테이너나 코드 타입 정의를 화면에서 직접 고치면 다음 재생성에 원복된다. 고치는 자리는 언제나 표다.
넷 다 표를 잘 만든다고 안 생기는 문제고, 그래서 마지막 컬럼이 최종 검수일이다. 언제 실물과 대 봤는지가 안 적혀 있으면 그 행은 문서일 뿐 사실이 아니다.
오늘 표 한 장부터 열어라
이벤트를 새로 정의하든 있는 걸 검수하든 순서는 같다. 아래 다섯을 순서대로 하면 된다.
- 질문부터 쓴다: 지금 답을 못 내고 있는 질문 다섯 개를 적어라. 답이 비율이나 숫자로 나오는 형태인가? 아니면 다시 써라.
- 이벤트마다 질문 한 문장: 기존 이벤트 목록이 있다면 각각 옆에 답하는 질문을 한 문장으로 적어라. 못 쓰는 이벤트가 몇 개인가? 그게 폐기 후보다.
- 화면 근거 대조: 각 이벤트에 대해 "이 화면 이 요소"를 지목하라. 못 지목하면 진입·노출형인지, 서버 전송인지, 아니면 설계가 화면보다 앞선 건지 셋 중 하나로 판정하라.
- 행 구조를 뒤집는다: 파라미터가 셀 안에 나열돼 있으면 이벤트 × 파라미터 1행으로 펼쳐라. 그다음 각 파라미터에 필수·선택·제외를 붙여라.
- 제외마다 이유와 조인키: 제외로 표시한 파라미터 옆에 왜 안 보내는지와 어떻게 되살리는지를 적어라. 조인키가 시간창이면 제외를 취소하고 그냥 보내라.
다섯 중 하나만 고른다면 두 번째지. 질문 한 문장을 못 쓰는 이벤트가 목록의 절반이면, 그 택소노미는 아직 시작 전이다.
이벤트 목록의 길이는 성숙도가 아니다. 폐기할 수 있는 능력이 성숙도다.
이 글은 디지털 마케팅 분석 입문 시리즈의 심화편. 전체 지도는 측정 설계를 다섯 층으로 진단하는 글에 있고, 이벤트라는 단위 자체가 낯설다면 쿠키·세션·이벤트 기초부터 보는 게 낫다. 사이트 밖 이야기는 추적 링크와 MMP 편과 오프페이지 노출 측정법으로 이어지고, 링크 이름 규칙은 UTM 컨벤션 편에 있다.
근거·출처
- 이벤트당 파라미터 25개, 사용자 속성 25개, 파라미터 값 100자, 이벤트명 40자: Google Analytics 고객센터, Event collection limits
- 맞춤 측정기준 한도(이벤트 50·사용자 25·아이템 10, 360은 125·100·25)와 삭제 후 48시간 대기: Google Analytics 고객센터, About custom dimensions and metrics
- 질문에서 시작하는 순서, 핵심 이벤트 소수로 좁히기, 트래킹 플랜 표준 컬럼: Amplitude, How to Create a Tracking Plan
- 이벤트 이름 짓기의 Object-Action 프레임워크와 일관성 원칙: Segment(Twilio), Naming conventions for clean data
- GA4 권장 이벤트 이름과 상품 퍼널 연동 이벤트: Google Analytics 고객센터, Recommended events
이 글의 표 구조·컬럼 설계·제외 판단은 실제로 운영하고 검수한 이벤트 46개짜리 표에서 나왔다. 다만 사례에 나오는 서비스·상품·식별자·금액은 전부 일반화했고, 이전 가능한 것은 값이 아니라 컬럼 구조와 판단 규칙이다. GA4 한도 수치는 직접 부딪혀 본 게 아니라 구글 공식 문서에서 확인한 값이며, 정책은 바뀔 수 있으니 도입 시점에 원문을 다시 확인하는 게 맞다. 마지막 절의 오운드 미디어 이벤트 두 개는 표에 자리를 잡아 본 설계 제안이고 아직 구현하지 않았다. 조인 손실률·연결률 같은 비율은 측정한 값이 아니라서 숫자로 적지 않았다.
이 글이 도움이 되었다면 공유해주세요
최신 인사이트
카카오톡 공유 썸네일 안 나올 때 해결법 (Kakao JavaScript SDK 2025)
카카오톡 공유하기에서 썸네일 이미지가 안 나오는 원인과 scrapImage로 KAGE URL을 변환해 해결하는 방법을 단계별로 설명합니다. 지금 확인하세요.
Claude Code 서브에이전트로 CRM 사용자 설명서 20분 만에 완성하는 방법
Claude Code 서브에이전트를 활용해 CRM 코드베이스에서 사용자 설명서와 비주얼 가이드북을 20분 만에 자동 생성한 실전 사례를 공유합니다. 지금 확인하세요.
GEO 생성형 엔진 최적화: 2025년 AI 마케팅 전략 완전 가이드
GEO 생성형 엔진 최적화란 무엇이며 기존 SEO와 어떻게 다른지, 2025년 AI 마케팅 전략의 핵심 실행 방법 5가지를 데이터와 함께 알아보세요.
관련 프로젝트
새 글을 이메일로 받아보세요
마케팅, 분석, 개발 인사이트를 정리해서 보내드려요.

