전자상거래 이벤트를 이해하기 위한 프로그래밍 지식

GA4 전자상거래 이벤트 코드에는 일반 맞춤 이벤트와 다른 한 가지가 있습니다 — items라는 매개변수의 ‘대괄호 [ ] 안에 또 다른 정보 묶음이 들어가는 구조입니다. 결국엔 데이터를 효과적으로 저장하고 전송하기 위해서 이런 형태가 나오는데, 이 형태를 비개발자도 이해하고 있어야 비로소 전자상거래가 ‘읽힙니다.’ 마케터가 직접 코드를 짤 일은 거의 없지만, 추적 누락을 짚어 내거나 개발자와 매개변수 누락 같은 대화를 매끄럽게 하려면 ‘데이터가 이런 식으로 저장되고 있다’는 감이 필요합니다. 이 글은 그 감을 만드는 최소한의 프로그래밍 지식을 정리합니다.

① 왜 새로운 형태로 데이터를 저장할까?

한 사람이 한 번의 결제에서 상품을 1개 사면 코드는 비교적 단순합니다. transaction_id(거래 ID)·value(총 금액)·currency(통화) 같은 거래 정보가 한 번씩 있고, 산 상품 1개의 정보(item_id·item_name·price·quantity…)가 한 번 들어가면 끝입니다.

그런데 같은 결제에서 ‘원피스 1개 + 청바지 2개’를 함께 산다면? 거래 자체의 정보는 한 번씩만 있어도 충분하지만, 상품 정보는 두 번 들어가야 합니다. 한 사람이 한 결제에 담을 수 있는 상품 수는 1개일 수도 100개일 수도 있으므로, 코드는 ‘상품 정보를 반복해서 담을 수 있는 구조’를 가져야 합니다.

상품 1개 구매 시거래 정보transaction_id: "...12345678"value: 7,000currency: "KRW"items: [ ... ]← 배열의 길이 = 1{ 상품 객체 1개 }item_id: "SKU_12345"item_name: "허들러스 원피스"coupon: "10% 할인 쿠폰"discount: 700index: 0price: 7,000quantity: 1상품 2개 구매 시거래 정보 (한 번만)transaction_id: "...12345678"value: 24,300← 두 상품 합currency: "KRW"items: [ ..., ... ]← 길이 = 2{ 상품 객체 — 원피스 }item_id: "SKU_12345"item_name: "허들러스 원피스"price: 7,000, quantity: 1{ 상품 객체 — 청바지 }item_id: "SKU_12346"item_name: "허들러스 청바지"price: 10,000, quantity: 2
상품이 1개일 때와 2개일 때 — ‘거래 정보’는 한 번씩만, ‘상품 정보’는 상품 개수만큼 반복. 100개 상품을 한 번에 사면 items 배열 안의 객체가 100개가 됩니다.

이 모양 — 매개변수 값의 자리에 ‘대괄호로 감싼 배열’이 들어가고, 그 배열 안에 ‘중괄호로 감싼 객체’가 콤마로 이어 붙는 모습 — 이 GA4 전자상거래의 핵심 형태입니다. 거래에 담긴 상품 수가 1개·2개·N개로 달라지더라도, 거래 자체의 속성(거래 ID·총 금액·통화)은 한 번씩만 적고 상품 정보를 반복해서 채워 넣을 수 있어 효율적입니다.

마케터에게는 낯선 모양이지만, 이걸 이해하고 있어야 비로소 전자상거래를 ‘읽을’ 수 있게 됩니다. 그래서 다음 절부터 ‘변수·배열·객체’ 세 가지 데이터 타입을 차례로 살펴봅니다.

② JavaScript의 세 가지 데이터 타입 — 변수·배열·객체

마케터가 알아야 할 단 세 가지가 있습니다 — 변수(variable)·배열(array)·객체(object). 각각이 어떻게 다른지, 콘솔에서 실행한 결과와 함께 봅니다. 한번에 모든 것을 이해하려 하지 말고, 한 단계씩 ‘아, 이런 모양이구나’ 하고 따라오면 충분합니다.

콘솔이란 — ‘브라우저가 코드를 실행해 보여 주는 창’

웹 브라우저(Chrome·Safari 등) 안에는 ‘개발자 도구’라는 보조 창이 있고, 그 안에 ‘콘솔(Console)’이라는 탭이 있습니다. 개발자가 코드를 한 줄씩 적어 ‘이런 코드를 실행하면 어떤 값이 나오는가’를 즉시 확인하는 작업 공간입니다. 마케터가 만질 일은 거의 없습니다 — 아래 화면들은 ‘개발자가 본 결과를 그대로 옮긴 것’ 정도로 받아들이시면 됩니다.

새 탭에서 열기새로 고침다른 이름으로 저장…페이지 소스 보기검사ElementsConsoleSourcesNetworkPerformance>'개발자가 여기에 코드를 한 줄씩 적습니다.'<결과가 바로 아래 줄에 출력됩니다.| (커서 깜빡임)
Chrome에서 빈 곳에 우클릭 → ‘검사’를 누르면 개발자 도구가 열리고, ‘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들이 모인 모양.

이건 사과야!색은 red야가격은 2,000원이야무게는 500g이야EVENTPROPERTY
‘apple’ 객체를 자연어로 풀면 ‘이건 사과야! 색은 red, 가격은 2,000원, 무게는 500g이야’ — 한 EVENT와 그 PROPERTY들이 모인 모양. GA4 전자상거래의 한 상품 객체가 갖는 모양도 정확히 이와 같습니다.

실제로 ‘장바구니 담기’ 이벤트를 같은 방식으로 풀어 보면 — add_to_cart의 매개변수 한 묶음도 동일한 구조입니다.

> varaddtocart= {currency:"KRW",price:7000  }< undefined
이건 장바구니 담기야!통화는 KRW야가격은 7,000원이야EVENTPROPERTY
add_to_cart’ 이벤트도 같은 방식 — 자연어로 풀면 ‘이건 장바구니 담기야! 통화는 KRW, 가격은 7,000원이야’. 객체({ })가 곧 이 모양을 코드로 옮긴 것입니다.

여기까지 — 변수·배열·객체 세 가지를 알았습니다. 이걸 무기로, 이제 purchase 이벤트 코드를 한 줄 한 줄 해부해 봅시다.

③ 전자상거래 코드 한 줄 한 줄 분해

지금까지의 데이터 타입을 가지고 purchase 이벤트 코드의 각 줄에 이름을 붙여 봅시다. 같은 코드 안에 이벤트 이름·일반 변수·배열 타입의 변수·객체 타입의 변수·KEY 다섯 가지가 모두 등장합니다.

gtag("event","purchase", {transaction_id:"...12345678",value:24300,currency:"KRW"items: [{item_id:"SKU_12345",item_name:"허들러스 원피스",price:7000,quantity:1},{item_id:"SKU_12346",item_name:"허들러스 청바지",price:10000,quantity:2}]});이벤트 이름이벤트 수준 변수배열 타입의 변수객체 타입의 변수 (1)객체 타입의 변수 (2)KEY‘items 배열의 길이 = 2’ → 이 거래에 상품 2개가 담겼다는 의미.거래 정보(transaction_id·value·currency)는 거래당 한 번, 상품 정보(items 안 각 객체)는 상품당 한 번씩 반복됩니다.한 코드 안에 ‘이벤트 이름·이벤트 수준 변수·배열·객체·KEY’ 다섯 가지가 모두 등장합니다.
한 코드를 세 그룹으로 묶어 봤습니다 — 이벤트 수준(이벤트 이름·이벤트 수준 변수·배열 타입의 변수), 객체 타입의 변수, 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 리포트도 어긋납니다.

gtag("event","purchase", {transaction_id:"...12345678",value:24300,currency:"KRW"items: [{item_id:"SKU_12345",item_name:"허들러스 원피스",price:7000, quantity:1},{item_id:"SKU_12346",item_name:"허들러스 청바지",price:10000, quantity:2}]});이벤트 수준 변수 (Event-Level)아이템 수준 변수 (Item-Level)굵은 테두리 박스 = 거래 한 건에 한 번씩 따라붙는 정보(이벤트 수준).회색 박스 = items 배열 안 각 상품 객체의 정보(아이템 수준). 상품 N개면 N번 반복.‘쿠폰(coupon)’ 같은 매개변수는 두 수준 모두에 등장할 수 있고, 자리가 다르면 의미가 다릅니다.
굵은 테두리 박스 = 이벤트 수준(거래 자체의 정보). 회색 박스 = 아이템 수준(상품 한 개의 정보). 거래에 상품 N개가 담기면 아이템 수준 변수는 N번 반복됩니다.

두 수준은 어떤 정보가 어디에 들어가야 하는지 자리가 다릅니다. ‘거래 한 건’에 관한 정보냐, ‘상품 한 개’에 관한 정보냐로 갈립니다.

이벤트 수준 (Event-Level)

이 이벤트 한 건 전체에 한 번씩 따라붙는 정보. 거래·결제 그 자체의 속성을 담습니다. 상품 수가 1개든 100개든 한 번씩만 있으면 됩니다.

transaction_id : 거래 ID value : 총 결제 금액 currency : 통화 (KRW · USD) coupon : 주문 전체 쿠폰 shipping : 배송비 tax : 세액

아이템 수준 (Item-Level)

items 배열 안의 각 상품 객체에 따라붙는 정보. 한 거래에 상품이 N개면 N번 반복됩니다. 상품 한 개의 속성을 담습니다.

item_id : 상품 ID(SKU) item_name : 상품 이름 item_brand : 상품 브랜드 item_category: 상품 카테고리 price : 상품 단가 quantity : 상품 수량 discount : 상품 할인액 coupon : 상품별 쿠폰

coupon처럼 두 수준 모두에 등장하는 항목도 있습니다 — 자리가 다르면 의미가 다릅니다. 주문 전체에 적용된 쿠폰(예: 3만원 이상 구매 시 3,000원 할인)은 이벤트 수준의 coupon(주문 쿠폰)으로, 특정 상품에만 적용된 쿠폰(예: 청바지 단독 10% 할인)은 아이템 수준의 coupon(상품 쿠폰)으로 보냅니다.

이 두 수준의 구분은 GA4 리포트로 그대로 이어집니다. ‘구매 수익·거래 수’ 같은 측정항목은 이벤트 수준에서 나오고, ‘상품 수익·조회된 상품·구매한 상품’ 같은 측정항목은 아이템 수준에서 나옵니다.

⑤ Items 객체 데이터는 GA4에서 어떻게 보이나

아이템 수준의 변수가 GA4 리포트에 어떻게 펼쳐지는지 보면, ‘왜 이런 구조가 필요한가’가 분명해집니다. 수익 창출전자상거래 구매 리포트에서 측정기준을 ‘항목 이름’으로 두면 — 각 상품마다 조회된 상품·장바구니에 추가된 상품·구매한 상품·상품 수익이 한 줄씩 정리됩니다.

항목 이름조회된 상품장바구니에 추가된 상품구매한 상품상품 수익
Super G Timbuk2 Recycled Backpack3,06222438$4,100.00
Google Campus Bike1,64212518$836.00
Chrome Dino Recycled Backpack1,062617$330.60
Google Yosemite Windbreaker87923337$1,915.20
Google Black Eco Zip Hoodie8329417$979.80
‘항목 이름’ 측정기준으로 본 전자상거래 구매 리포트. 첫 열(강조)이 측정기준이고, 그 옆 숫자 열들이 측정항목.

이 표가 매끄럽게 채워지려면 두 가지가 필요합니다.

  • view_item·add_to_cart·purchase 이벤트가 발생할 때마다 items 배열 안에 그 상품의 정보가 같이 들어가야 합니다. view_item만 보내고 items를 빠뜨리면 ‘조회된 상품’이 0으로 나옵니다.
  • 같은 상품의 items 정보가 모든 이벤트에서 똑같이 들어와야 합니다. 같은 ‘청바지’의 item_nameview_item에서는 ‘청바지’, purchase에서는 ‘청 바지(띄어쓰기 있음)’로 다르게 들어오면 두 줄로 분리됩니다.

①은 ‘전송 누락’의 문제, ②는 ‘데이터 정합성’의 문제 — 둘 다 GA4 리포트의 정확도에 직접 영향을 줍니다. ②가 ‘Items 일치 원칙’이고, 다음 절의 주제입니다.

⑥ Items 객체 데이터를 각 이벤트마다 똑같이 일치시켜야 한다

가장 중요한 원칙입니다 — 같은 상품의 items 안 정보(특히 item_id·item_name)는 view_item·add_to_cart·purchase 어느 이벤트에서 보내든 완전히 같은 값이어야 합니다.

왜 그런가 — GA4는 ‘같은 상품인가, 다른 상품인가’를 item_id·item_name 같은 식별 매개변수의 ‘문자 그대로의 일치’로 판단합니다. 사람 눈에는 같아 보여도 띄어쓰기 한 칸·맞춤법 한 글자가 다르면 GA4는 다른 상품으로 인식해 별도 줄로 집계합니다.

✓ 권장 — 세 이벤트가 같은 값
변수view_itemadd_to_cartpurchase
item_name청바지청바지청바지
항목 이름조회장바구니구매
청바지111
✗ 피함 — 이름이 다름
변수view_itemadd_to_cartpurchase
item_name청바지청바지원피스
항목 이름조회장바구니구매
청바지110
원피스001

이름이 ‘다르게’ 들어간 경우뿐 아니라, 띄어쓰기·표기 차이만으로도 같은 일이 벌어집니다. ‘청바지’와 ‘청 바지’는 사람 눈엔 같지만 GA4는 다른 상품으로 인식해 두 줄로 흩어집니다.

✗ 피함 — 띄어쓰기 차이
변수view_itemadd_to_cartpurchase
item_name청바지청바지청 바지
항목 이름조회장바구니구매
청바지110
청 바지001

이런 분리가 분석에 어떤 의미인지 — 깔때기가 무너집니다. ‘청바지를 조회한 사람 중 몇 %가 장바구니에 담고 몇 %가 구매했는가?’ 같은 가장 기본적인 분석이 안 됩니다. 한 상품을 두 줄로 나눠 봤기 때문이죠. 영향력이 작아 보여도, 여러 상품이 동시에 이런 문제를 가지면 리포트 신뢰도가 통째로 흔들립니다.

운영 관점에서 한 가지 실전 팁 — 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.

이 문서가 도움이 되셨나요?