Documentation Index
Fetch the complete documentation index at: https://docs.open.cx/llms.txt
Use this file to discover all available pages before exploring further.
Use this page when you want customers to open chat inside your mobile app.
Build one support page, load it in a WebView, and let OpenCX handle the conversation.
What You Are Building
Add a Support screen to your app. That screen opens a WebView pointed at a small HTTPS page with the OpenCX widget already open.
Implementation Steps
Create a support page
Host a page like https://app.example.com/mobile-support. Your app will load this URL in a WebView.
Add the widget
Give the page a real viewport height. Without this, the widget can load but the chat input may sit too high on the screen.<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#opencx-root {
width: 100vw;
height: 100dvh;
}
</style>
<script defer src="https://unpkg.com/@opencx/widget@latest/dist-embed/script.js"></script>
<script>
window.addEventListener('DOMContentLoaded', () => {
initOpenScript({
token: '<WIDGET_TOKEN>',
inline: true,
isOpen: true,
router: {
chatScreenOnly: true,
goToChatIfNoSessions: true,
},
theme: {
screens: {
chat: {
width: '100vw',
height: '100vh',
},
},
},
});
});
</script>
Open the page from your app
Add a Support button, Help Center row, or Account menu item that opens the WebView.
Test the mobile flow
Open the app, start a chat, close the screen, reopen it, and confirm the conversation still feels natural.
Open The WebView
Install react-native-webview first if your app does not already use it.import { WebView } from 'react-native-webview';
export function SupportScreen({ supportUrl }: { supportUrl: string }) {
return (
<WebView
source={{ uri: supportUrl }}
javaScriptEnabled
domStorageEnabled
allowsInlineMediaPlayback
onMessage={(event) => {
const payload = JSON.parse(event.nativeEvent.data);
if (payload.type === 'opencx.handoff') {
// Show a native banner, analytics event, or routing hint.
}
}}
/>
);
}
SupportViewController.swift
import UIKit
import WebKit
final class SupportViewController: UIViewController {
private let webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
view = webView
let url = URL(string: "https://app.example.com/mobile-support")!
webView.load(URLRequest(url: url))
}
}
import android.os.Bundle
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
class SupportActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val webView = WebView(this)
setContentView(webView)
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.loadUrl("https://app.example.com/mobile-support")
}
}
Recognize Signed-In Customers
If customers sign in to your app, pass a verified contact token to the widget. This lets the same customer see their support history across devices.
Request a token from your backend
Your backend calls OpenCX with your org API key. Do not call this from the mobile app.const response = await fetch('https://api.open.cx/widget/authenticate-user', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.OPENCX_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: user.email,
name: user.name,
customData: {
customerId: user.id,
plan: user.plan,
},
}),
});
const { token } = await response.json();
Pass the token into the widget
Add the token to your support page config. Your backend can render it into the page or your app can request it before opening the WebView.initOpenScript({
token: '<WIDGET_TOKEN>',
inline: true,
isOpen: true,
user: {
token: '<AUTHENTICATED_CONTACT_TOKEN>',
externalId: '<CURRENT_ACCOUNT_ID>',
},
});
Never put your OpenCX API key in the mobile app. Keep it on your backend.
Send Useful Context
Give support enough context to help without asking the customer to repeat themselves.
initOpenScript({
token: '<WIDGET_TOKEN>',
inline: true,
isOpen: true,
context: 'Customer is viewing order ORD-123 in the iOS app.',
sessionCustomData: {
platform: 'ios',
appVersion: '8.4.0',
accountId: 'acct_123',
},
});
Keep this clean. Send account IDs, plan names, app version, and the screen the customer came from. Do not send secrets or device identifiers.
Listen For Handoff
Use onHandoff if your app should show a native banner when a human takes over.
<script>
initOpenScript({
token: '<WIDGET_TOKEN>',
inline: true,
isOpen: true,
onHandoff: (payload) => {
window.ReactNativeWebView?.postMessage(
JSON.stringify({
type: 'opencx.handoff',
summary: payload.summary,
}),
);
},
});
</script>
Mobile Checklist
| Check | Why it matters |
|---|
inline: true | Makes the widget feel like the screen, not a website popup. |
isOpen: true | Opens chat immediately. |
router.chatScreenOnly | Skips the website-style session browser. |
Verified user.token | Keeps signed-in customers tied to the right contact. |
| Server-side API key | Keeps your OpenCX credentials out of the app bundle. |
Install Widget
Web, React, and headless install paths.
Authentication
Verified contact tokens and history access.
Configuration
Inline mode, routing, theme, and context options.
Headless
Build custom rendering when WebView is not enough.