BootConfig

Model used for boot.

See ChannelIO.boot

FieldDescriptionEtc.
pluginKeyKey generated by ChannelIORequired
memberIdUser's unique id.
Logged in customers should always have this value filled in
memberHashA hash value that verifies the provided secret key and member id
profileUsers' profile values
languageAn initial language that user will use. It only takes effect when the user is being created. If user is already created, this option is ignored.
unsubscribeEmailFlag for receive marketing message by email

If user's unsubscribeEmail value is already set to true, you can't update by boot
unsubscribeTextingFlag for receive marketing message sms of lms

If user's unsubscribeTexting value is already set to true, you can't update by boot
trackDefaultEventFlag for send default events like PageView
hidePopupFlag for hiding in-app popup like marketing messages.

If you want to implemets custom popup, use onPopupDataReceived delegate
channelButtonOptionOption that change default channel button position, margins.
bubbleOptionOption that change default bubble popup's position, margins.
appearancePlugin’s initial appearance settings

- 'light', 'dark': use dark/light theme
- 'system': follow system theme
iOS Only(> 10.1.0)

❗️

Do not recommend to use a predictable value for memberId

Because memberId is a unique value that we use to identify users, we do not recommend to use predictable values such as numerical combination, email address, user name and etc. It may cause privacy and security issues. We recommend to use higher than 256 bits hash value.

Profile profile = Profile.create()
    .setProperty(PROFILE_KEY, PROFILE_VALUE)
    .setName(USER_NAME);

ChannelButtonOption buttonOption = new ChannelButtonOption(
  ChannelButtonPosition.LEFT, 
  16, 
  23
);

BubbleOption bubbleOption = new BubbleOption(BubblePosition.TOP, 30);

BootConfig bootConfig = BootConfig.create(YOUR_PLUGIN_KEY)
    .setMemberId(MEMBER_ID)
    .setMemberHash(MEMBER_HASH)
    .setProfile(profile)
    .setLanguage(Language.ENGLISH)
    .setUnsubscribeEmail(true)
    .setUnsubscribeTexting(true)
    .setTrackDefaultEvent(false)
    .setHidePopup(true)
    .setChannelButtonOption(buttonOption)
    .setBubbleOption(bubbleOption);

ChannelIO.boot(bootConfig);
let profile = Profile()
  .set(name: USER_NAME)
  .set(propertyKey: KEY, value: VALUE)

let buttonOption = ChannelButtonOption.init(
  position: .left,
  xMargin: 16,
  yMargin: 23
)

let bubbleOption = BubbleOption(
  position: .top, // .top or .bottom
  yMargin: 0
)

let bootConfig = BootConfig.init(
  pluginKey: PLUGIN_KEY,
  memberId: MEMBER_ID,
  memberHash: MEMBER_HASH,
  profile: profile,
  channelButtonOption: buttonOption,
  bubbleOption: bubbleOption,
  hidePopup: false,
  trackDefaultEvent: true,
  language: .english,
  unsubscribeEmail: false,
  unsubscribeTexting: false
)

ChannelIO.boot(with: bootConfig)
Profile *profile = [[Profile alloc] init];
[profile setWithName:USER_NAME];
[profile setWithPropertyKey:KEY value:VALUE];

ChannelButtonOption *buttonOption = [[ChannelButtonOption alloc]
                                     initWithPosition:ChannelButtonPositionLeft
                                     xMargin:16
                                     yMargin:23
                                     ];

BubbleOption *bubbleOption = [[BubbleOption alloc] init];
[bubbleOption setPosition:BubblePostitionTop]; // BubblePostitionTop or BubblePostitionBottom
[bubbleOption setYMargin:0];

BootConfig *bootConfig = [[BootConfig alloc] init];
[bootConfig setWithMemberId:MEMBER_ID];
[bootConfig setMemberHash:MEMBER_HASH];
[bootConfig setProfile:profile];
[bootConfig setLanguage:LanguageOptionEnglish];
[bootConfig setWithUnsubscribeEmail:NO];
[bootConfig setWithUnsubscribeTexting:NO];
[bootConfig setTrackDefaultEvent:YES];
[bootConfig setHidePopup:NO];
[bootConfig setChannelButtonOption:buttonOption];
[bootConfig setBubbleOption:bubbleOption];
[bootConfig setUnsubscribeEmail:NO];
[bootConfig setUnsubscribeTexting:NO];

[ChannelIO bootWith:bootConfig completion:^(BootStatus status, User * user) { }];
const config = {
  "pluginKey": YOUR_PLUGIN_KEY,
  "memberId": MEMBER_ID,
  "memberHash": MEMBER_HASH,
  "profile": {
    "name": NAME,
    "email": EMAIL,
    "mobileNumber": "+~~~",
    "avatarUrl": AVATAR_URL,
    OTHER_KEY: OTHER_VALUE,
  },
  "language": LANGUAGE, // "en", "ko", "jp"
  "unsubscribeEmail": BOOLEAN,
  "unsubscribeTexting": BOOLEAN,
  "trackDefaultEvent": BOOLEAN,
  "hidePopup": BOOLEAN,
  "channelButtonOption": {
    "xMargin": 16,
    "yMargin": 16,
    "position": POSITION,  // "left", "right"
  },
  "bubbleOption": {
    "yMargin": 30,
    "position" POSITION,   // "top", "bottom"
  }
}

ChannelIO.boot(config).then((result) => {
  // result.status
  // result.user
})

Language

Language for initializing users for BootConfig
If user is already created, this option is ignored.

public enum Language {
  KOREAN,
  JAPANESE,
  ENGLISH;
}
@objc public enum LanguageOption: Int {
  case english
  case korean
  case japanese
  case device
}
typedef SWIFT_ENUM(NSInteger, LanguageOption, closed) {
  LanguageOptionEnglish = 0,
  LanguageOptionKorean = 1,
  LanguageOptionJapanese = 2,
  LanguageOptionDevice = 3,
};
// Set language to Korean
"language": "ko"

// Set language to Japanese
"language": "jp"

// Set language to English
"language": "en"

ChannelButtonOption

Option for default button's position.
You can set channel button position left bottom or right bottom by ChannelButtonPosition

// Units of x and y are dp in android.
ChannelButtonOption buttonOption = new ChannelButtonOption(
  ChannelButtonPosition.LEFT, 
  16, 
  23
);
// Units of x and y are pt in iOS.
let buttonOption = ChannelButtonOption.init(
  position: .left,
  xMargin: 16,
  yMargin: 23
)
// Units of x and y are pt in iOS.
ChannelButtonOption *buttonOption = [[ChannelButtonOption alloc]
                                     initWithPosition:ChannelButtonPositionLeft
                                     xMargin:16
                                     yMargin:23
                                     ];
"channelButtonOption": {
  "xMargin": 16,
  "yMargin": 16,
  "position": POSITION,  // 'left', 'right'
}

BubbleOption

Option for default bubble popup's position.
You can set bubble popup position top or bottom bottom by BubblePosition

// Units of x and y are dp in android.
BubbleOption bubbleOption = new BubbleOption(BubblePosition.TOP, 30);
// Units of x and y are pt in iOS.
let bubbleOption = BubbleOption(
  position: .top, // .top or .bottom
  yMargin: 0
)
// Units of x and y are pt in iOS.
	BubbleOption *bubbleOption = [[BubbleOption alloc] init];
  [bubbleOption setPosition:BubblePostitionTop]; // BubblePostitionTop or BubblePostitionBottom
  [bubbleOption setYMargin:0];
"bubbleOption": {
  "yMargin": 30,
  "position": POSITION,  // 'top', 'bottom'
}

Profile

profile data for boot

Profile profile = Profile.create()
    .setName(NAME)
    .setAvatarUrl(AVATAR_URL)
    .setEmail(EMAIL)
    .setMobileNumber("+xxxx")
    .setProperty(KEY, VALUE);
let profile = Profile()
    .set(name: NAME)
    .set(avatarUrl: AVATAR_URL)
    .set(email: EMAIL)
    .set(mobileNumber: "+xxxx")
    .set(propertyKey: KEY, value: VALUE)
Profile *profile = [[Profile alloc] init];
[profile setWithName:NAME];
[profile setWithAvatarUrl:AVATAR_URL];
[profile setWithEmail:EMAIL];
[profile setWithMobileNumber:@"+xxxx"];
[profile setWithPropertyKey:KEY value:VALUE];
"profile": {
  "name": NAME,
  "email": EMAIL,
  "mobileNumber": "+~~~",
  "avatarUrl": AVATAR_URL,
  OTHER_KEY: OTHER_VALUE,
}

User

Because memberId is a unique value used to identify a user, we do not recommend to use predictable values such as numerical combination, email address, user name and etc. It may cause privacy and security issues. We recommend using 256 bits hash or stronger.

ParameterDescription
idUnique id used by ChannelIO.
memberIdUser's unique id.
nameUser's name.
avatarUrlUser's profile Image url.
profileProfile dictionary to overwrite. Set null to reset. Set null for profile value to reset profile value. Empty map is not allowed.
alertUser's alert count.
tagsTags for user. Data will be overwritten. Max size is 10. Case-insensitive (migrate to lower case)
languageAn initial language that user will use. It only takes effect when the user is being created. If user is already created, this option is ignored.
unsubscribeTextingunsubscribeTexting: Unsubscribe from the user's marketing messages via SMS or LMS.
unsubscribeEmailUnsubscribe from the user's marketing message sent by email.
public class User {
  private String id;
  
  @Nullable
  private String memberId;
  
  @Nullable
  private String name;
  
  @Nullable
  private String avatarUrl;
  
  private int alert;
  
  @Nullable
  private Map<String, Object> profile;
  
  private boolean unsubscribeEmail;
  
  private boolean unsubscribeTexting;
  
  @Nullable
  private List<String> tags;

  private Language language;
}
@objc
public class User: NSObject {
  @objc public let id: String
  @objc public let memberId: String
  @objc public let name: String
  @objc public let avatarUrl: String?
  @objc public let profile: [String : Any]?
  @objc public let alert: Int
  @objc public let tags: [String]?
  @objc public let language: String?
  @objc public let unsubscribeEmail: Bool
  @objc public let unsubscribeTexting: Bool
}
@interface User : NSObject
@property (nonatomic, readonly, copy) NSString * _Nonnull id;
@property (nonatomic, readonly, copy) NSString * _Nonnull memberId;
@property (nonatomic, readonly, copy) NSString * _Nonnull name;
@property (nonatomic, readonly, copy) NSString * _Nullable avatarUrl;
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> * _Nullable profile;
@property (nonatomic, readonly) NSInteger alert;
@property (nonatomic, readonly, copy) NSArray<NSString *> * _Nullable tags;
@property (nonatomic, readonly, copy) NSString * _Nullable language;
@property (nonatomic, readonly) BOOL unsubscribeEmail;
@property (nonatomic, readonly) BOOL unsubscribeTexting;
@end
const user = {
  "id": ID,
  "memberId": MEMBER_ID,
  "name": NAME,
  "avatarUrl": AVATAR_URL,
	"alert": ALERT_COUNT,
  "profile": {
    "name": PROFILE_NAME,
    "mobileNumber": "+~~~",
    "CUSTOM_VALUE_1": "VALUE_1",
    "CUSTOM_VALUE_2": "VALUE_2"
  }
  "unsubscribeEmail": BOOLEAN,}
  "unsubscribeTexting": BOOLEAN,
  "tags": ["1", "2", "3"],
  "language": LANGUAGE
}

PopupData

Data in OnPopupDataReceived
You can render custom in-app popup by this model

public class PopupData {
  @Nullable
  private String chatId;
  
  @Nullable
  private String avatarUrl;
  
  @Nullable
  private String name;
  
  @Nullable
  private String message;
}
@objc
public class PopupData: NSObject {
  @objc public let chatId: String
  @objc public let message: String
  @objc public let name: String
  @objc public let avatarUrl: String
}
@interface PopupData : NSObject
@property (nonatomic, readonly, copy) NSString * _Nonnull chatId;
@property (nonatomic, readonly, copy) NSString * _Nonnull message;
@property (nonatomic, readonly, copy) NSString * _Nonnull name;
@property (nonatomic, readonly, copy) NSString * _Nonnull avatarUrl;
@end
const popupData = {
  "chatId": CHAT_ID,
  "avatarUrl": AVATAR_URL,
  "name": NAME,
  "message": MESSAGE,
}

UserData

Data builder for use updateUser

FieldDescription
languageForce change user's language
tagsTags for user.
Data will be overwritten.
Max size is 10.
Case-insensitive (migrate to lower case)
profileProfile map to overwrite. Set null to reset. Set null for profile value to reset profile value. Empty map is not allowed.
profileOnceMap of profile to be added if there is no each profile values.
unsubscribeEmailUnsubscribe from the user's marketing message sent by email.
unsubscribeTextingUnsubscribe from the user's marketing messages via SMS or LMS.

🚧

Unsubscribe Texting / Email field is available on 10.0.0 or later

Map<String, Object> profileMap = new HashMap<>();

// name
profileMap.put("name", USER_NAME);

// mobileNumber
profileMap.put("mobileNumber", "+~~~");

// email
profileMap.put("email", EMAIL);

// avatar url
profileMap.put("avatarUrl", AVATAR_URL);

// other values
profileMap.put(OTHER_KEY_1, OTHER_VALUE_INT);
profileMap.put(OTHER_KEY_2, OTHER_VALUE_STRING);

UserData userData = new UserData.Builder()
    .setUnsubscribeEmail(false)
    .setUnsubscribeTexting(true)
    .setLanguage(Language.ENGLISH)
    .setProfileMap(profileMap)
    .setProfileOnceMap(null)
    .build();

ChannelIO.updateUser(userData, null);
var profile: [String:Any] = [:]

// name
profile["name"] = USER_NAME
  
// mobileNumber
profile["mobileNumber"] = "+~~~"
  
// email
profile["email"] = EMAIL
  
// avatar url
profile["avatarUrl"] = AVATAR_URL
  
// other
profile[OTHER_KEY] = OTHER_VALUE
  
let userData = UpdateUserParamBuilder
  .with(language: .english)
  .with(profile: profile)
  .build()
    
ChannelIO.updateUser(param: userData) { (error, user) in
  if let user = user, error != nil {
    // success, result data is user
  } else if let error = error {
    // error, see error
  }
}
UpdateUserParamObjcBuilder *builder = [[UpdateUserParamObjcBuilder alloc] init];

// name
[builder withProfileKey:@"name" value:USER_NAME];

// mobileNumber
[builder withProfileKey:@"mobileNumber" value:@"+~~~"];
  
// email
[builder withProfileKey:@"email" value:EMAIL];
  
// avatar url
[builder withProfileKey:@"avatarUrl" value:AVATAR_URL];
  
// other
[builder withProfileKey:@"OTHER_KEY" value:OTHER_VALUE];

[builder withLanguage:LanguageOptionEnglish];

[ChannelIO updateUserWithParam:[builder build] completion:^(NSError * error, User * user) {
  if (user != nil && error == nil) {
    // success, result data is user
  } else (error != nil) {
    // error, see error
  }
}];
const user = {
  "language": LANGUAGE, // "ko", "jp", "en"
  "tags": ["1", "2", "3"],
  "profile": {
    "name": NAME,
    "email": EMAIL,
    "mobileNumber": '+~~~',
    "avatarUrl": AVATAR_URL,
    OTHER_KEY: OTHER_VALUE,
  },
  "profileOnce": {
  },
  "unsubscribeEmail": BOOLEAN,
  "unsubscribeTexting": BOOLEAN,
};

ChannelIO.updateUser(user).then((result) => {
  // result.error
  // result.user
});

BootStatus

Enum for boot result.

public enum BootStatus {
  SUCCESS,
  NOT_INITIALIZED,
  NETWORK_TIMEOUT,
  NOT_AVAILABLE_VERSION,
  SERVICE_UNDER_CONSTRUCTION,
  REQUIRE_PAYMENT,
  ACCESS_DENIED,
  UNKNOWN_ERROR;
}
@objc
public enum BootStatus : Int {
  case success
  case notInitialized
  case networkTimeout
  case notAvailableVersion
  case serviceUnderConstruction
  case requirePayment
  case accessDenied
  case unknown
}
typedef SWIFT_ENUM(NSInteger, BootStatus, closed) {
  BootStatusSuccess = 0,
  BootStatusNotInitialized = 1,
  BootStatusNetworkTimeout = 2,
  BootStatusNotAvailableVersion = 3,
  BootStatusServiceUnderConstruction = 4,
  BootStatusRequirePayment = 5,
  BootStatusAccessDenied = 6,
  BootStatusUnknown = 7,
};
"SUCCESS"
"NOT_INITIALIZED"
"NETWORK_TIMEOUT"
"NOT_AVAILABLE_VERSION"
"SERVICE_UNDER_CONSTRUCTION"
"REQUIRE_PAYMENT"
"ACCESS_DENIED"
"UNKNOWN_ERROR"