🛤️ Web SDK 연동 가이드

fplink-tracker.js Web SDK를 웹사이트에 연동하여 사용자 여정 데이터를 수집하고, 콘솔 대시보드에서 분석 결과를 확인하는 end-to-end 가이드입니다.

💡 이 가이드의 범위
이 가이드는 웹사이트(HTML 페이지)에 SDK를 삽입하여 사용자 여정을 추적하는 과정을 다룹니다. 모바일 앱이 없어도 웹 세션 분석(방문자 세션, 이벤트, 퍼널)을 바로 시작할 수 있습니다. 모바일 네이티브 SDK 연동은 모바일 SDK 가이드를 참고하세요.
🔒 애드온 필요
사용자 여정 분석 기능은 사용자 여정 분석 애드온을 구독해야 사용할 수 있습니다. 설정 > 구독·결제에서 활성화하세요.

전체 흐름 요약

콘솔에서 앱 등록
App ID, API Key 발급
웹사이트에 SDK 삽입 & 초기화
fplink-tracker.js 스크립트 추가 후 FPLinkTracker 인스턴스 생성
사용자 행동 이벤트 추적
페이지뷰, 클릭, 상품 조회 등 커스텀 이벤트 기록
퍼널 단계 추적
CLICKED → DEEP_LINK_RESOLVED → CONTENT_VIEWED → ACTION_TAKEN → GOAL_COMPLETED
사용자 식별
로그인 사용자를 세션에 연결하여 크로스 플랫폼 통합 분석
콘솔에서 결과 확인
대시보드에서 세션·퍼널·이벤트 분석 결과 시각화

Step 1: 사전 준비 — 앱 등록 & 키 발급

SDK를 사용하려면 먼저 콘솔에서 앱을 등록하고 인증 정보를 확인해야 합니다.

콘솔 앱 관리 페이지로 이동
콘솔 좌측 메뉴에서 앱 관리를 클릭합니다.
새 앱 등록
"앱 등록" 버튼을 클릭하고, 웹사이트 이름과 URL을 입력합니다. 모바일 앱이 없어도 웹 전용 프로젝트로 등록할 수 있습니다.
App ID와 API Key 확인
등록된 앱의 상세 페이지에서 API 키 버튼을 클릭하여 아래 2가지 값을 확인합니다.
항목확인 위치예시
App ID 콘솔 > 앱 관리 > 앱 상세 42
API Key 콘솔 > 앱 관리 > API 키 ak_live_abc123def456...
앱 관리에서 API 키 확인
📸

캡처 대상: 콘솔 > 앱 관리 > API 키 모달
App ID와 API Key가 표시된 화면을 캡처해주세요.

/images/docs/console/user-journey-app-apikey.png

Step 2: SDK 설치 & 초기화

웹 페이지에 SDK 스크립트를 추가하고 초기화합니다. 초기화 시 자동으로 세션이 생성됩니다.

2-1. SDK 스크립트 추가

HTML 파일의 </body> 태그 직전에 SDK를 로드합니다.

HTML
<!-- FINGERPUSH.LINK SDK -->
<script src="https://fpl-stage-console.kissoft.biz/sdk/v1/fplink-tracker.js"></script>

2-2. SDK 초기화

SDK 로드 후 FPLinkTracker 인스턴스를 생성합니다.

JavaScript
var fplinkTracker = new FPLinkTracker({
    baseUrl: 'https://fpl-stage-console.kissoft.biz',       // 서비스 도메인
    appId: '42',                         // ← Step 1에서 확인한 App ID
    apiKey: 'ak_live_abc123def456',      // ← Step 1에서 확인한 API Key
    platform: 'web',                     // 고정값
    debug: true                          // 개발 중에만 true (콘솔 로그 출력)
});
💡 autoInit 옵션
기본적으로 autoInit: true가 설정되어 있어서 인스턴스 생성 즉시 서버에 세션이 자동 생성됩니다. 수동으로 초기화하려면 autoInit: false로 설정 후 fplinkTracker.init()을 직접 호출하세요.

2-3. 초기화 확인

브라우저 개발자 도구(F12)의 Console 탭에서 아래 메시지가 출력되면 성공입니다.

Console 예상 출력
[FPLinkTracker] Initializing User Journey Tracker...
[FPLinkTracker] Creating new session...
[FPLinkTracker] Session created: { sessionId: "a1b2c3d4-...", ... }
[FPLinkTracker] SDK initialized successfully

세션 ID를 코드에서 확인하려면:

HTML — 세션 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://fpl-stage-console.kissoft.biz/sdk/v1/fplink-tracker.js"></script>
    <script>
    // SDK 초기화
    var fplinkTracker = new FPLinkTracker({
        baseUrl: 'https://fpl-stage-console.kissoft.biz',
        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>
⚠️ 예제 실행 시 Event tracking failed 에러
위 예제를 복사하여 실행하면 콘솔에 Event tracking failed (non-critical): TypeError: Failed to fetch가 나타날 수 있습니다. 이는 YOUR_APP_IDYOUR_API_KEY가 실제 값이 아니기 때문이며, 세션 생성 자체는 정상 동작합니다. 실제 App ID와 API Key로 교체하면 에러가 사라집니다.

Step 3: 사용자 행동 이벤트 추적

사용자의 행동(클릭, 상품 조회, 장바구니 등)을 이벤트로 기록합니다. 페이지뷰는 SDK가 자동으로 추적하므로 별도 코드가 필요 없습니다.

3-1. 자동 추적 (페이지뷰 & 이탈)

SDK 초기화 시 다음 2가지 이벤트가 자동으로 전송됩니다. 별도 코드를 작성할 필요 없습니다.

이벤트시점자동 수집 데이터
page_view SDK 초기화 완료 직후 url — 현재 페이지 URL (window.location.href)
title — 페이지 제목 (document.title)
referrer — 유입 경로 (document.referrer)
page_unload 페이지 이탈 시 (beforeunload) duration — 페이지 체류 시간 (ms)

3-2. 커스텀 이벤트 추적

trackEvent(eventType, eventData) 메서드로 원하는 사용자 행동을 기록합니다. 이벤트는 비동기로 전송되며, 전송 실패가 사용자 경험에 영향을 주지 않습니다.

JavaScript — 버튼 클릭 추적
document.getElementById('signupBtn').addEventListener('click', function() {
    fplinkTracker.trackEvent('button_click', {
        buttonId: 'signupBtn',
        label: '회원가입'
    });
});
JavaScript — 상품 조회 추적
// 상품 상세 페이지 진입 시
fplinkTracker.trackEvent('product_view', {
    productId: 'PROD-001',
    productName: '프리미엄 러닝화',
    price: 29900,
    category: '신발'
});
JavaScript — 장바구니 담기 추적
document.getElementById('cartBtn').addEventListener('click', function() {
    fplinkTracker.trackEvent('add_to_cart', {
        productId: 'PROD-001',
        productName: '프리미엄 러닝화',
        price: 29900,
        quantity: 1
    });
});

3-3. trackEvent API 명세

파라미터타입필수설명
eventType String 이벤트 유형 (예: button_click, product_view, add_to_cart)
eventData Object 이벤트 속성 (자유 형식 JSON 객체)
💡 이벤트 이름 규칙
이벤트 이름은 자유롭게 지정할 수 있습니다. 일관된 네이밍을 위해 snake_case를 권장합니다. 예: page_view, button_click, form_submit, video_play

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": "서울"}

③ 권장 데이터 구조 예시

JavaScript — 권장 구조 (Good ✅)
// 문자열 값 → 콘솔에서 필터로 검색 가능
fplinkTracker.trackEvent('purchase', {
    product_id: 'PROD-001',       // ✅ 문자열 → 필터 가능
    product_name: '프리미엄 러닝화', // ✅ 문자열 → 필터 가능
    category: 'shoes',             // ✅ 문자열 → 필터 가능
    currency: 'KRW',               // ✅ 문자열 → 필터 가능
    price: 29900,                  // 숫자 → 집계용 (필터 불가)
    quantity: 1                    // 숫자 → 집계용 (필터 불가)
});
JavaScript — 피해야 할 구조 (Bad ❌)
// 중첩 객체/배열 → 필터에서 완전히 무시됨
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

⑤ 필터 갱신 주기

⏰ 필터 반영 시점
이벤트 데이터의 필터는 매일 1회 배치 작업으로 갱신됩니다. 새로운 이벤트를 전송해도 즉시 콘솔 필터에 나타나지 않으며, 다음 배치 실행 후에 반영됩니다.
  • 분석 범위: 최근 90일 이내 데이터
  • 각 키당 최대 50개 값 (발생 빈도순)
  • 90일이 지난 데이터의 필터 값은 자동으로 제거됩니다

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을 클릭하고 목적 페이지에 도착했을 때 기록합니다.

JavaScript
// 랜딩페이지 로드 시
fplinkTracker.trackDeepLinkResolved();
// 또는 범용 메서드 사용
// fplinkTracker.trackFunnelEvent('DEEP_LINK_RESOLVED');

4-2. 콘텐츠 확인 (CONTENT_VIEWED)

사용자가 핵심 콘텐츠를 확인한 시점에 기록합니다. (예: 상품 상세 열람, 영상 재생 시작)

JavaScript
// 상품 상세 정보를 확인한 시점
fplinkTracker.trackContentViewed();

4-3. 행동 수행 (ACTION_TAKEN)

사용자가 전환에 가까운 행동을 수행한 시점에 기록합니다. (예: 장바구니 담기, 회원가입 폼 작성)

JavaScript
// 장바구니에 상품을 담은 시점
fplinkTracker.trackActionTaken();

4-4. 목표 달성 (GOAL_COMPLETED)

최종 전환 목표가 달성된 시점에 기록합니다.

JavaScript — 구매 완료
// 방법 A: trackGoal (목표 유형 + 금액)
fplinkTracker.trackGoal('purchase', 29900, 'KRW');

// 방법 B: 편의 메서드
fplinkTracker.trackPurchase(29900, 'KRW');
💡 상품 상세 정보를 함께 기록하려면
trackGoal()은 목표 유형·금액·통화만 전달합니다. 상품코드, 카테고리 등 상세 데이터는 trackEvent()를 함께 호출하세요.
JavaScript — 구매 완료 + 상세 상품 정보
// 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'
});
JavaScript — 복수 상품 구매
// 총 결제 금액으로 퍼널 목표 기록
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
});
JavaScript — 회원가입 완료
// 방법 A: trackGoal
fplinkTracker.trackGoal('signup', 1);

// 방법 B: 편의 메서드
fplinkTracker.trackSignup();
JavaScript — 커스텀 전환
// 뉴스레터 구독, 앱 다운로드 등 자유 전환
fplinkTracker.trackConversion('newsletter_signup', 1);

4-5. 전환 목표 사전 설정 (GoalType)

콘솔에서 URL/캠페인에 전환 목표를 미리 설정해두면, SDK가 세션 생성 시 goalType을 자동으로 받아옵니다. trackGoal() 호출 시 goalType을 생략할 수 있습니다.

JavaScript — 자동 goalType 활용
// 콘솔에서 이 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-1. 사용자 연결 (linkUser)

사용자가 로그인하면 linkUser()를 호출하여 세션에 사용자 ID를 연결합니다.

JavaScript
// 로그인 성공 후
fplinkTracker.linkUser('user-12345');

// 이메일, UUID 등 다양한 형식 지원
fplinkTracker.linkUser('user@example.com');

5-2. 외부 사용자 ID (setExternalUserId)

자사 서비스의 사용자 ID를 설정하면, 퍼널 이벤트 전송 시 자동으로 포함되어 콘솔에서 개별 사용자별 여정을 조회할 수 있습니다.

JavaScript
// 로그인 후 또는 SDK 초기화 직후
fplinkTracker.setExternalUserId('member-9876');

// 이후 퍼널 이벤트에 자동 포함됨
fplinkTracker.trackGoal('purchase', 29900, 'KRW');
// → 서버에 externalUserId: 'member-9876'가 함께 전송
⚠️ linkUser vs setExternalUserId 차이
linkUser()setExternalUserId()
동작서버 API 호출 → DB에 세션-사용자 영구 매핑SDK 내부 변수에만 저장 (서버 호출 없음)
적용 범위세션 전체 (세션이 살아있는 동안 유지)퍼널 이벤트 전송 시 payload에 포함
용도크로스 플랫폼·멀티 디바이스 통합 분석퍼널 단계별 사용자 식별·필터링
페이지 새로고침서버에 저장되어 유지됨SDK 메모리에만 있어 초기화 필요
💡 함께 사용하기
두 메서드는 목적이 다르므로 함께 사용하는 것을 권장합니다. linkUser()로 세션에 사용자를 영구 연결하고, setExternalUserId()로 퍼널 이벤트에 사용자 ID를 포함시키세요.
JavaScript — 권장 패턴
// 로그인 완료 시 두 메서드 모두 호출
function onLoginSuccess(userId) {
    // 1) 세션에 사용자 영구 연결 (서버 저장)
    fplinkTracker.linkUser(userId);

    // 2) 퍼널 이벤트에 사용자 ID 포함
    fplinkTracker.setExternalUserId(userId);
}

5-3. 플랫폼 전환 기록 (recordTransition)

웹에서 앱으로 전환되는 시점에 기록합니다. 이 데이터는 콘솔의 사용자 여정 분석에서 플랫폼 전환 경로로 시각화됩니다.

JavaScript
// 웹 → iOS 앱으로 전환 (딥링크 실행 시)
fplinkTracker.recordTransition('ios', 'deeplink', {
    targetUrl: 'myapp://product/123'
});

// 웹 → Android 앱으로 전환
fplinkTracker.recordTransition('android', 'deeplink');
파라미터타입필수설명
toPlatform String 전환 대상 플랫폼 (ios, android, web)
transitionType String 전환 유형 (deeplink, qr_scan, manual)
options Object 추가 정보 (targetUrl 등)

Step 6: 콘솔에서 결과 확인

SDK로 수집된 데이터는 콘솔 대시보드에서 다양한 관점으로 분석할 수 있습니다.

6-1. URL별 사용자 여정

콘솔 > URL 관리 > URL 선택 > 사용자 여정 분석 탭에서 해당 URL을 통해 유입된 세션을 조회합니다.

URL별 사용자 여정 분석
📸

캡처 대상: 콘솔 > URL 관리 > [URL선택] > 사용자 여정 분석 탭
세션 목록, 통계 카드(총 세션, 전환 세션, 전환율)가 표시된 화면을 캡처해주세요.

/images/docs/console/user-journey-url-sessions.png

통계 카드 해석

카드설명
총 세션해당 URL을 통해 생성된 전체 세션 수
전환 세션GOAL_COMPLETED 단계에 도달한 세션 수
전환율전환 세션 / 총 세션 × 100 (%)

필터 옵션

필터옵션설명
플랫폼 전체, 웹, iOS, Android 세션이 시작된 플랫폼별 필터링
세션 타입 전체, 단일 플랫폼, 크로스 플랫폼 단일 디바이스 vs 플랫폼 전환이 있는 세션
기간 시작일 ~ 종료일 조회 기간 설정

6-2. 캠페인별 사용자 여정

콘솔 > 캠페인 > 캠페인 선택 > 사용자 여정 분석 탭에서 캠페인에 포함된 모든 URL의 세션을 통합 조회합니다.

6-3. 데이터 분석 메뉴

콘솔 좌측 데이터 분석 메뉴에서 더 넓은 범위의 분석이 가능합니다.

메뉴용도
사용자 여정 분석전체 세션 타임라인, 플랫폼 분포, 크로스 플랫폼 전환 경로
사용자 분석외부 사용자 ID 기반 개별 사용자 행동 분석
이벤트 로그trackEvent()로 수집된 원시 이벤트 로그 조회
이벤트 분석이벤트 추이, 플랫폼별 비율, 비교 분석
딥링크 퍼널5단계 퍼널 시각화 (단계별 전환율, 이탈률)
딥링크 퍼널 분석
📸

캡처 대상: 데이터분석 > 딥링크 퍼널
웹 퍼널 5단계 차트(링크 클릭 → 페이지 도달 → 콘텐츠 조회 → 액션 수행 → 목표 완료)가 표시된 화면을 캡처해주세요.

/images/docs/console/user-journey-funnel.png

실전 예제: 이커머스 랜딩페이지

프로모션 단축 URL → 상품 랜딩페이지 → 구매까지 전체 여정을 추적하는 완전한 HTML 예제입니다. 아래 코드를 복사하여 바로 테스트할 수 있습니다.

💡 빠른 시작 데모
브라우저에서 바로 실행해볼 수 있는 인터랙티브 데모 페이지를 제공합니다. Quick Start 데모 페이지 열기 →
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://fpl-stage-console.kissoft.biz/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 초기화 ═══════════════════
    var fplinkTracker = new FPLinkTracker({
        baseUrl: 'https://fpl-stage-console.kissoft.biz',
        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', {
            productId: 'PROD-001',
            productName: '프리미엄 러닝화',
            price: 29900
        });
        log('📡 product_view 이벤트 전송');
    });

    // ═══════ 3. 상세 정보 보기 (퍼널 3단계) ═══════
    document.getElementById('detailBtn').addEventListener('click', function() {
        fplinkTracker.trackContentViewed();
        log('📡 CONTENT_VIEWED — 상세 정보 확인');

        fplinkTracker.trackEvent('product_detail', {
            productId: 'PROD-001',
            section: 'spec'
        });
        alert('상세 사양, 리뷰, 사이즈 가이드를 확인했습니다.');
    });

    // ═══════ 4. 장바구니 담기 (퍼널 4단계) ══════
    document.getElementById('cartBtn').addEventListener('click', function() {
        fplinkTracker.trackActionTaken();
        log('📡 ACTION_TAKEN — 장바구니 담기');

        fplinkTracker.trackEvent('add_to_cart', {
            productId: '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', {
            productId: '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)
💡 퍼널 + 이벤트를 함께 기록하는 이유
퍼널 단계(trackContentViewed() 등)는 대시보드의 퍼널 전환율을 계산하는 데 사용됩니다. 이벤트(trackEvent())는 상세 속성(상품명, 금액 등)을 포함한 세부 행동 로그로 활용됩니다. 두 가지를 함께 기록하면 퍼널 분석과 상세 이벤트 분석을 모두 수행할 수 있습니다.

트러블슈팅 & FAQ

세션이 생성되지 않아요

원인해결 방법
App ID 또는 API Key 오류 콘솔 앱 관리에서 값을 다시 확인하세요. appId는 숫자, apiKeyak_live_로 시작합니다.
CORS 오류 CORS(Cross-Origin Resource Sharing)란? 브라우저는 보안을 위해 현재 페이지의 도메인과 다른 도메인으로 API 요청을 보낼 때 자동으로 차단합니다. 예를 들어 https://mysite.com 페이지에서 https://fplink.net/api/...로 요청하면 서버가 "이 도메인의 요청을 허용한다"고 응답해야만 브라우저가 데이터를 전달합니다.

FPLink Web SDK API는 모든 도메인에서의 요청을 허용하도록 서버에 설정되어 있으므로, 정상적인 경우 CORS 오류가 발생하지 않습니다. 만약 CORS 에러가 보인다면 다음을 확인하세요:
① API 주소 오류 — SDK 엔드포인트(/api/v1/sdk/)가 아닌 다른 경로로 요청하고 있지 않은지 확인하세요.
② 네트워크/프록시 차단 — 사내 방화벽이나 프록시가 외부 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/ 요청의 상태 코드를 확인하세요.
애드온 미구독 사용자 여정 분석 애드온이 활성화되어 있는지 콘솔 설정에서 확인하세요.

디버그 모드 활용

SDK 초기화 시 debug: true를 설정하면 모든 API 호출의 요청/응답이 브라우저 Console에 출력됩니다. 운영 배포 시에는 반드시 debug: false로 변경하거나 옵션을 제거하세요.

디버그 모드 설정
var fplinkTracker = new FPLinkTracker({
    // ... 기본 설정 ...
    debug: true   // 개발 시 true → 운영 시 false 또는 제거
});

세션 수동 초기화

세션을 강제로 새로 생성하려면 clearSession()init()을 호출합니다.

JavaScript
// 기존 세션 삭제
fplinkTracker.clearSession();

// 새 세션 생성
fplinkTracker.init().then(function() {
    console.log('새 세션:', fplinkTracker.getSessionId());
});

SDK API 요약 레퍼런스

이 가이드에서 사용한 주요 메서드를 한눈에 정리합니다.

세션 관리

메서드설명
init()SDK 초기화 & 세션 생성/복원 (Promise)
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)GOAL_COMPLETED
trackPurchase(amount, currency)GOAL_COMPLETED (purchase)
trackSignup()GOAL_COMPLETED (signup)
trackConversion(name, value, currency)GOAL_COMPLETED (커스텀)

사용자 식별

메서드설명
linkUser(userId)로그인 사용자를 세션에 연결
setExternalUserId(userId)외부 사용자 ID 설정 (이벤트에 자동 포함)
getExternalUserId()현재 설정된 외부 사용자 ID 조회
setGoalType(goalType)전환 목표 유형 수동 설정
getGoalType()현재 설정된 전환 목표 조회
recordTransition(platform, type, opts)플랫폼 전환 기록
💡 더 자세한 정보
SDK의 전체 API 레퍼런스는 Web SDK API 가이드를 참고하세요. 모바일 네이티브 앱 연동은 모바일 SDK 가이드를 참고하세요.