Q. 내부 링크에 UTM을 붙이면 세션이 중복 계상되나요?
아니요. GA4와 Amplitude 모두 세션 소스는 첫 터치에 고정되고, 같은 파라미터를 다시 이어붙여도 세션이 갈리지 않는다. claude.com 실측에서 페이지 3개를 연속 이동해도 동일 익명ID·동일 캠페인이 유지됐다(2026-07-10). 대신 이 재부착에는 다른 목적이 있다, 광고 클릭ID를 도메인이 다른 전환 페이지까지 운반하는 것.
오늘 바로 쓸 핵심 3줄
- 전환 도메인이 분리돼 있다면, 클릭ID 허용 목록(gclid·fbclid·msclkid 등)부터 정의하라.
- 픽셀은 전환이 실제로 일어나는 도메인에만 설치하고, 마케팅 도메인은 URL로 값을 넘겨라.
- 네이버는 gclid가 없다, NaPm의 ci 값을 클릭ID로 캡처해 오프라인 조인에 써라.
광고를 타고 들어갔는데, 블로그까지 꼬리표가 따라왔다
구글 광고를 눌러 클로드(claude.com) 랜딩에 들어갔다. 주소창엔 익숙한 꼬리표, utm_source=google 같은 값들과 gclid가 붙어 있었으니 여기까진 평범한 편이지.
그런데 랜딩에서 블로그 글로 한 번 더 넘어가 보니, 같은 꼬리표가 그대로 다시 떠 있었다. 클릭한 적도 없는 링크인데 블로그 URL 뒤에 gclid가 붙어 있었다.
개발자 도구로 네트워크를 열어 봐도 구글 태그(GTM·gtag)나 픽셀 요청이 보이지 않았다. 그럼 이 클릭ID는 누가 계속 복사하고 있는 걸까. Playwright로 랜딩부터 블로그까지 세 페이지를 연속으로 넘기며 네트워크 요청과 주소창을 하나씩 대조했다(2026-07-10).
이 글은 세 가지를 답한다. 왜 파라미터가 계속 따라붙는가, 이게 트래픽을 중복 계상시키진 않는가, 우리 서비스도 이렇게 해야 하는가.
범인은 서버가 아니라 브라우저 안에 있었다
제일 먼저 의심한 건 서버였다. 서버가 응답을 만들 때부터 파라미터를 심는 거라면 이야기는 간단해서, curl로 원본 HTML을 그대로 받아봤다.
결과는 깨끗했다. canonical 태그에도 파라미터 없는 URL만 있었고 본문 어디에도 gclid 흔적이 없었다, 범인은 서버가 아니었던 것.
다음 용의자는 자바스크립트였다. 사이트 번들을 뒤져 Next.js가 만든 청크 하나(8c63d2c26586bdb1.js)를 열어보니 원하던 코드가 그대로 있었다.
로직은 이랬는데, 페이지가 열리면 주소창 쿼리에서 미리 정한 파라미터만 골라 sessionStorage(브라우저가 탭을 닫으면 자동으로 비우는 임시 저장 서랍)에 저장한다. 만료는 저장 시점부터 30분, 롤링 방식이다.
이후 페이지 안 모든 링크(a 태그)를 순회하며 저장해둔 파라미터를 다시 붙인다. 나중에 새로 생기는 링크까지 놓치지 않으려고 MutationObserver(화면 구조 변화를 실시간 감시하는 브라우저 API)를 10초간 걸어둔다.
30분이 그냥 고른 숫자였을까. 분석 도구(Segment·Amplitude)가 세션을 가르는 기준(analytics_session_id)도 똑같이 30분 창이라서, 캠페인 라벨의 수명을 세션 수명에 그대로 맞춘 것이었지. 세션이 끝나면 라벨도 같이 죽는다.
이미지: 서버 응답은 깨끗했다. 장식은 로드 후 자바스크립트가, sessionStorage에 30분 만료로 한다.
아무 파라미터나 담지 않는다, 12칸짜리 장바구니
그런데 이 스크립트가 주소창의 모든 파라미터를 다 챙기는 건 아니었다. 허용 목록을 코드에서 그대로 뽑아봤다.
["utm_source","utm_medium","utm_campaign","utm_content","utm_term",
"gclid","dclid","gbraid","wbraid","fbclid","msclkid","li_fat_id"]
UTM 5종(누가·어느 경로·어느 캠페인·어느 소재·어느 키워드로 왔는지)에, 클릭ID 7종이 더해져 딱 12칸이다. 클릭ID는 구글 4종(gclid·dclid·gbraid·wbraid), 페이스북(fbclid), 마이크로소프트(msclkid), 링크드인(li_fat_id)이다.
반면 같은 구글 광고가 자동으로 붙이는 gclsrc·targetid·gad_source·gad_campaignid 같은 진단용 파라미터는 목록에 없다, 전부 버려진다. 귀속(어떤 방문이 어떤 매출로 이어졌는지 추적하는 일)에 필요한 신호만 담고 나머지는 짐짝 취급하는 셈이다.
링크를 장식하는 데도 규칙이 있다. 전화(tel:)·메일(mailto:)·페이지 내부 앵커(#)·PDF·이미지 링크는 건너뛴다. 같은 도메인(claude.com과 그 하위 도메인)끼리만 장식하고, 링크에 파라미터가 이미 있으면 덮어쓰지 않는다.
그리고 전환 도메인인 claude.ai로 가는 링크만 예외로 취급한다. UTM은 다 빼고 클릭ID 3종(gclid·gbraid·wbraid)만 붙인다. 이 예외가 다음 발견으로 이어지거든.
이미지: UTM 5종 + 클릭ID 7종, 딱 12칸만 담긴다. 나머지는 버려진다.
가입 버튼에는 비밀 통로가 있었다
허용 목록만으로는 절반짜리 설명이다. claude.com에서 claude.ai(가입·로그인이 실제로 일어나는 전환 도메인)로 가는 링크를 열어보면, 클릭 전엔 안 보이던 경로가 튀어나온다. href를 다시 열어보니 claude.ai/redirect/{긴 문자열}/원래경로 형태였다.
이 경로를 curl로 따라가려 하니 403이 떴다. 헤드리스 브라우저로도 막혔다. Cloudflare가 사람인지 봇인지 가리는 챌린지를 걸어둔 탓인데, 결국 화면이 있는 진짜 브라우저(헤디드 크로미움)로 열어야 통과됐다.
끝까지 따라가 본 결과는 이랬다. /redirect/{ID}/code?gclid=X로 들어가면 최종 URL은 claude.ai/code?gclid=X로 바뀐다. 서버가 그 긴 ID를 소비하고 지운 뒤 클릭ID만 남긴다는 뜻이다.
claude.ai에 새로 심긴 ajs_anonymous_id 쿠키를 열어보니, claude.com에서 쓰던 익명ID가 글자 그대로 옮겨와 있었다. 신원이 도메인을 건너 그대로 이어진 것이다(신원 스티칭).
그리고 claude.ai는 넘어온 gclid를 자기 쿠키(_ant_gclid)에 저장해둔다. 가입이라는 전환이 실제로 일어나는 순간 이 쿠키를 꺼내 쓸 자리를 미리 마련해둔 셈이다.
여기서 흥미로운 대조가 하나 있는데, claude.ai에는 구글 태그가 남기는 쿠키(_gcl_au·_gcl_aw)가 있고 claude.com에는 없다. 마케팅 사이트는 무픽셀, 전환이 실제로 일어나는 사이트에만 태그를 심어둔 것이다. 픽셀은 전환 도메인에만, 이라는 최소 설치 원칙이지.
Segment 설정을 열어보니 claude.com과 claude.ai가 writeKey(분석 도구 접속 열쇠) 하나를 공유하고 있었다. 익명ID만 같으면 두 도메인 행동이 자동으로 한 프로필에 쌓인다. 연결된 목적지는 Amplitude(제품 분석)·Iterable(마케팅 메시징)·Hubspot(B2B CRM)·Podscribe(팟캐스트 광고 귀속)·자체 웹훅까지 다섯 갈래였는데, 구글 광고 전환 업로드로 보이는 목적지는 이 경로 어디에도 없었다. 서버 쪽에서 별도로 구글에 전환을 올리는 것으로 보이지만, 이건 외부에서 관측할 수 없는 영역이라 추정으로만 남겨둔다.
이미지: redirect 경로가 익명ID를 소비하고, 클릭ID만 전환 도메인 쿠키(_ant_gclid)로 남긴다.
왜 이렇게까지 하나: 쿠키가 못 하는 일이 두 가지 있다
여기까지 보면 굳이 이렇게 복잡하게 할 이유가 있나 싶다. 쿠키 하나면 되는 거 아닌가. 그런데 쿠키에는 못 하는 일이 정확히 두 가지 있고, 그게 이 설계 전체를 설명한다.
첫째, 쿠키는 도메인을 못 넘는다. 브라우저는 claude.com이 심은 쿠키를 claude.ai가 읽지 못하게 막아둔다, 다른 사이트가 내 쿠키를 훔쳐보지 못하게 하는 기본 보안 규칙이다. 그래서 광고 클릭ID를 claude.com에 쿠키로만 저장해두면, 방문자가 claude.ai로 넘어가는 순간 그 정보는 그냥 끊긴다.
둘째, 사파리의 ITP(Intelligent Tracking Prevention, 광고 추적을 막으려고 애플이 사파리에 넣어둔 정책)는 자바스크립트가 심은 쿠키 수명을 7일로 잘라버린다. 광고를 클릭하고 일주일 넘게 고민하다 가입하는 사람한테는 쿠키가 이미 사라진 뒤다.
여기에 동기 세 가지가 더해지거든. 자체 도메인으로 분석 요청을 우회시키는 것(a-cdn.anthropic.com)에서 보이듯 광고 차단기를 피하려는 목적, 서드파티 쿠키에 기대지 않고 자사 데이터를 직접 쥐려는 목적, 픽셀을 최소로 쓴다는 프라이버시 지향 브랜딩까지.
결국 URL이 도메인 경계와 쿠키 수명 제한을 동시에 우회하는 유일한 운반 수단이다. 그래서 1~4에서 본 장치들, 허용 목록·30분 만료·redirect 스티칭이 전부 URL 하나를 중심으로 짜여 있던 거다.
이미지: 쿠키가 못 하는 두 가지, 도메인을 못 넘고 사파리에서 7일이면 사라진다.
동의를 거부하면 정확히 어디까지 꺼질까
이 정도로 정교한 추적이면 동의를 거부했을 때 뭐가 남는지 궁금해진다. 동의 거부 쿠키(anthropic-consent-preferences)에 analytics·marketing 거부를 직접 심고 새로고침해봤다(2026-07-11).
| 기능 | 동의 거부 시 |
|---|---|
| tracking_params 저장 (sessionStorage) | 유지 (동의 무관) |
| 같은 도메인 링크 UTM 장식 | 유지 (동의 무관) |
| claude.ai 링크 redirect 익명ID | 제거 (완전 청정) |
| claude.ai 링크 클릭ID 부착 | 제거 |
| Segment/Amplitude 기동·비콘 | 0건 |
경계선이 뚜렷하더라. 캠페인 라벨(utm_source=google 같은)은 신원이 없는 문자열이라 동의 밖에 있고 그대로 유지된다. 반면 신원(익명ID)과 클릭ID가 도메인을 건너가는 건 그 순간 개인을 추적 가능하게 만드는 행위라서 동의 안으로 들어간다, 거부하면 즉시 끊긴다.
동의 관리 설계를 고민 중이라면 이 경계가 쓸 만한 참고선이다. 캠페인 라벨은 게이팅 대상이 아니고, 신원·클릭ID의 도메인 간 이동만 게이팅하면 된다는 뜻이니까.
이미지: 동의 거부 시 캠페인 라벨만 남고, 신원·클릭ID·비콘은 0건.
OpenAI도 똑같은 걸 하고 있었다
클로드 혼자만의 특이한 설계인지 확인하려고, 같은 조건(UTM+gclid를 붙인 랜딩 방문)으로 네 개 사이트를 더 열어봤다(2026-07-11).
| 사이트 | 내부 링크 장식 | 크로스 도메인 운반 | 저장 방식 | 구글 태그 |
|---|---|---|---|---|
| claude.com | UTM 전체 | claude.ai로 redirect 경로 + 클릭ID | sessionStorage 30분 | 없음(claude.ai에만) |
| openai.com | 없음 | chatgpt.com 링크에 gclid + 기기ID(openaicom-did) + 리퍼러 플래그(openaicom_referred) 부착 | 미확인 | 없음 |
| vercel.com | 없음 | 해당 없음(단일 도메인) | localStorage utmValues {currentUtm, prevUtm} | 없음 |
| notion.com | 없음 | 해당 없음 | localStorage adClick {type:"google", id:gclid} + _gcl_ls | 있음 |
| stripe.com | 없음 | 없음(관측상) | 없음(관측상) | 없음 |
패턴을 가르는 기준은 하나였다. 마케팅 도메인과 전환 도메인이 분리돼 있으면 URL로 운반한다, 클로드의 경로 방식이든 OpenAI의 쿼리 방식이든. 단일 도메인이면 그냥 저장소에 묻어둔다, Vercel의 utmValues와 Notion의 adClick처럼. 갈림길은 도메인 구조 하나로 갈렸다.
Vercel이 현재값과 직전값(currentUtm/prevUtm)을 같이 들고 있는 것도, Notion이 {플랫폼, 클릭ID} 구조로 저장하는 것도, 저장소 진영을 택했을 때 참고할 만한 구현이다.
이미지: 전환 도메인이 갈리면 URL로, 한 도메인이면 저장소로.
네이버엔 gclid가 없다, 대신 NaPm이 있다
지금까지는 전부 구글 생태계 얘기였잖아. 국내 마케터한테 진짜 중요한 건 네이버다. 우리 서비스의 네이버 브랜드검색 광고를 정액제(클릭이 몇 번 나도 추가 과금이 없는 상품)로 직접 클릭해봤다, 돈 걱정 없이 실측할 수 있는 조건이었다.
NaPm=ct={클릭시각}|ci={클릭ID}|tr={유형}|hk={해시}|nacn={브라우저 식별값}
같은 브라우저로 두 번 클릭해서 도착 URL을 나란히 놓고 비교해보니, ci 값만 바뀌고 nacn은 그대로였다. ci는 클릭 한 번마다 새로 발급되는 값, 말하자면 네이버판 gclid다. nacn은 브라우저(기기) 단위로 고정되는 값이지.
tr=brnd는 브랜드검색 상품 표시다. 성과형 광고인 파워링크는 충전이 필요해 이번엔 안 눌러봤다, 광고주 본인 계정이라면 광고시스템 화면에서 확인할 수 있다.
NaPm이 프리미엄 로그 분석과 연동되는 파라미터라는 건 업계에 통용되는 지식인데, 네이버 공식 문서(검색광고 교육 페이지)가 접근 차단이라 1차 출처로는 확인하지 못했다. 위에 적은 구조 자체는 직접 실측한 값이다.
동종업계 A사(인터넷가입 비교 서비스)의 같은 브랜드검색 랜딩도 열어봤다. utm_campaign을 bsa_naver_pc처럼 채널과 기기로 쪼개고, 서브링크마다 utm_content까지 따로 다는 세밀한 UTM 설계였다.
저장은 MMP(모바일 어트리뷰션 플랫폼, 앱과 웹의 광고 성과를 한 곳에서 묶어 추적해주는 도구) 하나(Airbridge)가 랜딩 URL 전체(NaPm 포함)를 localStorage에 3일 만료로 넣어두고, sessionStorage에도 utm 값을 따로 이중 저장하고 있었다. GA4와 구글 태그도 같이 쓰지만 클로드처럼 링크를 장식하진 않았다, 저장소 진영의 실제 구현이다.
랜딩에서 NaPm(적어도 ci·tr)을 UTM과 나란히 캡처해 저장해두면, 전환 API가 없는 네이버에서도 클릭 단위로 오프라인 매출을 조인(BQ 등에서 클릭ID를 매칭 키로 쓰는 것)할 길이 열린다. 이게 이번 실측에서 가장 실무적으로 쓸모 있던 발견이다.
이미지: 네이버 NaPm의 ci, 클릭마다 새로 찍히는 네이버판 gclid.
당신 사이트에 이게 필요한지 30초면 판별된다
여기까지 클로드·오픈AI·네이버까지 훑어봤으니, 이제 방향을 우리 사이트 쪽으로 돌려보자.
판단 기준은 세 가지인데, 전환이 일어나는 도메인이 랜딩과 분리돼 있는가, 다르면 URL 운반이 필요해진다. 캠페인이 아니라 리드 한 건 단위로 귀속해야 하는가, 그렇다면 클릭ID 하나까지 살려둬야 한다. 랜딩에서 최종 제출까지 거리가 먼가, 페이지를 여러 번 거치거나 며칠 뒤 돌아오는 구조라면 세션 쿠키만으로는 부족하다.
구현은 생각보다 크지 않거든. 코드 40줄 안팎이면 GTM 커스텀 HTML 태그로도 넣을 수 있다. 허용 목록부터 정의하고, 페이지 로드 시 주소창에서 목록에 걸리는 값만 sessionStorage에 만료시각과 함께 저장하고, 같은 도메인·비정적파일 링크만 순회하며 기존 값을 안 덮어쓰고 붙이고, SPA라면 MutationObserver로 재장식하고, canonical 태그는 파라미터 없는 URL로 유지한다.
- 도메인 분리: 전환이 다른 도메인에서 일어나나? 쿠키 대신 URL로 클릭ID를 넘기는 장치부터 만들어라.
- 리드 단위 귀속: 캠페인 말고 리드 한 건까지 추적해야 하나? 허용 목록에 클릭ID를 반드시 넣고, 만료 없는 별도 저장소에 백업하라.
- 네이버 클릭ID: 네이버 광고도 돌리나? NaPm의 ci 값을 UTM과 함께 캡처해 오프라인 조인 키로 확보하라.
그래도 하나만 챙긴다면, 이것이다.
픽셀이 못 넘는 경계는 URL이 넘는다, 그래서 URL이 사라지면 안 된다.
이 실측에 나오는 기초 개념은 '디지털 마케팅 분석 입문' 시리즈에서 초보자 눈높이로 풀었다. UTM 파라미터 완전 기초, 전환 추적의 원리(픽셀·클릭ID·서버사이드), 그리고 추적이 안 남는 영역은 다크 퍼널 추적법 참고.
근거·출처
- claude.com 실측(Playwright 네트워크 분석, sessionStorage·비콘 확인, 2026-07-10): claude.com
- 링크 장식 로직 소스(Next.js 번들 청크 8c63d2c26586bdb1.js, 2026-07-10): claude.com
- claude.ai redirect 실추적 + 동의 거부 실험(헤디드 Chromium, 2026-07-11): claude.ai
- 4사 벤치마크(동일 조건 UTM+gclid 랜딩, 2026-07-11): openai.com, vercel.com, notion.com, stripe.com
- 네이버 브랜드검색 클릭 실측(정액제 무과금 클릭, 2026-07-11): searchad.naver.com
일부 사례는 가명 처리했다(동종업계 A사). 구글 서버사이드 전환 업로드는 외부에서 관측할 수 없어 추정으로 남겼고, NaPm과 프리미엄 로그 분석의 연동은 공식 문서 확인 없이 통용 지식과 실측 구조만으로 적었다.
이 글이 도움이 되었다면 공유해주세요
최신 인사이트
카카오톡 공유 썸네일 안 나올 때 해결법 (Kakao JavaScript SDK 2025)
카카오톡 공유하기에서 썸네일 이미지가 안 나오는 원인과 scrapImage로 KAGE URL을 변환해 해결하는 방법을 단계별로 설명합니다. 지금 확인하세요.
Claude Code 서브에이전트로 CRM 사용자 설명서 20분 만에 완성하는 방법
Claude Code 서브에이전트를 활용해 CRM 코드베이스에서 사용자 설명서와 비주얼 가이드북을 20분 만에 자동 생성한 실전 사례를 공유합니다. 지금 확인하세요.
GEO 생성형 엔진 최적화: 2025년 AI 마케팅 전략 완전 가이드
GEO 생성형 엔진 최적화란 무엇이며 기존 SEO와 어떻게 다른지, 2025년 AI 마케팅 전략의 핵심 실행 방법 5가지를 데이터와 함께 알아보세요.
관련 프로젝트
새 글을 이메일로 받아보세요
마케팅, 분석, 개발 인사이트를 정리해서 보내드려요.
