Customization Guide
White-label the VIH Messenger SDK
Reshape the SDK's UI to match your app โ split the chat into category tabs, inject your brand colors, and rename or re-icon the tabs โ all from a single VihConfig you pass at launch. No custom build, no fork.
Available on Android and iOS. Android requires 1.1.3+ (com.github.ViH-Metaverse.ViH_SDK:vih-sdk-staging:1.1.3); iOS requires the matching SwiftPM package. The examples below are Kotlin โ see the iOS section for the Swift equivalents. Assumes you've completed the base integration guide.
โจ What you can customize
| Capability | What it does |
|---|---|
| Split tabs | Replace the single "Chats" tab with category tabs โ Promotions, Transactions, OTP โ each showing only that kind of message. |
| Compose tabs | Pick exactly which tabs appear (Discover, Chats/categories, Settings) and their order. Omit a tab to hide it. |
| Brand colors | Pass your app's hex codes; the SDK's nav, buttons, and headers adopt them. |
| Names & icons | Rename any tab and swap its icon for one of your drawables. |
Everything lives on one optional object, VihConfig, passed to a new startSdk overload. Anything you don't set falls back to the channel's server settings, then the SDK default โ so your config always wins, and a partial config is fine.
๐งฉ The VihConfig object
Build a VihConfig and hand it to startSdk alongside the phone + hashcode. The existing positional startSdk(context, phone, hashcode, โฆ) still works unchanged โ the config overload is purely additive.
import com.vihmessenger.vihchatbot.config.*
import com.vihmessenger.vihchatbot.utils.FloatingButtonView
val config = VihConfig(
theme = VihTheme(
primary = "#0B5FFF", // brand color โ nav, buttons, headers
onPrimary = "#FFFFFF" // text/icons on the brand color
),
navigation = VihNavigation(
tabs = listOf(
VihTab(VihTabId.DISCOVER),
VihTab(VihTabId.PROMO, label = "Offers"),
VihTab(VihTabId.OTP, label = "Codes"),
VihTab(VihTabId.SETTINGS)
),
defaultTab = VihTabId.PROMO
)
)
FloatingButtonView.startSdk(
context = this,
phone = "919876543210",
hashcode = "your-channel-hashcode",
config = config
)
The full shape:
VihConfig(
theme: VihTheme? = null,
navigation: VihNavigation? = null
)
VihTheme(
primary: String? = null, // "#RRGGBB"
onPrimary: String? = null,
secondary: String? = null,
accent: String? = null
)
VihNavigation(
tabs: List<VihTab>, // exactly the tabs shown, in order
defaultTab: VihTabId? = null // selected on open
)
VihTab(
id: VihTabId, // DISCOVER, CHATS, PROMO, TRANSACTIONAL, OTP, SETTINGS
label: String? = null, // rename the tab
icon: Int? = null // R.drawable.your_icon
)
๐๏ธ Split the chat into tabs
The default "Chats" tab shows every conversation. To split it, list the tabs you want instead of CHATS. The chat surface is a list of conversations (one row per business you chat with); each tab decides which conversations appear:
| Tab id | Shows | Filter |
|---|---|---|
CHATS | All active conversations | none |
PROMO | All active conversations (your chats) | none โ see note |
OTP | Conversations whose latest message is an OTP | latest template_type == 1 |
TRANSACTIONAL | Conversations whose latest message is transactional | latest template_type == 3 |
navigation = VihNavigation(
tabs = listOf(
VihTab(VihTabId.DISCOVER),
VihTab(VihTabId.PROMO, label = "Offers"), // shows your active chats
VihTab(VihTabId.OTP), // OTP messages only
VihTab(VihTabId.SETTINGS)
),
defaultTab = VihTabId.DISCOVER
)
Why Promo shows all chats. The chat surface is a list of conversations, but a "promotional" flag lives on individual messages, not whole conversations โ the chat-list API doesn't expose a conversation-level promo category. So the PROMO/Offers tab shows all your active chats (rather than filtering to empty). OTP and TRANSACTIONAL do filter, by each conversation's latest message type โ so they populate as OTP/transactional messages arrive. A true per-category message split would need the backend to tag conversations.
Use either the unified CHATS tab or a subset of the category tabs. The bottom bar supports up to 5 tabs; extra tabs are dropped.
๐จ Brand colors
Pass your app's hex codes in VihTheme. primary drives the bottom-nav selection, buttons, and header accents; onPrimary is the text/icon color that sits on the brand color. Your colors override the channel's server-configured colors.
theme = VihTheme(
primary = "#0B5FFF",
onPrimary = "#FFFFFF",
secondary = "#00C2A8" // optional secondary accent
)
This first release themes the highest-impact chrome (bottom nav, buttons, headers). A few deep surfaces are still being migrated to full tokens โ set primary + onPrimary for the biggest visual win. Dark mode is respected automatically. Malformed hex is ignored (the SDK keeps the previous color, never crashes).
๐ท๏ธ Tab names & icons
Set label to rename a tab and icon to a drawable resource in your app (or the SDK). Omit either to keep the SDK's default.
tabs = listOf(
VihTab(VihTabId.DISCOVER, label = "Explore", icon = R.drawable.ic_explore),
VihTab(VihTabId.CHATS, label = "Messages", icon = R.drawable.ic_messages),
VihTab(VihTabId.SETTINGS, label = "Account", icon = R.drawable.ic_account)
)
Icons should be a bottom-nav-sized vector/PNG drawable (โ24โ32dp). If a drawable can't be resolved, the SDK falls back to its default icon for that tab.
๐ Recipes
Split chat: Discover ยท Promo ยท OTP ยท Settings
VihConfig(
navigation = VihNavigation(
tabs = listOf(
VihTab(VihTabId.DISCOVER),
VihTab(VihTabId.PROMO),
VihTab(VihTabId.OTP),
VihTab(VihTabId.SETTINGS)
),
defaultTab = VihTabId.DISCOVER
)
)
Brand colors + renamed, re-iconed tabs
VihConfig(
theme = VihTheme(primary = "#0B5FFF", onPrimary = "#FFFFFF"),
navigation = VihNavigation(
tabs = listOf(
VihTab(VihTabId.DISCOVER, label = "Explore", icon = R.drawable.ic_explore),
VihTab(VihTabId.CHATS, label = "Messages", icon = R.drawable.ic_messages),
VihTab(VihTabId.SETTINGS, label = "Account", icon = R.drawable.ic_account)
)
)
)
Everything: split + brand + renames
VihConfig(
theme = VihTheme(primary = "#0B5FFF", onPrimary = "#FFFFFF"),
navigation = VihNavigation(
tabs = listOf(
VihTab(VihTabId.DISCOVER, label = "Explore"),
VihTab(VihTabId.PROMO, label = "Offers"),
VihTab(VihTabId.OTP, label = "Codes"),
VihTab(VihTabId.SETTINGS, label = "Account")
),
defaultTab = VihTabId.PROMO
)
)
iOS Swift
The same customization is available on iOS via VihUIConfig โ identical concepts, Swift syntax. Pass it at launch through configure(_:ui:), or apply it later with setUIConfig(_:).
import VihChatBotSDK
let ui = VihUIConfig(
theme: VihTheme(primary: "#0B5FFF", onPrimary: "#FFFFFF"),
navigation: VihNavigation(
tabs: [
VihTab(.discover),
VihTab(.promo, label: "Offers"),
VihTab(.otp),
VihTab(.settings, label: "Account",
icon: UIImage(systemName: "person.circle"))
],
defaultTab: .discover
)
)
VihChatBotSDK.shared.configure(config, ui: ui) // config = your VihSDKConfig
// or apply/replace later: VihChatBotSDK.shared.setUIConfig(ui)
The types mirror Android one-to-one:
VihUIConfig(theme: VihTheme?, navigation: VihNavigation?)
VihTheme(primary: String?, onPrimary: String?, secondary: String?, accent: String?)
VihNavigation(tabs: [VihTab], defaultTab: VihTabId?)
VihTab(_ id: VihTabId, label: String? = nil, icon: UIImage? = nil)
enum VihTabId { case discover, chats, promo, transactional, otp, settings }
Behavior matches Android exactly: tabs render from navigation.tabs (omit a tab to hide it); otp / transactional filter by message type while promo / chats show all active chats; brand colors override the server palette (host wins). Icons are any UIImage (SF Symbols work well). Custom tabs cap at 5.
โ๏ธ How it behaves
- Precedence: your
VihConfig> the channel's server settings > the SDK default. Set only what you want to change. - Non-breaking: omit
configand the SDK behaves exactly as before (Discover ยท Chats ยท Settings, server colors). - Fail-safe: unknown tab ids, missing icons, or bad hex are logged and fall back to defaults โ never a crash.
- Dark mode: honored automatically; your brand colors are preserved, body surfaces adapt.
๐ฎ Support
Questions on customization, a tab surface you need that isn't listed, or iOS timing? Reach the VIH team with your channel hashcode, SDK version, and the VihConfig you're using.