Web SDK 연동 가이드
fplink-tracker.js Web SDK를 웹사이트에 연동하여 사용자 여정 데이터를 수집하고, 콘솔 대시보드에서 분석 결과를 확인하는 end-to-end 가이드입니다.
| 애드온 | 필요한 기능 | 없을 때 |
|---|---|---|
| 사용자 여정 분석 | 세션 생성, 이벤트 추적(trackEvent), 플랫폼 전환 기록 | SDK 초기화가 실패합니다 (HTTP 403) |
| 모바일 딥링크 | 앱 등록(웹 앱 포함, 구매 수량만큼 등록 가능), 퍼널 단계·전환 기록(Step 4) | 앱을 등록할 수 없고, 퍼널·전환 호출이 거부됩니다 (HTTP 403) |
| 메시징 | 사용자 기본정보 저장(identify) | 오류 없이 action: "skipped"로 응답하고 저장하지 않습니다 |
전체 흐름 요약
Step 1: 사전 준비 — 앱 등록 & 키 발급
SDK를 사용하려면 먼저 콘솔에서 앱을 등록하고 인증 정보를 확인해야 합니다.
| 항목 | 확인 위치 | 예시 |
|---|---|---|
| App ID | 콘솔 > 앱 관리 목록의 앱 ID 열, 또는 API 키 창 | 42 |
| API Key | 콘솔 > 앱 관리 > API 키 버튼 | 3f2b8c1e-7a4d-4e5f-9b21-0c6d8e7f1a23 (UUID 형식) |
캡처 대상: 콘솔 > 앱 관리 > API 키 모달
App ID와 API Key가 표시된 화면을 캡처해주세요.
Step 2: SDK 설치 & 초기화
웹 페이지에 SDK 스크립트를 추가하고 초기화합니다. 초기화 시 자동으로 세션이 생성됩니다.
2-1. SDK 스크립트 추가
HTML 파일의 </body> 태그 직전에 SDK를 로드합니다.
<!-- FINGERPUSH.LINK SDK -->
<script src="https://api.fingerpush.link/sdk/v1/fplink-tracker.js"></script>
2-2. SDK 초기화
SDK 로드 후 FPLinkTracker 인스턴스를 생성합니다.
방법 1: 단일 앱 키 (하나의 플랫폼만 사용할 때)
var fplinkTracker = new FPLinkTracker({
baseUrl: 'https://api.fingerpush.link', // SDK 전용 도메인 (기존 fplink.net 도 동작)
appId: '42', // ← Step 1에서 확인한 App ID
apiKey: 'YOUR_API_KEY', // ← Step 1에서 확인한 API Key (UUID 형식)
platform: 'web', // 고정값
debug: true // 개발 중에만 true (콘솔 로그 출력)
});
방법 2: 멀티 앱 키 (웹 + 하이브리드 앱에서 동일 페이지를 공유할 때) v1.7.0+
iOS/Android 앱, 웹 앱을 각각 등록한 경우, apps 옵션으로 플랫폼별 키를 한 번에 지정할 수 있습니다. SDK가 감지한 platform(명시 지정 → localStorage 저장값 → 네이티브 브릿지 감지 순으로 결정)에 해당하는 키를 자동으로 선택합니다.
var fplinkTracker = new FPLinkTracker({
baseUrl: 'https://api.fingerpush.link',
apps: {
ios: { appId: '10', apiKey: 'IOS_APP_API_KEY' },
android: { appId: '11', apiKey: 'ANDROID_APP_API_KEY' },
web: { appId: '12', apiKey: 'WEB_APP_API_KEY' }
},
debug: true
});
- 명시적 지정: platform: 'ios'처럼 직접 지정하면 항상 우선
- localStorage 저장값: 세션 전달용 키(기본 fplink_session_id)에 저장된 platform 필드 (네이티브 앱이 딥링크/유니버설링크로 세션 전달 시 기록)
- 네이티브 브릿지 감지: 위 신호가 없을 때 window.FPLink / window.webkit.messageHandlers.FPLink 등록 여부로 폴백 감지
init()은 여러 번 호출해도 초기화가 한 번만 실행되고 같은 결과를 돌려줍니다. 그래서 자동 초기화를 켠 채로 fplinkTracker.init().then(...)을 호출해 초기화 완료를 기다리는 용도로 써도 됩니다 (SDK 1.12.0+). trackEvent 등 다른 메서드는 초기화 완료를 스스로 기다리므로 바로 호출해도 됩니다.
2-3. 초기화 확인
브라우저 개발자 도구(F12)의 Console 탭에서 아래 메시지가 출력되면 성공입니다.
[FPLinkTracker] Initializing User Journey Tracker...
[FPLinkTracker] Creating session... { platform: "web", ... }
[FPLinkTracker] Session created: { success: true, sessionId: "a1b2c3d4-...", ... }
[FPLinkTracker] SDK initialized successfully
세션 ID를 코드에서 확인하려면:
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>세션 ID 확인 예제</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
.info { background: #f0f8ff; padding: 16px; border-radius: 8px; margin: 12px 0; }
.info h3 { margin: 0 0 8px; }
.info pre { background: #1e293b; color: #e2e8f0; padding: 12px; border-radius: 6px;
font-size: 13px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; }
button { padding: 10px 20px; border: none; border-radius: 6px; font-size: 14px;
font-weight: 600; cursor: pointer; color: #fff; margin: 4px; }
.btn-session { background: #3498db; }
.btn-detail { background: #2ecc71; }
</style>
</head>
<body>
<h2>🔍 세션 ID 확인 예제</h2>
<div class="info">
<h3>현재 세션 ID</h3>
<pre id="sessionIdDisplay">SDK 초기화 중...</pre>
</div>
<div class="info">
<h3>세션 상세 정보</h3>
<pre id="sessionInfoDisplay">아래 버튼을 눌러 조회하세요.</pre>
</div>
<button class="btn-session" onclick="showSessionId()">세션 ID 확인</button>
<button class="btn-detail" onclick="showSessionInfo()">세션 상세 정보 조회</button>
<!-- SDK 로드 -->
<script src="https://api.fingerpush.link/sdk/v1/fplink-tracker.js"></script>
<script>
// SDK 초기화
var fplinkTracker = new FPLinkTracker({
baseUrl: 'https://api.fingerpush.link',
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_API_KEY',
platform: 'web',
debug: true
});
// 초기화 완료 후 세션 ID 자동 표시
// (자동 초기화 중이면 그 완료를 기다릴 뿐, 다시 초기화하지 않습니다)
fplinkTracker.init().then(function() {
document.getElementById('sessionIdDisplay').textContent =
fplinkTracker.getSessionId();
});
// 버튼: 세션 ID 확인
function showSessionId() {
var sessionId = fplinkTracker.getSessionId();
console.log('세션 ID:', sessionId);
document.getElementById('sessionIdDisplay').textContent =
sessionId || '(세션 없음)';
}
// 버튼: 세션 상세 정보 조회 (서버 API 호출)
function showSessionInfo() {
fplinkTracker.getSession().then(function(info) {
console.log('세션 정보:', info);
document.getElementById('sessionInfoDisplay').textContent =
JSON.stringify(info, null, 2);
});
}
</script>
</body>
</html>
Step 3: 사용자 행동 이벤트 추적
사용자의 행동(클릭, 상품 조회, 장바구니 등)을 이벤트로 기록합니다. 페이지뷰는 SDK가 자동으로 추적하므로 별도 코드가 필요 없습니다.
3-1. 자동 추적 (페이지뷰)
SDK 초기화 시 다음 이벤트가 자동으로 전송됩니다. 별도 코드를 작성할 필요 없습니다.
| 이벤트 | 시점 | 자동 수집 데이터 |
|---|---|---|
| page_view | SDK 초기화 완료 직후 |
url — 현재 페이지 URL (window.location.href) title — 페이지 제목 (document.title) referrer — 유입 경로 (document.referrer) host — url 의 호스트 (소문자, 예: www.example.com). 한 앱을 여러 사이트에 붙였을 때 사이트를 구분합니다 path — url 의 경로만 (쿼리 제외, 예: /product/123). 광고로 들어온 첫 페이지와 사이트 안 이동을 같은 값으로 묶어 조건(같다)을 걸 때 씁니다 utm_source·utm_medium·utm_campaign·utm_term·utm_content — url 에 있을 때만, 디코딩한 값 host·path·utm_* 는 서버가 url 에서 꺼내 같은 이벤트에 더합니다(이벤트 수는 그대로, url 원본도 그대로). 같은 이름의 키를 직접 보내면 그 값을 씁니다. url·referrer 의 인가 코드·토큰·이메일 등 민감 파라미터(OAuth 콜백의 code·state, *token, email 등)와 광고·검색 클릭 ID(gclid, srsltid, fbclid, 네이버 NaPm, Criteo cto_pld 등)는 지우고 수집합니다 (1.13.4+, 서버에서도 동일하게 제거). utm_* 는 그대로입니다 |
페이지 이탈(page_unload)은 수집하지 않습니다. beforeunload는 모바일 브라우저에서 발화하지 않는 경우가 많아 체류 시간 근거로 쓸 수 없는 반면, 페이지뷰당 수집 건수는 두 배가 되기 때문입니다. 세션 이벤트는 사용자 여정 분석의 과금 단위이므로 그만큼 사용량도 두 배가 됩니다. 페이지별 체류 시간이 필요하면 trackEvent로 직접 기록하세요.
3-2. 커스텀 이벤트 추적
trackEvent(eventType, eventData) 메서드로 원하는 사용자 행동을 기록합니다. 이벤트는 비동기로 전송되며, 전송 실패가 사용자 경험에 영향을 주지 않습니다.
document.getElementById('signupBtn').addEventListener('click', function() {
fplinkTracker.trackEvent('button_click', {
button_id: 'signupBtn',
label: '회원가입'
});
});
// 상품 상세 페이지 진입 시
fplinkTracker.trackEvent('product_view', {
product_id: 'PROD-001',
product_name: '프리미엄 러닝화',
price: 29900,
category: '신발'
});
document.getElementById('cartBtn').addEventListener('click', function() {
fplinkTracker.trackEvent('add_to_cart', {
product_id: 'PROD-001',
product_name: '프리미엄 러닝화',
price: 29900,
quantity: 1
});
});
3-3. trackEvent API 명세
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| eventType | String | 필수 | 이벤트 유형 (예: button_click, product_view, add_to_cart) |
| eventData | Object | 이벤트 속성 (자유 형식 JSON 객체) |
3-4. eventData 구조 설계 가이드
trackEvent()의 두 번째 인자인 eventData는 자유 형식 JSON 객체입니다. 키 이름과 값은 자유롭게 지정할 수 있지만, 콘솔의 이벤트 로그에서 검색 필터로 활용되므로 아래 규칙을 따르면 분석이 편리해집니다.
① 키 이름 규칙
- snake_case 사용 권장 — product_name, category (camelCase 지양)
- 1단계(flat) 구조로 작성 — 중첩 객체나 배열은 필터에서 제외됩니다
- 일관된 키 이름 사용 — 같은 의미의 데이터는 이벤트 간 동일한 키 사용
② 값 타입별 동작
콘솔의 이벤트 로그 필터는 eventData의 값 타입에 따라 필터 표시 여부가 결정됩니다.
| 데이터 타입 | 필터 | 용도 | 예시 |
|---|---|---|---|
| 문자열 | 검색 가능 | 카테고리, 상품명, ID 등 분류 용도 | "category": "electronics" |
| boolean | 검색 가능 | 상태 플래그, 회원 여부 등 | "is_member": true |
| 숫자 | 필터 불가 | 금액, 수량 등 집계용 | "price": 29900 |
| 배열 | 필터 불가 | — | "tags": ["sale"] |
| 중첩 객체 | 필터 불가 | — | "address": {"city": "서울"} |
③ 권장 데이터 구조 예시
// 문자열 값 → 콘솔에서 필터로 검색 가능
fplinkTracker.trackEvent('purchase', {
product_id: 'PROD-001', // ✅ 문자열 → 필터 가능
product_name: '프리미엄 러닝화', // ✅ 문자열 → 필터 가능
category: 'shoes', // ✅ 문자열 → 필터 가능
currency: 'KRW', // ✅ 문자열 → 필터 가능
price: 29900, // 숫자 → 집계용 (필터 불가)
quantity: 1 // 숫자 → 집계용 (필터 불가)
});
// 중첩 객체/배열 → 필터에서 완전히 무시됨
fplinkTracker.trackEvent('purchase', {
product: { // ❌ 중첩 객체 → 필터 불가
id: 'PROD-001',
name: '러닝화'
},
tags: ['sale', 'new'], // ❌ 배열 → 필터 불가
description: '이 상품은...(200자 이상)' // ❌ 200자 초과 → 필터 불가
});
④ 이벤트별 권장 키
아래는 자주 사용되는 이벤트의 권장 데이터 키입니다. 키 이름은 자유이지만 아래 패턴을 따르면 팀 내 일관성을 유지할 수 있습니다.
| 이벤트 | 필터용 키 (문자열) | 집계용 키 (숫자) |
|---|---|---|
| purchase | product_id, product_name, category, currency | price, quantity |
| add_to_cart | product_id, product_name, category | quantity, price |
| page_view | page_url, page_title, category, referrer | — |
| search | query, category | results_count |
| signup | method, referral_source | — |
| button_click | button_id, label, page | — |
⑤ 필터 갱신 주기
- 분석 범위: 이벤트명 목록은 최근 90일, 속성 값 필터는 최근 30일 이내 데이터
- 속성 값은 조직·앱·이벤트·속성 키별로 집계하며, 각 키당 최대 50개 값 (발생 빈도순)
- 기간이 지난 데이터의 필터 값은 자동으로 제거됩니다 — 최근 30일 동안 나오지 않은 속성 값은 필터 목록에서 빠집니다
Step 4: 퍼널 단계 추적 (웹 5단계)
사용자의 전환 여정을 5단계 퍼널로 추적합니다. 각 단계를 코드로 기록하면, 콘솔의 딥링크 퍼널 대시보드에서 단계별 전환율을 시각화할 수 있습니다.
웹 퍼널 5단계
| 순서 | 단계 | 설명 | SDK 메서드 |
|---|---|---|---|
| 1 | CLICKED | 단축 URL 클릭 (서버에서 자동 기록) | 자동 — 코드 불필요 |
| 2 | DEEP_LINK_RESOLVED | 목적 페이지(랜딩페이지) 도달 | fplinkTracker.trackDeepLinkResolved() |
| 3 | CONTENT_VIEWED | 목표 직전 첫 이정표 (상품 상세, 가입 화면 진입 등) — 선택 | fplinkTracker.trackContentViewed() |
| 4 | ACTION_TAKEN | 목표 직전 중간 행동 (장바구니 담기, 결제 시작 등) — 선택 | fplinkTracker.trackActionTaken() |
| 5 | GOAL_COMPLETED | 최종 목표 달성 (구매, 가입 등) | fplinkTracker.trackGoal(goalType, value) |
4-1. 랜딩페이지 도달 (DEEP_LINK_RESOLVED)
사용자가 단축 URL을 클릭하고 목적 페이지에 도착했을 때 기록합니다.
// 랜딩페이지 로드 시
fplinkTracker.trackDeepLinkResolved();
// 또는 범용 메서드 사용
// fplinkTracker.trackFunnelEvent('DEEP_LINK_RESOLVED');
| 전환목표 | CONTENT_VIEWED | ACTION_TAKEN |
|---|---|---|
| 구매 | 상품 상세 조회 | 장바구니 담기 또는 결제 시작 |
| 구독 | 요금제·상품 안내 조회 | 결제 수단 입력, 체험 시작 |
| 회원가입 | 가입 화면 진입 | 본인인증·약관 동의 완료 (없으면 생략) |
| 폼 제출 | 폼 화면 진입 | 생략 |
| 장바구니 담기 | 상품 상세 조회 | 생략 (목표가 곧 액션) |
| 상품 조회 · 콘텐츠 조회 | 생략 (목표가 곧 조회) | 생략 |
| 사용자 정의 | 목표 직전 이정표 두 개를 직접 정합니다 | |
4-2. 콘텐츠 확인 (CONTENT_VIEWED)
목표 직전 첫 이정표로, 사용자가 대상 콘텐츠를 확인한 시점에 기록합니다. (예: 상품 상세 열람, 가입 화면 진입, 영상 재생 시작)
// 상품 상세 정보를 확인한 시점
fplinkTracker.trackContentViewed();
4-3. 행동 수행 (ACTION_TAKEN)
목표 직전 중간 행동을 수행한 시점에 기록합니다. (예: 장바구니 담기, 결제 시작, 본인인증 완료) 회원가입·폼 제출처럼 마땅한 중간 행동이 없는 목표라면 호출하지 않습니다.
// 장바구니에 상품을 담은 시점
fplinkTracker.trackActionTaken();
4-4. 목표 달성 (GOAL_COMPLETED)
최종 전환 목표가 달성된 시점에 기록합니다.
// 방법 A: trackGoal (목표 유형 + 금액)
fplinkTracker.trackGoal('purchase', 29900, 'KRW');
// 방법 B: 편의 메서드
fplinkTracker.trackPurchase(29900, 'KRW');
options.transactionId를 전달하면 서버가 같은 세션에서 같은 주문번호/회원ID로 들어온 전환을 한 번만 기록합니다.
전달하지 않으면 같은 세션에서 같은 목표 유형이 5분 안에 다시 들어올 때만 중복으로 걸러지므로,
그 이후의 새로고침·재시도는 중복 기록될 수 있습니다.
// trackGoal에 options 추가
fplinkTracker.trackGoal('purchase', 29900, 'KRW', { transactionId: 'ORD-20260318-001' });
// trackPurchase에 options 추가
fplinkTracker.trackPurchase(29900, 'KRW', { transactionId: 'ORD-20260318-001' });
// trackSignup에 options 추가 (회원 ID를 transactionId로 활용, SDK 1.12.0+)
fplinkTracker.trackSignup({ transactionId: 'USER-12345' });
// trackConversion에 options 추가
fplinkTracker.trackConversion('newsletter_signup', 1, 'KRW', { transactionId: 'EMAIL-abc' });
clearSession() 없이 trackPurchase()나 trackGoal()을 여러 번 호출하면,
같은 세션에 전환이 각각 누적 기록됩니다 (위의 중복 방지 규칙에 걸리는 호출은 제외).
clearSession()은 로그아웃 또는 크로스플랫폼 전환 시에만 사용하세요.
// 1) 퍼널 목표 달성 (대시보드 전환율 집계용)
fplinkTracker.trackGoal('purchase', 29900, 'KRW');
// 2) 상세 상품 정보 (이벤트 분석용, flat 구조)
fplinkTracker.trackEvent('purchase', {
order_id: 'ORD-20260318-001',
product_id: 'PROD-001',
product_name: '프리미엄 러닝화',
category: '신발/러닝',
price: 29900,
quantity: 1,
coupon: 'SPRING50',
payment_method: 'card'
});
// 총 결제 금액으로 퍼널 목표 기록
fplinkTracker.trackGoal('purchase', 59800, 'KRW');
// 상품별로 개별 이벤트 전송 (flat 구조 유지)
fplinkTracker.trackEvent('purchase_item', {
order_id: 'ORD-20260318-002',
product_id: 'PROD-001',
product_name: '프리미엄 러닝화',
category: '신발/러닝',
price: 29900,
quantity: 1
});
fplinkTracker.trackEvent('purchase_item', {
order_id: 'ORD-20260318-002',
product_id: 'PROD-042',
product_name: '스포츠 양말 3팩',
category: '양말/스포츠',
price: 9900,
quantity: 3
});
// 방법 A: trackGoal
fplinkTracker.trackGoal('signup', 1);
// 방법 B: 편의 메서드
fplinkTracker.trackSignup();
// 뉴스레터 구독, 앱 다운로드 등 자유 전환
fplinkTracker.trackConversion('newsletter_signup', 1);
4-5. 전환 목표 사전 설정 (GoalType)
콘솔에서 URL/캠페인에 전환 목표를 미리 설정해두면, 사용자가 그 단축 URL·캠페인 링크를 클릭해 들어올 때 리다이렉트 주소에 fplink_goal_type이 붙고 SDK가 이를 자동으로 저장합니다. 이 경우 trackGoal() 호출 시 goalType을 null로 생략할 수 있습니다.
- 저장된 값은 브라우저(localStorage)에 남아 다음 방문에도 쓰이고, 목표가 설정된 다른 링크로 들어오면 그 값으로 바뀝니다. 목표가 설정된 링크로 들어온 적이 없는 브라우저에서는 getGoalType()이 null이므로, 필요하면 setGoalType()으로 지정하세요.
- goalType을 생략해도, 세션이 목표가 설정된 URL·캠페인으로 유입됐다면 서버가 그 목표로 기록합니다.
- goalType 값은 영문 소문자·숫자·밑줄 2~50자입니다 (예: purchase, newsletter_signup). 대문자는 소문자로 바뀌고, 그 외 문자가 있으면 HTTP 400으로 거부됩니다.
// 콘솔에서 이 URL의 goalType을 'purchase'로 설정했고, 사용자가 그 링크로 들어왔다면:
console.log(fplinkTracker.getGoalType()); // 'purchase'
// goalType 생략 가능 — 자동으로 'purchase' 사용
fplinkTracker.trackGoal(null, 29900, 'KRW');
// 또는 수동으로 변경
fplinkTracker.setGoalType('subscription');
fplinkTracker.trackGoal(null, 9900);
Step 5: 사용자 식별 & 크로스 플랫폼 전환
로그인한 사용자를 세션에 연결하면, 동일 사용자의 멀티 디바이스·멀티 세션 활동을 통합 분석할 수 있습니다.
5-0. 사용자 기본정보 수집 & 수신동의 관리 (identify / optIn)
로그인 또는 회원가입 시 identify()를 호출하면 사용자의 기본정보(이름·전화번호·이메일·앱푸시 식별자)와 수신동의를 주소록에 저장합니다. 이후 메시지 발송 시 전환분석 결과를 바로 발송 대상으로 연결할 수 있습니다. 주소록 저장에는 메시징 애드온이 필요합니다.
- 페이지 로드 시 → new FPLinkTracker({...}) (세션 생성·복원은 자동)
- 사용자 행동 발생 시 → fplinkTracker.trackEvent(...)
- 로그인 성공 시 → fplinkTracker.login({ externalUserId, phone, email, ... }) (세션 연결 + 주소록 저장)
- 회원가입 완료 시 → fplinkTracker.signup({ externalUserId, ... }) (login + 가입 전환 기록)
- 동의 변경 시 → fplinkTracker.optIn({ externalUserId, smsOptIn: false, ... })
- 회원탈퇴 시 → fplinkTracker.withdraw({ externalUserId })
- 로그아웃 시 → fplinkTracker.clearSession()
// 로그인 성공 후 — 기본정보 + 수신동의 한 번에 저장
const result = await fplinkTracker.identify({
externalUserId: user.id,
name: user.name,
phone: user.phone, // 서버에서 암호화하여 저장
email: user.email, // 서버에서 암호화하여 저장
smsOptIn: user.smsConsent,
emailOptIn: user.emailConsent
});
console.log(result.action); // "created" | "updated" | "reactivated" | "skipped" ...
// 마이페이지 수신동의 변경 시 — 변경 항목만 전달
await fplinkTracker.optIn({
externalUserId: user.id,
smsOptIn: false,
emailAdOptIn: true
});
// 회원탈퇴 시 — 개인정보를 지우고 수신동의를 모두 해제
await fplinkTracker.withdraw({ externalUserId: user.id });
| identify 결과 action | 의미 |
|---|---|
| created | 새 연락처를 만들었습니다 |
| updated | 기존 연락처를 갱신했습니다 |
| reactivated | 탈퇴(withdraw)했던 사용자를 다시 살렸습니다 (재가입) |
| skipped | 메시징 애드온이 없어 저장하지 않았습니다 |
| …_conflict | 예: updated_conflict. 전화번호·이메일이 이미 다른 사용자에게 등록돼 있어 그 항목만 저장하지 않았습니다 |
- identify — 처음 호출 시 레코드를 생성(created), 이후 호출 시 전달한 필드만 업데이트(updated). null·빈 값 필드는 기존 값 유지.
- optIn — 수신동의 항목만 단독 업데이트. identify를 먼저 호출하지 않았거나 탈퇴한 사용자에게 호출하면 404 반환.
5-1. 사용자 연결 (linkUser)
사용자가 로그인하면 linkUser()를 호출하여 세션에 사용자 ID를 연결합니다.
// 로그인 성공 후
fplinkTracker.linkUser('user-12345');
// 이메일, UUID 등 다양한 형식 지원
fplinkTracker.linkUser('user@example.com');
5-2. 외부 사용자 ID (setExternalUserId)
자사 서비스의 사용자 ID를 설정하면, 퍼널 이벤트 전송 시 자동으로 포함되어 콘솔에서 개별 사용자별 여정을 조회할 수 있습니다.
// 로그인 후 또는 SDK 초기화 직후
fplinkTracker.setExternalUserId('member-9876');
// 이후 퍼널 이벤트에 자동 포함됨
fplinkTracker.trackGoal('purchase', 29900, 'KRW');
// → 서버에 externalUserId: 'member-9876'가 함께 전송
| linkUser() | setExternalUserId() | |
|---|---|---|
| 동작 | 서버 API 호출 → DB에 세션-사용자 영구 매핑 | SDK 내부 변수에만 저장 (서버 호출 없음) |
| 적용 범위 | 세션 전체 (세션이 살아있는 동안 유지) | 퍼널 이벤트 전송 시 payload에 포함 |
| 용도 | 크로스 플랫폼·멀티 디바이스 통합 분석 | 퍼널 단계별 사용자 식별·필터링 |
| 페이지 새로고침 | 서버에 저장되어 유지됨 | SDK 메모리에서 사라짐 — 다시 설정하세요 (linkUser로 연결한 세션이면 페이지 로드 후 서버 응답으로 복원됨) |
// 로그인 완료 시 두 메서드 모두 호출
function onLoginSuccess(userId) {
// 1) 세션에 사용자 영구 연결 (서버 저장)
fplinkTracker.linkUser(userId);
// 2) 퍼널 이벤트에 사용자 ID 포함
fplinkTracker.setExternalUserId(userId);
}
5-3. 플랫폼 전환 기록 (recordTransition)
웹에서 앱으로 전환되는 시점에 기록합니다. 이 데이터는 콘솔의 사용자 여정 분석에서 플랫폼 전환 경로로 시각화됩니다.
// 웹 → iOS 앱으로 전환 (Universal Link)
fplinkTracker.recordTransition('ios', 'universal_link', {
customData: { targetUrl: 'https://myapp.com/product/123' }
});
// 웹 → Android 앱으로 전환 (App Link)
fplinkTracker.recordTransition('android', 'app_link');
// transitionType 생략 시 기본값 'redirect' 사용
fplinkTracker.recordTransition('ios');
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| toPlatform | String | 필수 | 전환 대상 플랫폼 (ios, android, web) |
| transitionType | String | 전환 유형 — 기본값 redirect. 자유 문자열로 저장되며 아래 값을 권장합니다. (redirect, deep_link, universal_link, app_link, share, manual) |
|
| options | Object | 추가 정보 — customData(자유 객체), toDeviceInfo, urlId/campaignId |
Step 6: 콘솔에서 결과 확인
SDK로 수집된 데이터는 콘솔 대시보드에서 다양한 관점으로 분석할 수 있습니다.
6-1. URL별 사용자 여정
콘솔 > 단축 URL 목록에서 URL 행의 사용자 여정 분석(경로 아이콘) 버튼을 누르면, 해당 URL을 통해 유입된 세션만 걸러진 사용자 여정 분석 화면이 열립니다.
캡처 대상: 콘솔 > 단축 URL 목록 > 사용자 여정 분석 버튼으로 연 화면
세션 목록, 통계 카드(총 세션, 크로스 플랫폼 세션, 크로스 플랫폼 비율)가 표시된 화면을 캡처해주세요.
통계 카드 해석
| 카드 | 설명 |
|---|---|
| 총 세션 | 조회 조건에 해당하는 전체 세션 수 |
| 크로스 플랫폼 세션 | 웹 ↔ 앱 등 플랫폼 전환이 한 번 이상 있었던 세션 수 |
| 크로스 플랫폼 비율 | 크로스 플랫폼 세션 / 총 세션 × 100 (%) |
필터 옵션
| 필터 | 옵션 | 설명 |
|---|---|---|
| 플랫폼 | 전체, Web, iOS, Android | 세션이 시작된 플랫폼별 필터링 |
| 세션 타입 | 전체, 단일 플랫폼, 크로스 플랫폼 | 단일 디바이스 vs 플랫폼 전환이 있는 세션 |
| 시작 날짜 · 종료 날짜 | 날짜 선택 | 조회 기간 설정 |
6-2. 캠페인별 사용자 여정
콘솔 > 캠페인 목록에서 캠페인 행의 사용자 여정 분석 버튼을 누르면 그 캠페인 링크로 유입된 세션을 조회할 수 있습니다. URL과 마찬가지로 캠페인에 iOS 또는 Android 앱이 연결되어 있을 때 열리며, 웹사이트만 연동했다면 데이터 분석 > 사용자 여정 분석에서 웹 앱을 선택해 조회하세요.
6-3. 데이터 분석 메뉴
콘솔 좌측 데이터 분석 메뉴에서 더 넓은 범위의 분석이 가능합니다.
| 메뉴 | 용도 |
|---|---|
| 행동 분석 > 사용자 여정 분석 | 전체 세션 타임라인, 플랫폼 분포, 크로스 플랫폼 전환 경로 |
| 행동 분석 > 사용자 분석 | 외부 사용자 ID 기반 개별 사용자 행동 분석 |
| 행동 분석 > 이벤트 로그 | trackEvent()로 수집된 원시 이벤트 로그 조회 |
| 행동 분석 > 이벤트 분석 | 이벤트 추이, 플랫폼별 비율, 비교 분석 |
| 성과 분석 > 딥링크 퍼널 | 퍼널 시각화 (웹 앱은 5단계, 단계별 전환율·이탈률, 기록하지 않은 단계는 "건너뜀") |
| 성과 분석 > 전환 분석 | trackGoal() 등으로 기록한 전환 집계 |
캡처 대상: 데이터분석 > 딥링크 퍼널
웹 퍼널 5단계 차트(링크 클릭 → 페이지 도달 → 콘텐츠 조회 → 액션 수행 → 목표 완료)가 표시된 화면을 캡처해주세요.
실전 예제: 이커머스 랜딩페이지
프로모션 단축 URL → 상품 랜딩페이지 → 구매까지 전체 여정을 추적하는 완전한 HTML 예제입니다. 아래 코드를 복사하여 바로 테스트할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>프리미엄 러닝화 — 봄 프로모션</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
.product { border: 1px solid #eee; border-radius: 12px; padding: 20px; margin: 20px 0; }
.price { font-size: 24px; font-weight: 700; color: #e74c3c; margin: 12px 0; }
.btn { display: block; width: 100%; padding: 14px; border: none; border-radius: 8px;
font-size: 16px; font-weight: 600; cursor: pointer; margin: 8px 0; color: #fff; }
.btn-detail { background: #2ecc71; }
.btn-cart { background: #3498db; }
.btn-buy { background: #e74c3c; }
.log-panel { background: #f0f8ff; padding: 12px; border-radius: 8px; margin-top: 20px;
font-size: 13px; }
.log-panel .log { color: #666; margin: 4px 0; }
</style>
</head>
<body>
<div class="product">
<div style="background:#f0f0f0; height:200px; display:flex; align-items:center;
justify-content:center; border-radius:8px; font-size:60px;">👟</div>
<h2>프리미엄 러닝화</h2>
<p>⭐ 4.8 · 리뷰 326건</p>
<div class="price">₩29,900 <small style="text-decoration:line-through; color:#999">₩59,800</small></div>
<button class="btn btn-detail" id="detailBtn">📖 상세 정보 보기</button>
<button class="btn btn-cart" id="cartBtn">🛒 장바구니 담기</button>
<button class="btn btn-buy" id="buyBtn">💳 바로 구매하기</button>
</div>
<!-- 추적 로그 (개발용, 운영 시 제거) -->
<div class="log-panel">
<strong>📡 SDK 추적 로그</strong>
<div id="logArea"></div>
</div>
<!-- ========== SDK 로드 ========== -->
<script src="https://api.fingerpush.link/sdk/v1/fplink-tracker.js"></script>
<script>
// ─── 로그 표시 (개발용) ───────────────────
function log(msg) {
var el = document.getElementById('logArea');
var div = document.createElement('div');
div.className = 'log';
div.textContent = new Date().toLocaleTimeString() + ' — ' + msg;
el.appendChild(div);
}
// ═══════ 1. SDK 초기화 ═══════════════════
// 단일 앱 키 방식 (방법 2: 멀티 앱 키는 상단 가이드 참고)
var fplinkTracker = new FPLinkTracker({
baseUrl: 'https://api.fingerpush.link',
appId: 'YOUR_APP_ID', // ← 실제 App ID로 교체
apiKey: 'YOUR_API_KEY', // ← 실제 API Key로 교체
platform: 'web',
debug: true
});
// SDK 초기화 완료 대기
fplinkTracker.init().then(function() {
log('✅ 세션 생성 완료: ' + fplinkTracker.getSessionId());
// ═══════ 2. 페이지 도달 (퍼널 2단계) ══════
fplinkTracker.trackDeepLinkResolved();
log('📡 DEEP_LINK_RESOLVED — 랜딩페이지 도달');
// 상품 조회 이벤트
fplinkTracker.trackEvent('product_view', {
product_id: 'PROD-001',
product_name: '프리미엄 러닝화',
price: 29900
});
log('📡 product_view 이벤트 전송');
});
// ═══════ 3. 상세 정보 보기 (퍼널 3단계) ═══════
document.getElementById('detailBtn').addEventListener('click', function() {
fplinkTracker.trackContentViewed();
log('📡 CONTENT_VIEWED — 상세 정보 확인');
fplinkTracker.trackEvent('product_detail', {
product_id: 'PROD-001',
section: 'spec'
});
alert('상세 사양, 리뷰, 사이즈 가이드를 확인했습니다.');
});
// ═══════ 4. 장바구니 담기 (퍼널 4단계) ══════
document.getElementById('cartBtn').addEventListener('click', function() {
fplinkTracker.trackActionTaken();
log('📡 ACTION_TAKEN — 장바구니 담기');
fplinkTracker.trackEvent('add_to_cart', {
product_id: 'PROD-001',
price: 29900,
quantity: 1
});
alert('장바구니에 담았습니다!');
});
// ═══════ 5. 구매 완료 (퍼널 5단계) ═════════
document.getElementById('buyBtn').addEventListener('click', function() {
fplinkTracker.trackGoal('purchase', 29900, 'KRW');
log('✅ GOAL_COMPLETED — 구매 완료 ₩29,900');
fplinkTracker.trackEvent('purchase', {
product_id: 'PROD-001',
price: 29900,
currency: 'KRW'
});
alert('구매가 완료되었습니다! 🎉');
});
</script>
</body>
</html>
동작 흐름
① 단축 URL 클릭 → CLICKED (서버 자동 기록)
② 랜딩페이지 로드 → DEEP_LINK_RESOLVED + product_view
③ "상세 정보 보기" 클릭 → CONTENT_VIEWED + product_detail
④ "장바구니 담기" 클릭 → ACTION_TAKEN + add_to_cart
⑤ "바로 구매하기" 클릭 → GOAL_COMPLETED + purchase (₩29,900)
트러블슈팅 & FAQ
세션이 생성되지 않아요
| 원인 | 해결 방법 |
|---|---|
| App ID 또는 API Key 오류 | 콘솔 앱 관리에서 값을 다시 확인하세요. appId는 숫자, apiKey는 3f2b8c1e-7a4d-… 같은 UUID 형식입니다. 값이 틀리면 HTTP 400 또는 401이 납니다. |
| 애드온 미활성 (HTTP 403) | 사용자 여정 분석 애드온이 활성화되어 있는지 구독 & 결제 > 구독 관리에서 확인하세요. |
| baseUrl 오류 | baseUrl에는 SDK 전용 도메인(https://api.fingerpush.link)을 넣으세요. 기존 연동의 https://fplink.net·연결한 커스텀 도메인도 계속 동작합니다. 콘솔 주소로는 SDK 요청이 거부됩니다. |
| CORS 오류 |
CORS(Cross-Origin Resource Sharing)란? 브라우저는 보안을 위해
현재 페이지의 도메인과 다른 도메인으로 API 요청을 보낼 때 자동으로 차단합니다.
예를 들어 https://mysite.com 페이지에서
https://api.fingerpush.link/api/...로 요청하면
서버가 "이 도메인의 요청을 허용한다"고 응답해야만 브라우저가 데이터를 전달합니다.
FPLink Web SDK API는 모든 도메인에서의 요청을 허용하도록 서버에 설정되어 있으므로, 정상적인 경우 CORS 오류가 발생하지 않습니다. 만약 CORS 에러가 보인다면 다음을 확인하세요: ① API 주소 오류 — 요청이 baseUrl + /api/v1/cross-platform/…로 나가는지 확인하세요 (baseUrl 오타, 콘솔 주소 사용 등). ② 네트워크/프록시 차단 — 사내 방화벽이나 프록시가 외부 API 요청을 차단할 수 있습니다. ③ 브라우저 확장 프로그램 — 광고 차단기 등이 요청을 차단할 수 있습니다. 시크릿 모드에서 테스트해 보세요. 확인 방법: 브라우저 개발자 도구(F12) → Console 탭에서 Access to fetch at '...' from origin '...' has been blocked by CORS policy 메시지가 보이면 CORS 문제입니다. |
| localStorage 사용 불가 | 시크릿 모드에서는 localStorage가 제한될 수 있습니다. 일반 모드에서 테스트하세요. |
이벤트가 전송되지 않아요
| 원인 | 해결 방법 |
|---|---|
| 세션 미초기화 | fplinkTracker.getSessionId()로 세션이 존재하는지 확인하세요. |
| 네트워크 오류 | 개발자 도구 Network 탭에서 /api/v1/cross-platform/ 요청의 상태 코드를 확인하세요. |
| 애드온 미구독 (HTTP 403) | 이벤트는 사용자 여정 분석, 퍼널·전환(/session/funnel/track)은 모바일 딥링크 애드온이 필요합니다. 구독 & 결제 > 구독 관리에서 확인하세요. |
| 이벤트 이름이 너무 김 | 이벤트 이름은 100자 이내로 지정하세요. |
디버그 모드 활용
SDK 초기화 시 debug: true를 설정하면 모든 API 호출의 요청/응답이 브라우저 Console에 출력됩니다. 운영 배포 시에는 반드시 debug: false로 변경하거나 옵션을 제거하세요.
var fplinkTracker = new FPLinkTracker({
// ... 기본 설정 ...
debug: true // 개발 시 true → 운영 시 false 또는 제거
});
세션 수동 초기화
세션을 강제로 새로 생성하려면 clearSession() 후 init()을 호출합니다.
// 기존 세션 삭제
fplinkTracker.clearSession();
// 새 세션 생성
fplinkTracker.init().then(function() {
console.log('새 세션:', fplinkTracker.getSessionId());
});
SDK API 요약 레퍼런스
이 가이드에서 사용한 주요 메서드를 한눈에 정리합니다.
세션 관리
| 메서드 | 설명 |
|---|---|
| init() | SDK 초기화 & 세션 생성/복원 (Promise). 여러 번 호출해도 한 번만 실행 (1.12.0+) |
| getSessionId() | 현재 세션 ID 반환 |
| getSession() | 서버에서 세션 정보 전체 조회 (Promise) |
| clearSession() | 로컬 세션 삭제 |
| refreshSession(id?) | 세션 갱신 (하이브리드 앱용) |
이벤트 추적
| 메서드 | 설명 |
|---|---|
| trackEvent(type, data) | 커스텀 이벤트 기록 (비동기) |
| trackCustomEvent(name, data) | trackEvent의 별칭 |
퍼널 추적
| 메서드 | 퍼널 단계 |
|---|---|
| trackFunnelEvent(stage, opts) | 범용 — 모든 단계에 사용 가능 |
| trackDeepLinkResolved() | DEEP_LINK_RESOLVED |
| trackContentViewed() | CONTENT_VIEWED |
| trackActionTaken() | ACTION_TAKEN |
| trackGoal(type, value, currency, opts?) | GOAL_COMPLETED — opts.transactionId로 중복 방지 가능 |
| trackPurchase(amount, currency, opts?) | GOAL_COMPLETED (purchase) — opts.transactionId로 중복 방지 가능 |
| trackSignup(opts?) | GOAL_COMPLETED (signup) — opts.transactionId로 중복 방지 가능 (1.12.0+) |
| trackConversion(name, value, currency, opts?) | GOAL_COMPLETED (커스텀) — opts.transactionId로 중복 방지 가능 |
사용자 식별
| 메서드 | 설명 |
|---|---|
| login(userInfo) | 로그인 시 호출 — linkUser() + identify() |
| signup(userInfo, opts?) | 회원가입 시 호출 — login() + 가입 전환 기록 (opts.transactionId, opts.skipTracking) |
| identify(userInfo) | 주소록에 기본정보·수신동의 저장 (메시징 애드온 필요) |
| updateProfile(userInfo) | 프로필 수정 시 주소록 갱신 (identify()와 동일) |
| optIn(options) | 수신동의 항목만 갱신 |
| withdraw({ externalUserId }) | 회원탈퇴 — 개인정보 삭제·수신동의 해제 |
| linkUser(userId) | 로그인 사용자를 세션에 연결 |
| setExternalUserId(userId) | 외부 사용자 ID 설정 (이벤트에 자동 포함) |
| getExternalUserId() | 현재 설정된 외부 사용자 ID 조회 |
| setGoalType(goalType) | 전환 목표 유형 수동 설정 |
| getGoalType() | 현재 설정된 전환 목표 조회 |
| recordTransition(platform, type, opts) | 플랫폼 전환 기록 |
| notifyReady() | 하이브리드 앱의 네이티브 브릿지에 READY를 다시 통보 (1.13.0+). 초기화 완료·백그라운드 복귀 시에는 자동 — 웹뷰 준비 완료 신호 |
| FPLinkTracker.getInstance() | 마지막으로 생성된 트래커 인스턴스 (1.13.0+). 네이티브가 evaluateJavaScript로 SDK를 조작할 때 사용 — 사이트가 window.tracker를 노출하지 않아도 동작 |
유틸리티
| 메서드 | 설명 |
|---|---|
| getDeviceId() | 브라우저 핑거프린트 기반 디바이스 ID 반환 (디버깅용) |
| FPLinkTracker.VERSION | SDK 버전 문자열 (예: 1.13.0) |