봇이 열 개 돌고 있었습니다. 유튜브 쇼츠 채널들, 인스타 네 계정, 쓰레드, 무인 팔로우봇. 대시보드를 열면 전부 초록불이었습니다. 조회수 28,706, 팔로워 3,207, 게시 정상. 숫자가 매일 올라갔습니다.
그런데 한 문장을 스스로에게 걸었더니 전부 멈췄습니다. 저는 대시보드를 볼 때마다 "1원칙으로 분석해"를 강제로 겁니다 — 진짜 의미 있는 숫자 하나가 뭐냐, 나머지는 허영 아니냐. 그 질문을 봇들에 던졌습니다.
이 봇들이 존재하는 이유가 뭐지? 앱으로 사람을 보내서 광고 수익을 만드는 것. 그러면 진짜 숫자는 조회수가 아니라 앱 방문입니다. 조회수는 그 앞 단계일 뿐.
그래서 물었습니다. 28,706 조회 중에 앱 방문 하나라도 만든 게 있나?
몰랐습니다. 아무도 재고 있지 않았습니다.
대시보드는 활동을 잰다, 결과가 아니라
당신의 자동화에 물어보세요. 그게 재는 게 활동입니까, 결과입니까?
조회수·팔로워·게시 성공 — 전부 상류 지표입니다. "봇이 뭔가 했다"는 증거지, "그게 목표에 닿았다"는 증거가 아닙니다. 매출 사슬은 이렇게 생겼습니다:
관심(views) -> 클릭(앱 방문) -> 전환(수익)제 대시보드는 맨 왼쪽 칸만 채우고 있었습니다. 가운데 칸 — 관심이 실제로 클릭으로 넘어가는가 — 은 완전히 캄캄했습니다. 조회수 5만짜리 쓰레드 글도 앱으로 한 명도 못 보낼 수 있습니다. 그걸 모르면 조회수는 그냥 예쁜 숫자입니다.
당신이라면?
여기서 손이 근질거립니다. 조회수는 오르니까, 콘텐츠를 더 찍고 채널을 더 열고 싶어집니다. 상류를 더 밀면 되겠지.
멈추세요. 상류는 이미 넘칩니다 — 월 2만 조회는 병목이 아닙니다. 병목은 그 관심이 어디서 새는지 모른다는 것입니다. 봇을 하나 더 만들겠습니까, 아니면 이미 있는 트래픽이 어디로 빠지는지 먼저 보겠습니까?
저는 후자를 골랐고, 계측선을 찾으러 갔습니다. 그리고 두 번 놀랐습니다.
반전 1 — 수신기는 이미 켜져 있었다
UTM 파라미터(utm_source, utm_campaign 같은)를 링크에 붙이면 GA4가 "이 방문은 쓰레드에서 왔다"를 자동으로 분류합니다. 그러려면 앱 쪽에 GA4 스니펫이 있어야 합니다.
앱 코드를 grep 했습니다. GA 측정 ID가 안 나왔습니다. "역시 수신기가 없구나" 했는데 — 틀렸습니다.
측정 ID가 환경변수 뒤에 숨어 있었습니다. 코드는 process.env.NEXT_PUBLIC_GA_ID가 있을 때만 스니펫을 렌더합니다. grep은 하드코딩된 ID를 찾으니 당연히 빈손이었죠. 실제 배포된 페이지를 curl 하니 G-XXXX... gtag가 멀쩡히 렌더되고 있었습니다. 운세 앱 여섯 개가 이미 몇 주째 GA4로 방문을 잡고 있었습니다.
즉 유튜브 쇼츠가 붙여 보내던 UTM은 허공에 뿌려진 게 아니라 이미 집계되고 있었습니다. 저는 그것도 모르고 "측정이 안 된다"고 진단했던 겁니다. 소스 코드의 부재는 기능의 부재가 아닙니다 — 환경변수 뒤를 봐야 합니다.
반전 2 — 진짜 구멍은 딱 하나였다
그럼 뭐가 문제였나. 쇼츠는 완전한 UTM을 보냅니다. 그런데 쓰레드 봇은 링크에 ?src=threads만 붙이고 있었습니다.
GA4는 utm_* 접두사만 캠페인으로 인식합니다. src=같은 커스텀 파라미터는 그냥 무시합니다. 쓰레드에서 온 방문은 전부 "출처 불명"으로 뭉개지고 있었습니다. 조회 8만짜리 채널의 유입이 통째로 안 보였던 겁니다.
고친 코드는 세 줄이었습니다. 링크를 만드는 함수 하나 — 봇의 모든 앱 링크가 이 함수 하나를 거칩니다(단일 초크포인트) — 를 바꿨습니다:
# 전: GA4가 무시함
return f"{url}?src=threads"
# 후: host 첫 라벨을 캠페인으로 자동 추출 (unse.ootssu.com -> unse)
host = url.split("://", 1)[-1].split("/", 1)[0]
camp = host.split(".", 1)[0]
return f"{url}?utm_source=threads&utm_medium=social&utm_campaign={camp}"호출부 여섯 곳을 안 건드렸습니다. 함수 하나가 병목이었으니 함수 하나만 고치면 모든 링크가 따라옵니다. 뿌리에서 한 번 고치면 모든 호출자가 따라오는 그 구조입니다.
자가진단 — 당신의 깔때기는 보이나요?
지금 당신의 파이프라인에 이 셋을 던져보세요.
- 목표에서 역산한 진짜 숫자가 대시보드에 있나? 조회수 말고, 그게 만들려는 결과(방문·가입·매출)가 숫자로 찍히나요? 없으면 나머지는 전부 허영 지표입니다.
- "수신기가 없다"를 코드 부재로 판단했나? 환경변수·피처플래그 뒤에 이미 켜져 있는지 라이브를 직접 찔러보세요. 소스
grep은 거짓 음성을 냅니다. - 유입 링크가 목적지가 읽을 수 있는 언어로 태깅됐나?
src=,ref=같은 자작 파라미터는 대부분의 분석 도구가 무시합니다. 표준(UTM)을 쓰세요.
솔직한 부분
계측선을 이었다고 매출이 생긴 건 아닙니다. 지금 데이터는 0입니다. GA4 리포트는 실제 클릭이 몇 개 들어와야 채워지고, 그건 앞으로 3~7일을 기다려야 나옵니다.
이 글은 "문제를 풀었다"가 아닙니다. 몇 주 동안 못 풀고 있던 이유가, 풀 대상을 볼 수조차 없었기 때문이었다는 이야기입니다. 측정이 답을 준 게 아니라, 이제서야 질문을 던질 수 있게 됐을 뿐입니다 — 어느 봇이 진짜로 사람을 앱에 보내나. 표본이 쌓이기 전에 결론 내지 않는 것이 다음 규율이고요.
그래서 지금 제가 미는 건 콘텐츠도 채널도 아닙니다. 아무것도 안 만들고 며칠 기다려 그 숫자를 읽는 것. 그게 지금 가장 값진 다음 행동입니다. 봇을 정직하게 감사하면 대부분은 죽여야 할 것으로 드러나는데, 죽일지 살릴지도 저 숫자가 정합니다.
당신의 자동화는 활동을 재고 있나요, 결과를 재고 있나요? 오늘 딱 하나, 가장 바쁜 봇의 링크가 목적지에서 제대로 태깅돼 도착하는지 curl 한 번 찔러보세요. 아마 저처럼 놀랄 겁니다.