광고 픽셀은 UTM이 사라져도 어떻게 전환을 잡는가
Cookie-based Click Attribution & SPA Pageview Tracking
난이도: ★★★☆☆
연관 노트: 왜 서버는 이전 요청을 기억하지 않는가
핵심 요약
- 스크립트는 광고 유입 시에만 실행되는 게 아니라 모든 방문자에게 항상 실행된다.
- 광고 클릭 시 URL에 붙어오는 클릭 ID를 스크립트가 감지해 쿠키에 저장하고, 이후 전환 이벤트가 발생하면 그 쿠키값을 매체 서버로 전송한다.
- 매체 서버는 클릭 ID를 외래키로 캠페인 정보를 조회해 전환을 카운팅한다.
왜 헷갈렸나
- UTM이 URL에서 사라지면 전환 추적도 불가능하다고 생각했음 → UTM은 URL 파라미터라 소실되지만, 쿠키는 브라우저에 남는다
- “광고 유입 시에만 스크립트가 실행된다”고 생각했음 → 스크립트는 항상 실행, 클릭 ID가 있을 때만 쿠키에 저장
- 매체 서버로 보내는 방식이 POST라고 단정했음 → 이미지 픽셀(구식)은 GET, 현대 JS 픽셀은
navigator.sendBeacon()/fetch()
메커니즘
1. 클릭 ID — 쿠키 저장
[광고 캠페인 클릭]
URL: mysite.com?gclid=CjwKCAiA9abc123
^
광고 매체가 발급한 클릭 ID (영수증 번호)
[픽셀 스크립트 실행 — 모든 방문자]
URL 쿼리스트링에 gclid가 있는가?
→ Yes: _gcl_au 쿠키에 저장 (만료: 90일)
→ No: 아무 것도 저장 안 함. 스크립트는 계속 실행됨
[이후 UTM 소실해도]
쿠키: _gcl_au=CjwKCAiA9abc123 ← 브라우저에 잔류
2. 전환 이벤트 → 매체 서버 전송
[전환 이벤트 발생]
pixel({ event: 'purchase', value: 100 })
[픽셀 내부]
쿠키에서 _gcl_au 읽기 → CjwKCAiA9abc123
HTTP 요청 전송:
POST https://google-analytics.com/collect
Body: { event: 'purchase', gclid: 'CjwKCAiA9abc123', ... }
[매체 서버]
gclid 'CjwKCAiA9abc123' 조회
→ "이건 캠페인 A, 광고그룹 B, 키워드 C에서 발생한 클릭"
→ 해당 캠페인 전환 +1
클릭 ID는 캠페인 정보를 직접 담지 않는다. 캠페인 정보를 조회하는 외래키다.
3. 매체별 클릭 ID 쿠키
| 매체 | 클릭 ID 파라미터 | 쿠키명 |
|---|---|---|
| Google Ads | gclid | _gcl_au |
| Meta | fbclid | _fbp, _fbc |
| Naver | nclickid (비공개) | 자체 쿠키 |
| 국내 DSP | (매체별 상이) | 자체 쿠키 |
어트리뷰션 인플레이션
여러 매체를 순서대로 클릭하면, 각 매체가 독립적으로 자기 쿠키를 심는다.
[사용자 행동]
네이버 광고 클릭 → 쿠키 N 저장
구글 광고 클릭 → 쿠키 G 저장
메타 광고 클릭 → 쿠키 M 저장
오가닉 진입 후 결제
[전환 이벤트 발생 — 모든 픽셀 동시 실행]
naverPixel({ event: 'join' }) → 쿠키 N 전송 → 네이버: 전환 +1
googlePixel({ event: 'join' }) → 쿠키 G 전송 → 구글: 전환 +1
metaPixel('Purchase') → 쿠키 M 전송 → 메타: 전환 +1
실제 전환: 1건
각 매체 리포트 합산: 3건
각 매체는 자기 쿠키만 본다. 다른 매체가 있었는지 모른다. 그래서 동시에 “내가 기여했다”고 주장한다.
라스트 클릭 문제: 실제로 구글이 마지막 클릭이었어도, 메타는 “내 lookback window(7일) 내에 클릭이 있었다”는 이유로 전환을 가져간다. 각자의 “라스트 클릭”이 겹친다.
→ 해결: 모든 채널을 한 곳에서 보는 서드파티 어트리뷰션 툴 (GA4, Triple Whale 등). 각 매체 리포트를 신뢰하지 않고 자체 기준으로 어트리뷰션.
SPA에서 pageview를 수동 호출해야 하는 이유
일반 웹사이트(MPA)는 페이지 이동 = 실제 페이지 리로드 → 스크립트 재실행 → pageview 자동 전송.
[MPA]
페이지 이동 → HTML 재요청 → 스크립트 재로드 → pageview 자동 ✓
[SPA (Next.js)]
페이지 이동 → URL만 바뀜 → 스크립트 재로드 없음 → pageview 안 찍힘 ✗
해결: routeChangeComplete에 수동 연결
// _app.tsx
Router.events.on("routeChangeComplete", () => {
pixelAPageView(); // 매체 A — 어트리뷰션용
pixelBPageView(); // 매체 B — 행동 수집용
// 설치된 모든 매체 픽셀 pageview 호출
});
routeChangeComplete = Next.js Router에서 URL 변경이 완료된 시점. 이때 수동으로 호출해야 각 매체가 사용자 행동을 정상 트래킹한다.
어트리뷰션 픽셀 vs 행동 수집 픽셀
일부 매체는 두 개의 파이프라인을 분리해 제공한다.
| 어트리뷰션 픽셀 | 행동 수집 픽셀 | |
|---|---|---|
| 목적 | 광고 어트리뷰션 측정 | 방문자 행동 수집 |
| 용도 | ROAS 계산, 전환 카운팅 | 리타게팅 오디언스 구축 |
| 함수 | trackConversion({ type }) | trackPageView() |
다음에 이 상황을 만나면
트리거: 새 광고 매체 픽셀 설치 요청이 올 때
- 픽셀 스크립트를
_app.tsx에 삽입 (모든 페이지에 로드되도록) - SPA라면
routeChangeComplete에 pageview 수동 연결 - 전환 이벤트는 실제 전환 페이지(결제 완료 등)에만 발화
- Window 타입 선언 추가 (
declare global { interface Window { ... } }) - 스크립트 로드 전 함수 호출 대비 — 큐 패턴 확인
// 큐 패턴: 스크립트 로드 전 호출을 쌓아뒀다가 로드 후 실행
window.pixelSDK =
window.pixelSDK ||
function (...args: unknown[]) {
(window.pixelSDK.q = window.pixelSDK.q || []).push(args);
};
window.pixelSDK(); // 큐에 쌓임 → SDK 스크립트 로드 후 자동 처리
커넥팅 닷
← 선행 개념 (이걸 알아야 이해된다)
- 왜 서버는 이전 요청을 기억하지 않는가 — HTTP Stateless이기 때문에 상태(클릭 정보)를 쿠키에 저장하는 구조가 필요함. 쿠키가 상태를 들고 있는 HTTP 레이어 원리와 동일
- HTTP 쿠키 (Set-Cookie / Cookie 헤더) — 브라우저가 쿠키를 저장하고 이후 요청마다 자동으로 포함하는 원리. 픽셀이 쿠키를 읽어 전송하는 메커니즘의 기반
→ 확장 개념 (여기서 더 나아가면)
- ITP (Intelligent Tracking Prevention) — Safari의 서드파티 쿠키 제한. 픽셀 추적 정확도를 떨어뜨리는 주요 원인. 매체들이 서버사이드 픽셀(Conversions API)로 전환하는 이유
- Conversions API (CAPI) — 브라우저 픽셀 대신 서버에서 직접 매체 서버로 전환 이벤트를 보내는 방식. ITP 우회 + 쿠키 의존도 제거
- Multi-touch Attribution — 라스트 클릭 대신 터치포인트마다 기여도를 나눠주는 모델. Linear, Time-decay, Data-driven 등
↔ 같은 원리가 적용되는 곳
- JWT 인증 — 클릭 ID가 외래키인 것처럼, JWT도 서버가 상태를 저장하지 않고 토큰(외래키)으로 사용자 정보를 조회. 둘 다 “ID → 서버 매핑” 패턴
- sessionStorage 대신 URL에 상태를 담는 이유 — UTM 파라미터는 URL에 상태를 담는 방식. 쿠키 기반 추적과 달리 탭 간 공유 가능하지만 소실 위험이 있음
- WebView에서 인증 팝업이 조용히 차단되는 이유 — 브라우저/앱 정책이 3rd party 동작을 제한하는 같은 맥락. 픽셀이 ITP로 차단되듯, 팝업이 WebView 정책으로 차단됨
- 단축 URL 뒤에 붙인 파라미터는 어디로 갔나? — 추적 파라미터가 리다이렉트를 거쳐 목적지·분석 도구까지 도달하느냐의 같은 문제
참고
- Google Ads — gclid 설명 — 클릭 ID 구조와 자동 태깅
- ITP 2.1 이후 쿠키 제한 — WebKit 블로그 — 서드파티 쿠키가 줄어드는 배경