Docs
DashboardRelease Notes
  • What is DeepConverse?
  • Chatbots
    • Basics
      • Building chatbot intents
      • Intent action responses
      • Chatbot Persistence mode
      • Publishing changes
    • Advanced Functionality
      • Connection Override
      • User Identity Verification
      • Announcements
      • Channel Specific Functionality
        • Zendesk Sunshine Conversations
          • How to handle image and file uploads in Zendesk Sunshine Conversations?
        • Zendesk Chat (Classic)
          • How to handoff conversations to Zendesk Chat (Classic) ?
        • Calendly
    • Branding
    • Deploy
      • Chatbot Versioning
      • iOS SDK
        • iOS (Custom Webview)
      • Android SDK
      • Adding widget to your Zendesk Help Center
      • Adding widget to your website
      • Custom Initialization and Passing Metadata
      • Open chatbot via Javascript
      • Adding widget to your Shopify Store
        • Adding the widget to Shopify via the Theme editor embed block
    • Localization
    • Customizations
      • Adding a link to your Privacy Policy in Chatbot window
  • Voice Bot
    • Getting Started with Voice Bots
    • Voice Bot Architecture
    • Supported use cases for Voice Bot
    • Setup and Configuration
  • Ticket Automation
    • Setup Zendesk email and ticket automation
  • Guides
    • Building Guides
    • Guide Theme Customization
    • Embedding Guides on your website
    • Embedding Guides in Chatbots
    • How to copy Guides across sites
  • Conversational Flow Builder
    • What is the Conversation Flow Builder?
    • Assign Parameters in Conversations
      • Predefined Parameters
    • How to use Rules in Conversations
    • Conversation Blocks
      • Question
      • Salesforce Blocks
        • Agent Availability Block
        • Live Agent Handover
      • Guide Blocks
        • Guide Step (Guide Flow)
        • Solved Block
        • Unsolved Block
        • Guide (Chatbot)
      • HTTP Request
      • Client Events
      • Policy
      • Zendesk Sunshine Conversations Handoff (In Widget)
    • Data Tables
      • How to read or search data from Data Tables?
  • Analytics
    • Chatbot Analytics
    • Viewing Chat Conversations
    • Message Viewer
    • Integrating with Google Analytics
    • Export API
      • Conversations Endpoint
      • Messages Endpoint
  • Integrations
    • Supported Integrations
      • Zendesk
      • Zendesk Sunshine Conversations
      • Salesforce
      • Gorgias
  • Account
    • Adding Users
    • Permissions and Roles
    • Multiple Sites
  • Security
    • DeepConverse Public IPs
    • Subprocessors
    • Data Request Policy
    • Technical and Organizational Security Measures
    • Reporting Security Vulnerabilities
      • Log4Shell Vulnerability
    • Generative AI - Technical Security Measures
  • Support
    • Contacting Support
    • Service Levels and Response Times
    • Platform Stability
Powered by GitBook
On this page

Was this helpful?

  1. Chatbots
  2. Deploy
  3. iOS SDK

iOS (Custom Webview)

PreviousiOS SDKNextAndroid SDK

Last updated 1 year ago

Was this helpful?

In cases where the implementation of the chatbot requires customization of the UI or app elements its recommended to implement a custom webview.

We provide our open source SDK for reference. You can find it here on our .

Webview

You can load the webview with the following URL which is configured to auto open the chatbot on receiving the trigger event.

https://cdn.deepconverse.com/v1/assets/widget/embedded-chatbot?hostname=<SUBDOMAIN>-<BOT_ID>.deepconverse.com

Once your webview has been created with this URL on click of a button or any other action which loads the URL you will invoke the following Javascript in the webview.

// Load the chatbot with Metadata
private func actionButtonJs() -> String {
    do {
        var metadataJSON = json(from: self.session.metadata)
        print("[DeepConverseSDK] Metadata:", metadataJSON)
        let s = """
    setTimeout(function () {var evt = new CustomEvent('botWidgetInit', { detail: \(metadataJSON!) });document.dispatchEvent(evt);}, 100)

    document.addEventListener('dc.bot', function(e) {
      let payload = { action: e.detail.action };
      window.webkit.messageHandlers.actionTapped.postMessage(payload);
    });
    """
        return s;
    } catch {
        print("[DeepConverseSDK] Error in Metadata" + error.localizedDescription);
        
        // Fallback to load without metadata
        
        let s = """
        setTimeout(function () {var evt = new CustomEvent('botWidgetInit', { detail: {} });document.dispatchEvent(evt);}, 100)
    
        document.addEventListener('dc.bot', function(e) {
          let payload = { action: e.detail.action };
          window.webkit.messageHandlers.actionTapped.postMessage(payload);
        });
        """
        return s;
    }


}

Here is the example of how to configure the webview and use the above function.

// Some code
private func configureWebview() {

    let webConfiguration = WKWebViewConfiguration()
    let contentController = WKUserContentController()
    let js: String = actionButtonJs();
    let userScript = WKUserScript(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
    contentController.removeAllUserScripts()
    contentController.addUserScript(userScript)
    contentController.add(
                self,
                name: "actionTapped"
            )
    webConfiguration.userContentController = contentController

    self.webview = WKWebView(frame: self.view.frame, configuration: webConfiguration)
    self.webview.navigationDelegate = self
    self.view.addSubview(self.webview)

    self.webview.scrollView.isScrollEnabled = false
    let webRequest = URLRequest(url: url,
                                cachePolicy: .useProtocolCachePolicy,
                                timeoutInterval: timeout)

    let layoutGuide = self.view.safeAreaLayoutGuide
    self.webview.translatesAutoresizingMaskIntoConstraints = false
    self.webview.leadingAnchor.constraint(
          equalTo: layoutGuide.leadingAnchor).isActive = true
    self.webview.trailingAnchor.constraint(
          equalTo: layoutGuide.trailingAnchor).isActive = true
    self.webview.topAnchor.constraint(
          equalTo: layoutGuide.topAnchor).isActive = true
    self.webview.bottomAnchor.constraint(
          equalTo: layoutGuide.bottomAnchor).isActive = true

    self.webview.load(webRequest)

    DispatchQueue.main.asyncAfter(deadline: .now() + timeout) {
        if (self.webview.isLoading) {
            self.webview.stopLoading()
            self.delegate.didWebViewFail(withError: DeepConverseWebHostError.WebViewTimeout)
        }
    }
}

We also provide callbacks to assist closing the webview.

In the above code snippet we register the actionTapped handler to listen to the callbacks. Three main actions are sent back in open, minimize, close

// Some code
extension DeepConverseHostViewController : WKScriptMessageHandler {
    public func userContentController (
        _ userContentController: WKUserContentController,
        didReceive message: WKScriptMessage
    ) {
        do {
            print("[DeepConverseSDK] message:", message.body);
            guard let payload = message.body as? [String: String] else { return }
            print("struct:", payload["action"])

            switch (payload["action"]) {
            case "open":
                print("[DeepConverseSDK] open action");
                break;
            case "minimize":
                print("[DeepConverseSDK] minimize action")
                self.dismiss(animated: true, completion: nil);
                break;
           case "close":
                print("[DeepConverseSDK] close action");
                break;
            default:
                print("[DeepConverseSDK] unknown action")
            }

            delegate.didReceiveEvent(event: payload)
        } catch {
            print("[DeepConverseSDK] Event error")
        }
    }
}

With the webview configured you can use now have the custom view controller as child or top level container as required in your app.

Github