SocialHub.AI
개발자 센터 · 웹 추적

자신의 사이트에서 사용자 행동을 추적하세요.

마케팅 또는 전자상거래 사이트에 퍼스트파티 비콘 하나만 설치하면 해당 페이지의 조회수가 이메일, 로열티 포털, 앱과 동일한 회원 행동 타임라인에 반영됩니다. 키나 종속성 없이, 몇 줄의 바닐라 자바스크립트로 공개 엔드포인트에 데이터를 전송하기만 하면 됩니다. Flash은 서버 측에서 기기, 지역 및 봇 감지 정보를 처리합니다.

01 — 작동 방식

호스팅된 한 줄 또는 자체 포함된 코드 조각

호스팅된 트래커를 스크립트 태그 하나로 추가하거나, 외부 종속성 없이 사용하려면 자체 포함된 스니펫을 붙여넣으세요. 어느 방법이든 식별자를 생성하고 개인정보 보호 신호를 준수합니다. POST페이지 조회수를 하나의 엔드포인트로 변환:

POST https://flash.socialhub.ai/api/v1/tracking/pageview

클라이언트 비트를 보냅니다.

URL, 제목, 리퍼러, ID, 화면, 언어, 시간대, UTM — 그게 전부입니다.

Flash는 서버 측을 강화합니다.

장치, OS 및 브라우저는 사용자 에이전트에서 구문 분석됩니다. IP의 국가; 봇이 감지되고 플래그가 지정됩니다. 이에 대해 클라이언트를 신뢰할 필요는 없습니다.

항상 204를 반환합니다.

봇, GPC, 잘못된 형식 또는 승인 여부와 관계없이 엔드포인트는 아무런 메시지도 표시하지 않습니다. 추적 과정에서 페이지에 오류가 발생하는 경우는 절대 없습니다.

자체 도메인에서는 익명으로 처리됩니다. 사이트에 Flash 세션 쿠키가 없으므로 페이지 조회수는 알려진 회원이 아닌 직접 생성한 anonymous_id에 연결됩니다. 회원 정보는 Flash 소유 플랫폼(로열티 포털 및 앱 내 회원 센터)에서 세션을 통해 회원을 식별하여 얻습니다. 방문자의 사이트 내 행동이 최소한 자신의 세션 전반에 걸쳐 일관되도록 일관된 anonymous_id를 사용하세요.

02 - 설치

접속 방법은 두 가지입니다. YOUR_TEAM_ID을 설정하면 바로 접속할 수 있습니다.

추천

옵션 A · 호스팅 — 한 줄

</body> 앞에 스크립트 태그 하나를 삭제하세요. 단일 페이지 앱 경로 변경 사항을 자동 추적하고 window.flashTrack()을 노출합니다. 다른 연결 항목은 없습니다.

인덱스.html
<!-- SocialHub web tracking — one line, before </body> -->
<script src="https://flash.socialhub.ai/sdk/flash-tracker.js"
        data-team-id="YOUR_TEAM_ID" defer></script>
↓ flash-tracker.js 다운로드소스 보기 ↗종속성 없음 · 원하시면 자체 소스에서 호스팅 가능

옵션 B · 인라인 — 외부 스크립트 없음

외부 요청이 필요하지 않습니까(엄격한 CSP 또는 자체 번들 내부의 코드)? 대신 이 자체 포함된 코드 조각을 붙여넣으세요. window.shTrack()를 노출합니다. 단일 페이지 앱에서 각 경로가 변경된 후에 이를 호출합니다.

인덱스.html
<!-- SocialHub web tracking — paste before </body> on every page -->
<script>
(function () {
  var TEAM_ID = "YOUR_TEAM_ID";                                  // Settings → API
  var ENDPOINT = "https://flash.socialhub.ai/api/v1/tracking/pageview";

  // Honor Global Privacy Control / Do Not Track — no signal sent.
  if (navigator.globalPrivacyControl === true || navigator.doNotTrack === "1") return;

  function uid() {
    return (window.crypto && crypto.randomUUID)
      ? crypto.randomUUID()
      : (Date.now() + "-" + Math.random().toString(16).slice(2));
  }
  function persist(store, key) {
    try { var v = store.getItem(key); if (!v) { v = uid(); store.setItem(key, v); } return v; }
    catch (e) { return uid(); }
  }
  function utm() {
    var p = new URLSearchParams(location.search), o = {};
    ["source", "medium", "campaign", "term", "content"].forEach(function (n) {
      var val = p.get("utm_" + n); if (val) o[n] = val;
    });
    return Object.keys(o).length ? o : undefined;
  }
  function track() {
    var body = JSON.stringify({
      v: 1,
      page_url: location.href,
      page_title: document.title,
      referrer: document.referrer || undefined,
      anonymous_id: persist(localStorage, "sh_anon"),       // stable per browser
      session_id: persist(sessionStorage, "sh_session"),    // resets per tab session
      team_id: TEAM_ID,
      utm: utm(),
      screen: screen.width + "x" + screen.height,
      language: navigator.language,
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
      timestamp: Date.now()
    });
    try {
      if (navigator.sendBeacon) navigator.sendBeacon(ENDPOINT, body);
      else fetch(ENDPOINT, { method: "POST", body: body, keepalive: true }).catch(function () {});
    } catch (e) { /* never break the page */ }
  }

  window.shTrack = track;   // for SPAs: call window.shTrack() after each route change
  track();                  // initial page view
})();
</script>
spa-router.js
// Single-page apps: after each client-side route change
router.afterEach(function () { window.shTrack && window.shTrack(); });
03 — 페이로드 계약

비콘 본체

application/json (또는 sendBeacon을 통해 일반 string)을 전송하세요. 4KB를 초과하거나 유효성 검사에 실패한 데이터는 아무런 경고 없이 삭제됩니다.

필드유형메모
vnumber스키마 버전. 항상 1입니다.
page_urlstring페이지의 전체 URL(≤ 2048) 필수의.
page_titlestring?문서 제목 (500자 이하)
referrerstring?document.referrer (≤ 2048).
anonymous_idstring생성한 안정적인 브라우저별 ID(≤ 36). 필수의.
session_idstring세션별로 생성하는 ID(최대 36자). 필수 항목입니다.
team_idstringSocialHub 팀 ID(36 이하) — 브랜드를 식별합니다. 필수의.
utmobject?string 쿼리에서 { source, medium, campaign, term, content }를 파싱합니다.
screenstring?"1920x1080".
languagestring?navigator.language
timezonestring?IANA tz, 예: America/Los_Angeles.
timestampnumber클라이언트 시대 ms. 필수의.
04 — 보호

스푸핑 트래픽에 대한 저항력 강화

team_id은 페이지 소스에 존재하며, 다른 분석 ID와 마찬가지로 공개되어 있습니다. 따라서 엔드포인트는 서버 측에서 조용히 자체 방어 기능을 수행합니다(항상 204을 응답하므로 공격자가 탐색할 수 있는 피드백이 없습니다).

기준 속도 제한 · 상시 작동

모든 팀은 별도의 설정 없이 기본적으로 보호됩니다. 엔드포인트는 하나의 소스가 전송할 수 있는 비콘 수를 제한하므로, 스크랩된 team_id로 인해 분석 데이터가 과부하되거나 오염되는 것을 방지합니다. 또한 장애 발생 시에도 실제 트래픽이 중단되지 않도록 설계되어 있습니다.

출처 허용 목록 · 선택 사항

설정 → 추적 보호에서 허용되는 비콘을 자체 도메인으로 제한할 수 있으며, 적용하기 전에 모니터링 미리 보기를 통해 false 양성 여부를 확인할 수 있습니다. 이렇게 하면 다른 사이트에서 브라우저에서 SDK을 사용하는 것을 차단할 수 있습니다.

제한 사항에 대해 솔직하게 알려주세요.

속도 제한 및 허용 목록은 보안 수준을 높이고 피해를 제한하지만, 키리스 클라이언트는 악의적인 스크립트가 요청을 위조하는 것을 완전히 막을 수는 없습니다. 민감한 데이터 수집의 경우, 인증된 API을 통해 서버 간 전송을 사용하는 것이 좋습니다.

하류에서 깨끗한 수치 유지

악용 방지 기능은 데이터가 저장되기 전에 실행되므로 필터링된 트래픽은 회원 타임라인, 세그먼트 또는 대시보드에 도달하지 않습니다. 또한 추적 보호 페이지에서 차단된 트래픽의 양을 확인할 수 있습니다.

05 - 개인정보 보호

방문자를 고려한 설계

GPC 및 추적 금지

이 코드 조각은 navigator.globalPrivacyControl 및 navigator.doNotTrack을 확인하고 둘 중 하나라도 설정된 경우 아무것도 전송하지 않습니다. 이 안전장치를 유지하세요.

원시 PII 없음

식별자와 페이지 컨텍스트만 전송합니다. 비콘에는 이름, 이메일 또는 양식 콘텐츠가 전송되지 않습니다. 회원 신원은 사이트가 아닌 Flash 표면에서 확인됩니다.

먼저 동의 배너를 확인하세요.

사이트에서 동의 관리자를 사용하는 경우 동의 뒤에 스니펫을 지정하세요. 방문자가 분석을 수락한 후에만 추적기를 호출하세요.

봇 필터링됨

서버 측 봇 탐지는 사람이 아닌 트래픽에 플래그를 지정하여 회원 타임라인이나 통계를 오염시키지 않습니다.

나머지 여정을 기록하세요

웹은 네 가지 플랫폼 중 하나입니다. 이메일, 로열티 포털, 앱이 동일한 회원 타임라인을 어떻게 보여주는지 확인해 보세요.