This guide provides a step-by-step approach to embedding an AI chatbot widget into your iOS application using WKWebView. By loading an HTML string into a WebView, you can embed an AI chatbot widget directly into your app.
Your Sendbird bot ID. If you don't have a bot, create one on Sendbird Dashboard under AI chatbot > Bot studio > Create bot. For further information, see the Bot studio guide.
Customize the HTML content to display your widget by setting the applicationID and botID. If the widget is not loading correctly in the WebView, this should be the first thing to check.
extension ChatBotWidgetView {
func widgetHTML(
applicationId: String,
botId: String,
showCloseIcon: Bool
) -> String {
"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Chatbot</title>
<!-- Load React and ReactDOM libraries -->
<script crossorigin src="https://unpkg.com/react@18.2.0/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.development.js"></script>
<!-- Load chat-ai-widget script and set process.env to prevent it from being undefined -->
<script>process = { env: { NODE_ENV: '' } }</script>
<script crossorigin src="https://unpkg.com/@sendbird/chat-ai-widget@latest/dist/index.umd.js"></script>
<link href="https://unpkg.com/@sendbird/chat-ai-widget@latest/dist/style.css" rel="stylesheet" />
<!-- Optional; to enable JSX syntax -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
html, body { height: 100%; margin: 0; }
\(showCloseIcon == true ? "" : "#aichatbot-widget-close-icon { display: none }")
</style>
</head>
<body>
<!-- div element for chat-ai-widget container -->
<div id="root"></div>
<!-- Initialize chat-ai-widget and render the widget component -->
<script type="text/babel">
const { ChatWindow } = window.ChatAiWidget;
const App = () => {
return (
<ChatWindow
applicationId="\(applicationId)"
botId="\(botId)"
/>
);
};
ReactDOM.createRoot(document.querySelector('#root')).render(<App />);
</script>
<script>
// Attach click event to the close icon after the chat widget is loaded
window.onload = function() {
setTimeout(() => {
const closeIcon = document.querySelector('#aichatbot-widget-close-icon');
closeIcon?.addEventListener('click', () => window.webkit?.messageHandlers?.bridgeHandler?.postMessage?.("closeChatBot"));
}, 1000); // delay to ensure the element is loaded
};
</script>
</body>
</html>
"""
}
}
In the HTML code above, the showCloseIcon parameter is used to determine whether the close button of the widget should be displayed. By default, the close button is displayed. If you want to hide the close button, set showCloseIcon to false.
In the script section of the HTML, you will find that the click event of the close button is added to webkit.messageHandlers.
<script>
// Attach click event to the close icon after the chat widget is loaded.
window.onload = function() {
setTimeout(() => {
const closeIcon = document.querySelector('#aichatbot-widget-close-icon');
closeIcon?.addEventListener('click', () => window.webkit?.messageHandlers?.bridgeHandler?.postMessage?.("closeChatBot"));
}, 1000); // delay to ensure the element is loaded.
};
</script>
To handle this event, you need to configure the bridgeHandler when creating the WKWebView.