이 문서에서는 JavaScript SDK(이하 "SDK")의 초기 설정에 대해 설명합니다.
SDK는 웹 서비스에 채널 버튼을 쉽게 설치할 수 있도록 도와줍니다.

아래 2가지 방법 중 하나를 선택해서 설치해주세요.

옵션1. 직접 로드

일반적인 케이스

웹 서비스가 여러 개의 페이지로 구성되어 있고, 각 페이지를 요청할 때마다 새로운 정적 리소스를 로드한다면 아래의 가이드를 참고합니다.

📘

위와 같은 방식으로 동작하는 웹 서비스를 일반적으로 MPA라고 부릅니다.

자세한 내용은 MPA(Multi-Page Application)를 참고합니다.

1단계: 설치하기

HTML 파일의 <body> 태그 내에 아래 스크립트를 삽입합니다.

<script>
  (function(){var w=window;if(w.ChannelIO){return w.console.error("ChannelIO script included twice.");}var ch=function(){ch.c(arguments);};ch.q=[];ch.c=function(args){ch.q.push(args);};w.ChannelIO=ch;function l(){if(w.ChannelIOInitialized){return;}w.ChannelIOInitialized=true;var s=document.createElement("script");s.type="text/javascript";s.async=true;s.src="https://cdn.channel.io/plugin/ch-plugin-web.js";var x=document.getElementsByTagName("script")[0];if(x.parentNode){x.parentNode.insertBefore(s,x);}}if(document.readyState==="complete"){l();}else{w.addEventListener("DOMContentLoaded",l);w.addEventListener("load",l);}})();
</script>

2단계: 부트하기

boot 메서드를 사용해서 SDK를 초기화합니다. 전달된 인자 객체에 memberId필드가 있는지 여부에 따라 유저 타입이 결정됩니다.

익명 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelIO('boot', {
  "pluginKey": "YOUR_PLUGIN_KEY" // fill your plugin key
});

멤버 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelIO('boot', {
  "pluginKey": "YOUR_PLUGIN_KEY", // fill your plugin key
  "memberId": "USER_MEMBER_ID", // fill user's member id
  "profile": { // fill user's profile
    "name": "USER_NAME", // fill user's name
    "mobileNumber": "USER_MOBILE_NUMBER", // fill user's mobile number
    "landlineNumber": "USER_LANDLINE_NUMBER", // fill user's landline number
    "CUSTOM_VALUE_1": "VALUE_1", // custom property
    "CUSTOM_VALUE_2": "VALUE_2" // custom property
  }
});

웹 서비스와 채널톡의 유저 정보를 통합하기 위해서는 부트 옵션에 몇 가지 추가 정보를 전달해야 합니다. 자세한 내용은 memberIdprofile을 참고합니다.

❗️

보안을 위해서 멤버 해시 사용을 권장합니다.

만약 아이디, 이메일과 같은 예측 가능한 값으로 memberId를 설정할 경우 인증되지 않은 제3자가 memberId를 유추할 수 있습니다. 이 경우 제3자가 고객의 개인 정보나 채팅 내역을 탈취하는 등 보안 위협에 노출될 수 있습니다. 보안을 위해서 멤버 해시를 설정하는 것을 권장합니다.

📘

동일한 사람이라고 판단되는 유저는 합쳐질 수 있습니다

익명 유저 상태에서 멤버 유저로 부트를 하는 경우 채널톡이 같은 유저라고 판단할 수 있는 합리적인 근거가 있다면 채팅 목록과 같은 유저 정보를 합칠 수 있습니다. 더 자세한 내용은 고객정보 통합하기를 참고합니다.

boot API에 대한 더 자세한 설명은 bootboot option을 참고합니다.
SDK에서 제공하는 다양한 메서드는 ChannelIO를 참고합니다.

Single Page Application

웹 서비스가 Single Page Application(SPA)로 구성되었거나 JavaScript의 Class로 SDK를 사용하는 경우, 아래의 예제 코드를 참고합니다.

🚧

클라이언트 사이드(client-side)에서만 SDK를 사용해야 합니다.

SDK는 서버 사이드(server-side)에서 미리 실행될 수 없습니다.

1단계: Service 추가하기

JavaScript를 위한 Service

class ChannelService {
  loadScript() {
    (function(){var w=window;if(w.ChannelIO){return w.console.error("ChannelIO script included twice.");}var ch=function(){ch.c(arguments);};ch.q=[];ch.c=function(args){ch.q.push(args);};w.ChannelIO=ch;function l(){if(w.ChannelIOInitialized){return;}w.ChannelIOInitialized=true;var s=document.createElement("script");s.type="text/javascript";s.async=true;s.src="https://cdn.channel.io/plugin/ch-plugin-web.js";var x=document.getElementsByTagName("script")[0];if(x.parentNode){x.parentNode.insertBefore(s,x);}}if(document.readyState==="complete"){l();}else{w.addEventListener("DOMContentLoaded",l);w.addEventListener("load",l);}})();
  }

  boot(option, callback) {
    window.ChannelIO('boot', option, callback);
  }

  shutdown() {
    window.ChannelIO('shutdown');
  }

  showMessenger() {
    window.ChannelIO('showMessenger');
  }
  
  hideMessenger() {
    window.ChannelIO('hideMessenger');
  }

  openChat(chatId, message) {
    window.ChannelIO('openChat', chatId, message);
  }

  track(eventName, eventProperty) {
    window.ChannelIO('track', eventName, eventProperty);
  }
  
  onShowMessenger(callback) {
    window.ChannelIO('onShowMessenger', callback);
  }
  
  onHideMessenger(callback) {
    window.ChannelIO('onHideMessenger', callback);
  }
  
  onBadgeChanged(callback) {
    window.ChannelIO('onBadgeChanged', callback);
  }

  onChatCreated(callback) {
    window.ChannelIO('onChatCreated', callback);
  }

  onFollowUpChanged(callback) {
    window.ChannelIO('onFollowUpChanged', callback);
  }

  onUrlClicked(callback) {
    window.ChannelIO('onUrlClicked', callback);
  }

  clearCallbacks() {
    window.ChannelIO('clearCallbacks');
  }
  
  updateUser(userInfo, callback) {
    window.ChannelIO('updateUser', userInfo, callback);
  }

  addTags(tags, callback) {
    window.ChannelIO('addTags', tags, callback);
  }

  removeTags(tags, callback) {
    window.ChannelIO('removeTags', tags, callback);
  }

  setPage(page) {
    window.ChannelIO('setPage', page);
  }

  resetPage() {
    window.ChannelIO('resetPage');
  }

  showChannelButton() {
    window.ChannelIO('showChannelButton');
  }

  hideChannelButton() {
    window.ChannelIO('hideChannelButton');
  }

  setAppearance(appearance) {
    window.ChannelIO('setAppearance', appearance);
  }
}

export default new ChannelService();

TypeScript를 위한 Service

declare global {
  interface Window {
    ChannelIO?: IChannelIO;
    ChannelIOInitialized?: boolean;
  }
}

interface IChannelIO {
  c?: (...args: any) => void;
  q?: [methodName: string, ...args: any[]][];
  (...args: any): void;
}

interface BootOption {
  appearance?: string;
  customLauncherSelector?: string;
  hideChannelButtonOnBoot?: boolean;
  hidePopup?: boolean;
  language?: string;
  memberHash?: string;
  memberId?: string;
  pluginKey: string;
  profile?: Profile;
  trackDefaultEvent?: boolean;
  trackUtmSource?: boolean;
  unsubscribe?: boolean;
  unsubscribeEmail?: boolean;
  unsubscribeTexting?: boolean;
  zIndex?: number;
}

interface Callback {
  (error: Error | null, user: CallbackUser | null): void;
}

interface CallbackUser {
  alert: number
  avatarUrl: string;
  id: string;
  language: string;
  memberId: string;
  name?: string;
  profile?: Profile | null;
  tags?: string[] | null;
  unsubscribeEmail: boolean;
  unsubscribeTexting: boolean;
}

interface UpdateUserInfo {
  language?: string;
  profile?: Profile | null;
  profileOnce?: Profile;
  tags?: string[] | null;
  unsubscribeEmail?: boolean;
  unsubscribeTexting?: boolean; 
}

interface Profile {
  [key: string]: string | number | boolean | null | undefined;
}

interface FollowUpProfile {
  name?: string | null;
  mobileNumber?: string | null;
  email?: string | null;
}

interface EventProperty {
  [key: string]: string | number | boolean | null | undefined;
}

type Appearance = 'light' | 'dark' | 'system' | null;

class ChannelService {
  loadScript() {
    (function(){var w=window;if(w.ChannelIO){return w.console.error("ChannelIO script included twice.");}var ch:IChannelIO=function(){ch.c?.(arguments);};ch.q=[];ch.c=function(args){ch.q?.push(args);};w.ChannelIO=ch;function l(){if(w.ChannelIOInitialized){return;}w.ChannelIOInitialized=true;var s=document.createElement("script");s.type="text/javascript";s.async=true;s.src="https://cdn.channel.io/plugin/ch-plugin-web.js";var x=document.getElementsByTagName("script")[0];if(x.parentNode){x.parentNode.insertBefore(s,x);}}if(document.readyState==="complete"){l();}else{w.addEventListener("DOMContentLoaded",l);w.addEventListener("load",l);}})();
  }

  boot(option: BootOption, callback?: Callback) {
    window.ChannelIO?.('boot', option, callback);
  }

  shutdown() {
    window.ChannelIO?.('shutdown');
  }

  showMessenger() {
    window.ChannelIO?.('showMessenger');
  }

  hideMessenger() {
    window.ChannelIO?.('hideMessenger');
  }

  openChat(chatId?: string | number, message?: string) {
    window.ChannelIO?.('openChat', chatId, message);
  }

  track(eventName: string, eventProperty?: EventProperty) {
    window.ChannelIO?.('track', eventName, eventProperty);
  }

  onShowMessenger(callback: () => void) {
    window.ChannelIO?.('onShowMessenger', callback);
  }

  onHideMessenger(callback: () => void) {
    window.ChannelIO?.('onHideMessenger', callback);
  }

  onBadgeChanged(callback: (unread: number, alert: number) => void) {
    window.ChannelIO?.('onBadgeChanged', callback);
  }

  onChatCreated(callback: () => void) {
    window.ChannelIO?.('onChatCreated', callback);
  }

  onFollowUpChanged(callback: (profile: FollowUpProfile) => void) {
    window.ChannelIO?.('onFollowUpChanged', callback);
  }

  onUrlClicked(callback: (url: string) => void) {
    window.ChannelIO?.('onUrlClicked', callback);
  }

  clearCallbacks() {
    window.ChannelIO?.('clearCallbacks');
  }

  updateUser(userInfo: UpdateUserInfo, callback?: Callback) {
    window.ChannelIO?.('updateUser', userInfo, callback);
  }

  addTags(tags: string[], callback?: Callback) {
    window.ChannelIO?.('addTags', tags, callback);
  }

  removeTags(tags: string[], callback?: Callback) {
    window.ChannelIO?.('removeTags', tags, callback);
  }

  setPage(page: string) {
    window.ChannelIO?.('setPage', page);
  }

  resetPage() {
    window.ChannelIO?.('resetPage');
  }

  showChannelButton() {
    window.ChannelIO?.('showChannelButton');
  }

  hideChannelButton() {
    window.ChannelIO?.('hideChannelButton');
  }

  setAppearance(appearance: Appearance) {
    window.ChannelIO?.('setAppearance', appearance);
  }
}

export default new ChannelService();

2단계: 설치하기

1단계에서 추가한 Service를 통해 SDK를 설치할 수 있습니다.

ChannelService.loadScript();

3단계: 부트하기

boot 메서드를 사용해서 SDK를 초기화합니다. 전달된 인자 객체에 memberId필드가 있는지 여부에 따라 유저 타입이 결정됩니다.

익명 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelService.boot({
  "pluginKey": "YOUR_PLUGIN_KEY", // fill your plugin key
});

멤버 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelService.boot({
  "pluginKey": "YOUR_PLUGIN_KEY", // fill your plugin key
  "memberId": "USER_MEMBER_ID", // fill user's member id
  "profile": { // fill user's profile
    "name": "USER_NAME", // fill user's name
    "mobileNumber": "USER_MOBILE_NUMBER", // fill user's mobile number
    "landlineNumber": "USER_LANDLINE_NUMBER", // fill user's landline number
    "customField1": "VALUE_1", // custom property
    "customField2": "VALUE_2" // custom property
  }
});

웹 서비스와 채널톡의 유저 정보를 통합하기 위해서는 부트 옵션에 몇 가지 추가 정보를 전달해야 합니다. 자세한 내용은 memberIdprofile을 참고합니다.

❗️

보안을 위해서 멤버 해시 사용을 권장합니다.

만약 아이디, 이메일과 같은 예측 가능한 값으로 memberId를 설정할 경우 인증되지 않은 제3자가 memberId를 유추할 수 있습니다. 이 경우 제3자가 고객의 개인 정보나 채팅 내역을 탈취하는 등 보안 위협에 노출될 수 있습니다. 보안을 위해서 멤버 해시를 설정하는 것을 권장합니다.

📘

동일한 사람이라고 판단되는 유저는 합쳐질 수 있습니다

익명 유저 상태에서 멤버 유저로 부트를 하는 경우 채널톡이 같은 유저라고 판단할 수 있는 합리적인 근거가 있다면 채팅 목록과 같은 유저 정보를 합칠 수 있습니다. 더 자세한 내용은 고객정보 통합하기를 참고합니다.

🚧

SPA 환경에서 워크플로우와 마케팅 기능을 사용하려면 setPagetrack 메서드가 필요합니다.

SPA 환경에서 URL 변경 시 SDK와 채널톡 서버는 자동으로 이를 인지하지 못합니다. 자세한 내용은 SPA 환경에서 워크플로우와 마케팅 기능을 활용하고 싶어요를 참고합니다.

boot API에 대한 더 자세한 설명은 bootboot option
SDK에서 제공하는 다양한 메서드는 ChannelIO를 참고합니다.

옵션2. NPM 모듈 사용

1단계: 모듈 설치하기

아래의 명령어를 실행하여 @channel.io/channel-web-sdk-loader를 설치합니다.

npm install @channel.io/channel-web-sdk-loader
yarn add @channel.io/channel-web-sdk-loader
pnpm i @channel.io/channel-web-sdk-loader

2단계: SDK 설치하기

1단계에서 추가한 모듈을 통해 SDK를 설치할 수 있습니다.

import * as ChannelService from '@channel.io/channel-web-sdk-loader';

ChannelService.loadScript()

3단계: 부트하기

boot 메서드를 사용해서 SDK를 초기화합니다. 전달된 인자 객체에 memberId필드가 있는지 여부에 따라 유저 타입이 결정됩니다.

익명 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelService.boot({
  "pluginKey": "YOUR_PLUGIN_KEY", // fill your plugin key
});

멤버 유저를 위해 부트를 실행하려면 아래 코드를 참고합니다.

ChannelService.boot({
  "pluginKey": "YOUR_PLUGIN_KEY", // fill your plugin key
  "memberId": "USER_MEMBER_ID", // fill user's member id
  "profile": { // fill user's profile
    "name": "USER_NAME", // fill user's name
    "mobileNumber": "USER_MOBILE_NUMBER", // fill user's mobile number
    "landlineNumber": "USER_LANDLINE_NUMBER", // fill user's landline number
    "customField1": "VALUE_1", // custom property
    "customField2": "VALUE_2" // custom property
});

웹 서비스와 채널톡의 유저 정보를 통합하기 위해서는 부트 옵션에 몇 가지 추가 정보를 전달해야 합니다. 자세한 내용은 memberIdprofile을 참고합니다.

❗️

보안을 위해서 멤버 해시 사용을 권장합니다.

만약 아이디, 이메일과 같은 예측 가능한 값으로 memberId를 설정할 경우 인증되지 않은 제3자가 memberId를 유추할 수 있습니다. 이 경우 제3자가 고객의 개인 정보나 채팅 내역을 탈취하는 등 보안 위협에 노출될 수 있습니다. 보안을 위해서 멤버 해시를 설정하는 것을 권장합니다.

📘

동일한 사람이라고 판단되는 유저는 합쳐질 수 있습니다

익명 유저 상태에서 멤버 유저로 부트를 하는 경우 채널톡이 같은 유저라고 판단할 수 있는 합리적인 근거가 있다면 채팅 목록과 같은 유저 정보를 합칠 수 있습니다. 더 자세한 내용은 고객정보 통합하기를 참고합니다.

NPM 모듈에 대한 더 자세한 설명은 githubnpm
NPM 모듈에서 제공하는 API 문서는 TypeDoc을 참고합니다.