전자상거래 이벤트를 이해하기 위한 프로그래밍 지식
GA4 전자상거래 이벤트 코드에는 일반 맞춤 이벤트와 다른 한 가지가 있습니다 — items라는 매개변수의 ‘대괄호 [ ]’ 안에 또 다른 정보 묶음이 들어가는 구조입니다. 결국엔 데이터를 효과적으로 저장하고 전송하기 위해서 이런 형태가 나오는데, 이 형태를 비개발자도 이해하고 있어야 비로소 전자상거래가 ‘읽힙니다.’ 마케터가 직접 코드를 짤 일은 거의 없지만, 추적 누락을 짚어 내거나 개발자와 매개변수 누락 같은 대화를 매끄럽게 하려면 ‘데이터가 이런 식으로 저장되고 있다’는 감이 필요합니다. 이 글은 그 감을 만드는 최소한의 프로그래밍 지식을 정리합니다.
① 왜 새로운 형태로 데이터를 저장할까?
한 사람이 한 번의 결제에서 상품을 1개 사면 코드는 비교적 단순합니다. transaction_id(거래 ID)·value(총 금액)·currency(통화) 같은 거래 정보가 한 번씩 있고, 산 상품 1개의 정보(item_id·item_name·price·quantity…)가 한 번 들어가면 끝입니다.
그런데 같은 결제에서 ‘원피스 1개 + 청바지 2개’를 함께 산다면? 거래 자체의 정보는 한 번씩만 있어도 충분하지만, 상품 정보는 두 번 들어가야 합니다. 한 사람이 한 결제에 담을 수 있는 상품 수는 1개일 수도 100개일 수도 있으므로, 코드는 ‘상품 정보를 반복해서 담을 수 있는 구조’를 가져야 합니다.
items 배열 안의 객체가 100개가 됩니다.이 모양 — 매개변수 값의 자리에 ‘대괄호로 감싼 배열’이 들어가고, 그 배열 안에 ‘중괄호로 감싼 객체’가 콤마로 이어 붙는 모습 — 이 GA4 전자상거래의 핵심 형태입니다. 거래에 담긴 상품 수가 1개·2개·N개로 달라지더라도, 거래 자체의 속성(거래 ID·총 금액·통화)은 한 번씩만 적고 상품 정보를 반복해서 채워 넣을 수 있어 효율적입니다.
마케터에게는 낯선 모양이지만, 이걸 이해하고 있어야 비로소 전자상거래를 ‘읽을’ 수 있게 됩니다. 그래서 다음 절부터 ‘변수·배열·객체’ 세 가지 데이터 타입을 차례로 살펴봅니다.
② JavaScript의 세 가지 데이터 타입 — 변수·배열·객체
마케터가 알아야 할 단 세 가지가 있습니다 — 변수(variable)·배열(array)·객체(object). 각각이 어떻게 다른지, 콘솔에서 실행한 결과와 함께 봅니다. 한번에 모든 것을 이해하려 하지 말고, 한 단계씩 ‘아, 이런 모양이구나’ 하고 따라오면 충분합니다.
콘솔이란 — ‘브라우저가 코드를 실행해 보여 주는 창’
웹 브라우저(Chrome·Safari 등) 안에는 ‘개발자 도구’라는 보조 창이 있고, 그 안에 ‘콘솔(Console)’이라는 탭이 있습니다. 개발자가 코드를 한 줄씩 적어 ‘이런 코드를 실행하면 어떤 값이 나오는가’를 즉시 확인하는 작업 공간입니다. 마케터가 만질 일은 거의 없습니다 — 아래 화면들은 ‘개발자가 본 결과를 그대로 옮긴 것’ 정도로 받아들이시면 됩니다.
이제 콘솔에서 ‘숫자’를 다루는 가장 기본 동작부터 봅시다.
기본 — 숫자와 문자열의 ‘+’는 의미가 다르다
콘솔에 1+1이라고 적으면 ‘덧셈’이 일어나 2가 나옵니다.
> 1+1< 2
그런데 같은 ‘+’도 따옴표로 감싼 문자열끼리는 ‘이어 붙이기’의 의미가 됩니다 — 1과 1을 더한 게 아니라, ‘1’ 옆에 ‘1’을 붙였습니다.
> '1'+'1'< '11'
한국어에도 똑같이 적용됩니다. 두 문자열을 ‘+’로 이으면 한 문자열이 됩니다.
> '유성민'+'입니다.'< '유성민입니다.'
왜 이걸 짚느냐 — 매개변수 값이 ‘숫자(Number)’냐 ‘문자열(String)’이냐에 따라 코드의 동작이 달라지기 때문입니다. price: 7000은 숫자라서 다른 가격과 더해 매출을 구할 수 있고, item_name: "허들러스 원피스"는 문자열이라서 다른 문자열과 이어 붙여 ‘분류 라벨’을 만들 수도 있습니다. 데이터 타입의 차이를 한 번만 짚어 두면 됩니다.
변수(variable) — 이름이 붙은 값
지금까지는 ‘1과 1을 더하면 무엇이 나오나’처럼 코드가 끝나면 결과가 사라졌습니다. 그런데 그 결과를 ‘이름’에 담아 두고 나중에 부를 수 있으면 훨씬 유용하겠죠. 그게 ‘변수’의 개념입니다.
var라는 키워드로 어떤 ‘이름’에 값을 담아 둘 수 있습니다. 이 ‘이름 + 값’의 한 쌍을 변수라고 부릅니다.
> vara=1;< undefined// 선언만 했기 때문에 돌려 줄 값 없음
이제 ‘a’라는 이름에 ‘1’이 담겨 있습니다. 다음에 그 이름을 부르면 담아 둔 값이 돌아옵니다.
> a;< 1// 이름 'a'를 부르면 그 안에 담아 둔 값 1이 돌아옴
여기서 ‘이름(a)’이 곧 KEY, ‘담긴 값(1)’이 곧 VALUE입니다. 이벤트 매개변수가 price: 7000 형태로 적히는 것도 같은 원리 — price가 KEY, 7000이 VALUE.
배열(array) — 여러 값을 ‘순서대로’ 담은 묶음
이름 하나에 값 하나를 담는 게 ‘변수’라면, ‘여러 값을 한 이름 안에 담아 둘 수’도 있어야 할 때가 있습니다. 예를 들어 ‘과일 목록’을 한 이름에 담아 두고 싶을 때.
대괄호 [ ]로 감싸 여러 값을 ‘순서대로’ 담은 것이 배열입니다.
> vara= ["apple","banana","orange"];< undefined
이름 ‘a’ 안에 사과·바나나·오렌지 세 값이 ‘순서대로’ 담겼습니다. 다시 a를 부르면 그 안에 들어 있는 값들이 펼쳐져 보입니다 — 길이 3, 그리고 각 자리에 0·1·2번 ‘순번(index)’이 붙어 있습니다.
> a;< (3) ['apple','banana','orange']0:"apple"1:"banana"2:"orange" length:3
특정 자리의 값을 꺼내려면 ‘이름[순번]’ 형태로 부릅니다. 0부터 시작한다는 점만 기억하면 됩니다.
> a[0]< 'apple'// 첫 번째(0번 자리) 값
이 ‘배열’ 개념이 곧 GA4 전자상거래의 items가 가진 모양입니다 — 한 거래에 담긴 ‘상품 N개’를 순서대로 담는 그릇.
객체(object) — 이름이 붙은 값 여러 개를 한 묶음으로
이제 한 단계 더 — 한 ‘대상’에 대해 여러 속성(색·가격·무게…)을 ‘이름’과 함께 묶어 두고 싶을 때가 있습니다. 그게 ‘객체’입니다.
중괄호 { }로 감싸, 이름(KEY)과 값(VALUE)의 쌍을 여러 개 묶은 것이 객체입니다.
> varapple= {color:"red",price:2000,weight:"500g" }< undefined
‘apple’이라는 이름에 ‘색=red, 가격=2000, 무게=500g’ 세 KEY-VALUE가 한 묶음으로 담겼습니다. 점(.)으로 KEY를 지정해 그 값만 꺼낼 수 있습니다.
> apple.color;< 'red'// 'apple' 객체의 'color' KEY 값
그리고 이 ‘apple 객체’를 GA4 전자상거래의 화법으로 옮기면 자연스럽게 ‘이건 사과야! 색은 red, 가격은 2,000원, 무게는 500g이야’가 됩니다 — 한 EVENT와 그 PROPERTY들이 모인 모양.
실제로 ‘장바구니 담기’ 이벤트를 같은 방식으로 풀어 보면 — add_to_cart의 매개변수 한 묶음도 동일한 구조입니다.
> varaddtocart= {currency:"KRW",price:7000 }< undefined
add_to_cart’ 이벤트도 같은 방식 — 자연어로 풀면 ‘이건 장바구니 담기야! 통화는 KRW, 가격은 7,000원이야’. 객체({ })가 곧 이 모양을 코드로 옮긴 것입니다.여기까지 — 변수·배열·객체 세 가지를 알았습니다. 이걸 무기로, 이제 purchase 이벤트 코드를 한 줄 한 줄 해부해 봅시다.
③ 전자상거래 코드 한 줄 한 줄 분해
지금까지의 데이터 타입을 가지고 purchase 이벤트 코드의 각 줄에 이름을 붙여 봅시다. 같은 코드 안에 이벤트 이름·일반 변수·배열 타입의 변수·객체 타입의 변수·KEY 다섯 가지가 모두 등장합니다.
차근차근 짚어 보면:
- 이벤트 이름 —
gtag("event", "purchase", { ... })의 두 번째 자리 ‘purchase’가 이벤트의 이름입니다. - 이벤트 수준 변수 —
transaction_id·value·currency세 줄은 ‘이 거래 한 건’ 전체에 한 번씩 따라붙는 정보. 거래 ID·총 금액·통화는 거래마다 하나씩만 있으면 됩니다. - 배열 타입의 변수(
items) — Key 자리(items) 뒤에 일반 값이 아니라 대괄호[ ]가 옵니다. 한 거래에 상품이 여러 개 담길 수 있어서, 그 묶음을 ‘반복 가능한 그릇’인 배열로 받습니다. - 객체 타입의 변수 — 배열 안에 들어 있는 각
{ }묶음 하나하나가 ‘상품 한 개’에 대한 객체. 위 코드에는 객체가 2개 들어 있어 ‘상품 2개가 담긴 거래’가 됩니다. - KEY — 각 객체 안의
item_id: "SKU_12345"·item_name: "허들러스 원피스"처럼 ‘이름:값’ 한 쌍이 줄줄이 들어 있는데, ‘:’ 왼쪽의item_id·item_name이 KEY, 오른쪽의"SKU_12345"·"허들러스 원피스"가 VALUE입니다.
이 다섯 가지를 한꺼번에 외우려고 하지 말고, ‘items만 다른 매개변수와 달리 배열이고, 그 안에 객체가 들어간다’ 정도만 기억해 두면 충분합니다. 매개변수가 ‘일반 값(문자열·숫자) 자리’이냐 ‘배열 자리’이냐의 차이가 GA4 전자상거래 코드의 가장 큰 특징입니다.
④ 이벤트 수준의 변수 vs 아이템 수준의 변수
같은 purchase 이벤트 안의 매개변수는 두 가지 ‘수준(level)’으로 나뉩니다. 어디에 들어가야 하는지 자리가 정해져 있어, 자리를 헷갈리면 GA4 리포트도 어긋납니다.
두 수준은 어떤 정보가 어디에 들어가야 하는지 자리가 다릅니다. ‘거래 한 건’에 관한 정보냐, ‘상품 한 개’에 관한 정보냐로 갈립니다.
이벤트 수준 (Event-Level)
이 이벤트 한 건 전체에 한 번씩 따라붙는 정보. 거래·결제 그 자체의 속성을 담습니다. 상품 수가 1개든 100개든 한 번씩만 있으면 됩니다.
아이템 수준 (Item-Level)
items 배열 안의 각 상품 객체에 따라붙는 정보. 한 거래에 상품이 N개면 N번 반복됩니다. 상품 한 개의 속성을 담습니다.
coupon처럼 두 수준 모두에 등장하는 항목도 있습니다 — 자리가 다르면 의미가 다릅니다. 주문 전체에 적용된 쿠폰(예: 3만원 이상 구매 시 3,000원 할인)은 이벤트 수준의 coupon(주문 쿠폰)으로, 특정 상품에만 적용된 쿠폰(예: 청바지 단독 10% 할인)은 아이템 수준의 coupon(상품 쿠폰)으로 보냅니다.
이 두 수준의 구분은 GA4 리포트로 그대로 이어집니다. ‘구매 수익·거래 수’ 같은 측정항목은 이벤트 수준에서 나오고, ‘상품 수익·조회된 상품·구매한 상품’ 같은 측정항목은 아이템 수준에서 나옵니다.
⑤ Items 객체 데이터는 GA4에서 어떻게 보이나
아이템 수준의 변수가 GA4 리포트에 어떻게 펼쳐지는지 보면, ‘왜 이런 구조가 필요한가’가 분명해집니다. 수익 창출 → 전자상거래 구매 리포트에서 측정기준을 ‘항목 이름’으로 두면 — 각 상품마다 조회된 상품·장바구니에 추가된 상품·구매한 상품·상품 수익이 한 줄씩 정리됩니다.
| 항목 이름 | 조회된 상품 | 장바구니에 추가된 상품 | 구매한 상품 | 상품 수익 |
|---|---|---|---|---|
| Super G Timbuk2 Recycled Backpack | 3,062 | 224 | 38 | $4,100.00 |
| Google Campus Bike | 1,642 | 125 | 18 | $836.00 |
| Chrome Dino Recycled Backpack | 1,062 | 61 | 7 | $330.60 |
| Google Yosemite Windbreaker | 879 | 233 | 37 | $1,915.20 |
| Google Black Eco Zip Hoodie | 832 | 94 | 17 | $979.80 |
이 표가 매끄럽게 채워지려면 두 가지가 필요합니다.
- ①
view_item·add_to_cart·purchase이벤트가 발생할 때마다items배열 안에 그 상품의 정보가 같이 들어가야 합니다.view_item만 보내고items를 빠뜨리면 ‘조회된 상품’이 0으로 나옵니다. - ② 같은 상품의
items정보가 모든 이벤트에서 똑같이 들어와야 합니다. 같은 ‘청바지’의item_name이view_item에서는 ‘청바지’,purchase에서는 ‘청 바지(띄어쓰기 있음)’로 다르게 들어오면 두 줄로 분리됩니다.
①은 ‘전송 누락’의 문제, ②는 ‘데이터 정합성’의 문제 — 둘 다 GA4 리포트의 정확도에 직접 영향을 줍니다. ②가 ‘Items 일치 원칙’이고, 다음 절의 주제입니다.
⑥ Items 객체 데이터를 각 이벤트마다 똑같이 일치시켜야 한다
가장 중요한 원칙입니다 — 같은 상품의 items 안 정보(특히 item_id·item_name)는 view_item·add_to_cart·purchase 어느 이벤트에서 보내든 완전히 같은 값이어야 합니다.
왜 그런가 — GA4는 ‘같은 상품인가, 다른 상품인가’를 item_id·item_name 같은 식별 매개변수의 ‘문자 그대로의 일치’로 판단합니다. 사람 눈에는 같아 보여도 띄어쓰기 한 칸·맞춤법 한 글자가 다르면 GA4는 다른 상품으로 인식해 별도 줄로 집계합니다.
| 변수 | view_item | add_to_cart | purchase |
|---|---|---|---|
item_name | 청바지 | 청바지 | 청바지 |
| 항목 이름 | 조회 | 장바구니 | 구매 |
|---|---|---|---|
| 청바지 | 1 | 1 | 1 |
| 변수 | view_item | add_to_cart | purchase |
|---|---|---|---|
item_name | 청바지 | 청바지 | 원피스 |
| 항목 이름 | 조회 | 장바구니 | 구매 |
|---|---|---|---|
| 청바지 | 1 | 1 | 0 |
| 원피스 | 0 | 0 | 1 |
이름이 ‘다르게’ 들어간 경우뿐 아니라, 띄어쓰기·표기 차이만으로도 같은 일이 벌어집니다. ‘청바지’와 ‘청 바지’는 사람 눈엔 같지만 GA4는 다른 상품으로 인식해 두 줄로 흩어집니다.
| 변수 | view_item | add_to_cart | purchase |
|---|---|---|---|
item_name | 청바지 | 청바지 | 청 바지 |
| 항목 이름 | 조회 | 장바구니 | 구매 |
|---|---|---|---|
| 청바지 | 1 | 1 | 0 |
| 청 바지 | 0 | 0 | 1 |
이런 분리가 분석에 어떤 의미인지 — 깔때기가 무너집니다. ‘청바지를 조회한 사람 중 몇 %가 장바구니에 담고 몇 %가 구매했는가?’ 같은 가장 기본적인 분석이 안 됩니다. 한 상품을 두 줄로 나눠 봤기 때문이죠. 영향력이 작아 보여도, 여러 상품이 동시에 이런 문제를 가지면 리포트 신뢰도가 통째로 흔들립니다.
운영 관점에서 한 가지 실전 팁 — item_id는 ‘변하지 않는 SKU·상품 코드’로 두는 것이 가장 안전합니다. item_name은 시즌·마케팅 이슈로 바뀌기 쉽지만, item_id가 고정되어 있으면 ‘항목 ID’ 측정기준으로 같은 상품의 시즌 간 추이를 한 줄로 묶어 볼 수 있습니다.
자주 묻는 질문
코드를 모르는데 콘솔을 꼭 봐야 하나요?
아니요 — 만질 일은 거의 없습니다. 다만 ‘데이터가 이런 식으로 저장돼서 GA4로 보내진다’는 직관을 잡아 두면, 추적 누락을 짚어 내거나 개발자와 ‘이 매개변수가 비어 있는데요’ 같은 대화를 할 때 의사소통이 훨씬 매끄러워집니다. 본문 화면들을 ‘이런 모양이구나’ 정도로 한 번 훑어 두면 충분합니다.
왜 items만 배열이고 나머지(transaction_id 등)는 일반 변수인가요?
‘한 거래’는 하나뿐이라 transaction_id·value·currency는 값이 하나씩만 있으면 됩니다. 하지만 한 거래에 담긴 ‘상품’은 1개일 수도, 10개일 수도, 100개일 수도 있으므로 반복 가능한 구조가 필요합니다. 그래서 items만 배열 형태입니다 — N개의 상품을 한 거래에 담을 수 있도록.
‘이벤트 수준’과 ‘아이템 수준’ — 분석에선 어떻게 다른가요?
이벤트 수준 변수는 ‘거래당’ 분석에 쓰입니다 — 거래 건수, 평균 객단가(value의 평균), 통화별 합계 등. 아이템 수준 변수는 ‘상품당’ 분석에 쓰입니다 — 상품 이름·카테고리·브랜드별 조회·장바구니·구매 추이. 두 수준이 별개라서 GA4 리포트도 ‘구매 수익·거래 수’ 같은 이벤트 수준 측정항목과 ‘조회된 상품·구매한 상품’ 같은 아이템 수준 측정항목이 따로 있습니다.
상품 이름이 시즌마다 바뀌면 어떻게 하나요?
item_id를 ‘변하지 않는 SKU 또는 상품 코드’로 두는 것이 안전합니다. item_name은 이름이 바뀌면 GA4 리포트에서 다른 줄로 분리되지만, item_id가 고정되어 있으면 ‘항목 ID’ 측정기준으로는 한 상품으로 묶어 볼 수 있습니다(자세한 건 ‘전자상거래 리포트 100% 이해하기’).
한 거래에 상품이 100개면 items가 100개 들어가나요?
네 — 거래에 담긴 상품 수만큼 items 배열의 길이가 늘어납니다. GA4는 한 이벤트의 items 배열을 약 200개 상품까지 안전하게 처리합니다. 일반 쇼핑몰에서는 거의 닿을 일이 없는 한도입니다.
coupon이 이벤트 수준에도, 아이템 수준에도 있을 수 있다고요?
네 — 자리가 다르면 의미가 다릅니다. 주문 전체에 적용된 쿠폰(예: 5만원 이상 구매 시 3,000원 할인)은 이벤트 수준의 coupon(주문 쿠폰)으로, 특정 상품에만 적용된 쿠폰(예: 청바지 단독 10% 할인)은 아이템 수준의 coupon(상품 쿠폰)으로 보냅니다. 같은 이름의 매개변수지만 자리가 다르므로 GA4 리포트에서도 따로 집계됩니다.
‘0부터 시작’이라는 배열 순번은 왜 그런가요?
JavaScript를 포함한 대부분의 프로그래밍 언어가 배열의 첫 자리를 ‘0번’으로 매깁니다. 1부터가 직관적으로 느껴지지만, 0부터인 게 표준이라 익숙해지면 됩니다. GA4 items 배열의 index 매개변수도 같은 규칙 — 첫 번째 상품이 index: 0, 두 번째가 index: 1.
