LiveChat Widget Integration - WideChat/Rocket.Chat GitHub Wiki
https://docs.rocket.chat/guides/omnichannel/livechat-widget-installation
This script loads livechat widget in web page
<!-- Start of Rocket.Chat Livechat Script -->
<script type="text/javascript">
(function(w, d, s, u) {
w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u; w.RocketChat.parentURL = w.location.href;
var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
j.async = true; j.src = 'http://localhost:3000/livechat/rocketchat-livechat.min.js?_=201903270000';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', 'http://localhost:3000/livechat');
</script>
Livechat Widget API is used for initializing widget with configuration(theme, customFields, department, visitor name/email etc) and for registering callbacks for some events like onChatStarted, onChatEnded, onChatMinimized, onChatMaximized, etc.
This Widget API is used inside Installation script as described in https://developer.rocket.chat/reference/api/livechat-api
To integrate widget in web, just need to add installation script in the html file.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
<!-- Start of Rocket.Chat Livechat Script -->
<script type="text/javascript">
(function(w, d, s, u) {
w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u; w.RocketChat.parentURL = w.location.href;
var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
j.async = true; j.src = 'http://localhost:3000/livechat/rocketchat-livechat.min.js?_=201903270000';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', 'http://localhost:3000/livechat');
</script>
</body>
</html>
We can use LiveChat Widget API in the script as below inside RocketChat()
function. API documentation: https://developer.rocket.chat/reference/api/livechat-api
- Create an HTML file with the below code. Modify server info i.e.
http://localhost:3000/livechat
. (Or directly get this from Omnichannel Installation Section) - Open the HTML file in the web browser. It should load Livechat Widget on the web page.
- If there is a CORS issue, we need to deploy this HTML file on the same domain. In the code add this file in
public
folder in the server repo. i.e.Rocket.Chat/public/livechat.html
. And it should be accessible usinghttps://<server>/livechat.html
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
<!-- Start of Rocket.Chat Livechat Script -->
<script type="text/javascript">
(function (w, d, s, u) {
w.RocketChat = function (c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u;
var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
j.async = true; j.src = 'http://localhost:3000/livechat/rocketchat-livechat.min.js?_=201903270000';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', 'http://localhost:3000/livechat');
RocketChat(function () {
const appName = "MyViasat";
const token = "MyViasatToken";
this.setCustomField('appName', appName);
this.setCustomField('token', token);
this.onChatStarted(() => {
console.log("onChatStarted fn")
});
});
</script>
</body>
</html>
To integrate widget in mobile, need to inject installation javascript in the web web view.
import React, { useContext, createContext, useEffect, useState } from 'react';
import { Platform } from 'react-native';
import { useQuery } from '@apollo/client';
import { GET_CONFIGURATIONS } from 'shared/queries/configurations';
import { GET_ACCOUNT_INFO_QUERY } from '../queries/profile';
import AppColors from 'shared/styles/colors';
import { useToken } from './token';
import packageJson from 'shared/myversion.json';
/*
* Documentation for the RocketChat livechat API: https://docs.rocket.chat/api/livechat-api#usage
*/
interface CustomFields {
name: string;
value: string;
disableOverwrite?: boolean;
}
const isWeb = Platform.OS === 'web';
const APP_NAME = Platform.select({
android: 'MyViasatMobileAND',
ios: 'MyViasatMobileIOS',
web: 'MyViasatWebAmer',
default: 'MyViasatWebAmer',
});
const SCRIPT_ID = 'rocketchat-script';
let webView: any = null;
const theme = {
color: AppColors.darkGray32424E,
fontColor: AppColors.white,
iconColor: AppColors.white,
};
const uninitalizedRocketChatFn = (): void => {
console.error('RocketChat did not load properly');
};
const Context = createContext({
maximizeWidget: uninitalizedRocketChatFn,
restartMobileWidget: uninitalizedRocketChatFn,
setCustomFields: (fields: CustomFields[]) => {
console.error('RocketChat did not load properly');
},
hideWidget: uninitalizedRocketChatFn,
showWidget: uninitalizedRocketChatFn,
isRocketChatEnabled: false,
loadRocketChatMobile: (webViewRef: any) => {
console.error('RocketChat did not load properly');
},
});
const runRocketChatMethods = (stringFunction: string) => {
if (isWeb) {
Function(stringFunction)();
} else {
//validating this so it doesn't throw a random error, moving back and forward screens
if (webView && webView.current) webView.current.injectJavaScript(stringFunction);
}
};
const loadRocketChatScript = (
hostUrl: string,
livechatUrl: string,
setIsScriptLoaded: React.Dispatch<React.SetStateAction<boolean>>,
) => {
const w: any = window;
const existingScript = document.getElementById(SCRIPT_ID);
if (!existingScript) {
return new Promise(function (resolve, reject) {
//@ts-ignore
w.RocketChat = params => w.RocketChat._.push(params);
w.RocketChat._ = [];
w.RocketChat.url = `${livechatUrl}`;
const tag = document.createElement('script');
tag.async = true;
tag.src = `${hostUrl}`;
tag.id = SCRIPT_ID;
tag.onload = resolve;
tag.onerror = reject;
const scriptElement = document.getElementsByTagName('script')[0];
scriptElement.parentNode?.insertBefore(tag, scriptElement);
})
.then(() => {
setDefaultsOnLoad(setIsScriptLoaded);
})
.catch(err => {
console.error(err);
});
}
};
const loadRocketChatMobileScript = (hostUrl: string, livechatUrl: string, webViewRef: any) => {
const injectRocketChatScript = `(function () {
var existingScript = document.getElementById("${SCRIPT_ID}");
if (!existingScript) {
window.RocketChat = function (c) { window.RocketChat._.push(c) };
window.RocketChat._ = [];
window.RocketChat.url = "${livechatUrl}";
var tag = document.createElement('script');
tag.async = true;
tag.src = "${hostUrl}";
tag.id = "${SCRIPT_ID}";
var head = document.getElementsByTagName("head")[0];
head.append(tag);
}
})();
`;
webViewRef.current.injectJavaScript(injectRocketChatScript);
webView = webViewRef;
};
const setDefaultsOnLoad = (setIsScriptLoaded: React.Dispatch<React.SetStateAction<boolean>>) => {
if (isWeb) {
hideWidget();
} else {
restartMobileWidget();
}
setTheme();
setCustomFields([{ name: 'appName', value: APP_NAME }]);
setIsScriptLoaded(true);
};
// Kept the methods as string then parse it as function (see runRocketChatMethods) for web since they are using the exact same thing.
const rocketChatMethods = {
restartMobileWidgetString: `
RocketChat(function () {
this.minimizeWidget();
this.maximizeWidget();
});`,
maximizeWidgetString: `
RocketChat(function () {
this.maximizeWidget();
});`,
showWidget: `
RocketChat(function(){
this.showWidget();
});`,
setCustomFields: (fields: CustomFields[]) =>
`RocketChat(function(){
${fields
.map(
({ name, value, disableOverwrite }) =>
`this.setCustomField("${name}", "${value}", ${disableOverwrite ? false : true});`,
)
.join('')}
});`,
setTheme: `
RocketChat(function(){
this.setTheme(${JSON.stringify(theme)});
});`,
hideWidget: `
RocketChat(function(){
this.hideWidget();
});`,
setGuestName: (name: string) => `RocketChat(function(){
this.setGuestName("${name}");
});`,
setGuestEmail: (email: string) => `RocketChat(function(){
this.setGuestEmail("${email}");
});`,
};
const maximizeWidget = () => runRocketChatMethods(rocketChatMethods.maximizeWidgetString);
const restartMobileWidget = () => runRocketChatMethods(rocketChatMethods.restartMobileWidgetString);
const setCustomFields = (fields: CustomFields[]) => runRocketChatMethods(rocketChatMethods.setCustomFields(fields));
const setTheme = () => runRocketChatMethods(rocketChatMethods.setTheme);
const hideWidget = () => runRocketChatMethods(rocketChatMethods.hideWidget);
const showWidget = () => runRocketChatMethods(rocketChatMethods.showWidget);
const setGuestName = (name: string) => runRocketChatMethods(rocketChatMethods.setGuestName(name));
const setGuestEmail = (email: string) => runRocketChatMethods(rocketChatMethods.setGuestEmail(email));
const getEmail = (contactMethods: any[]): string =>
contactMethods.find(contactMethod => contactMethod.__typename.toLowerCase() === 'email')?.email ?? '';
export const RocketChatProvider = ({ children }: { children: React.ReactNode }): JSX.Element | null => {
// Will not take any scope other than global(at least from what I can tell).
// Mobile can only be passed a function to access the global scope there.
const { token } = useToken();
const [isScriptLoaded, setIsScriptLoaded] = useState<boolean>(false);
useEffect(() => {
if (isScriptLoaded && token?.accessToken) setCustomFields([{ name: 'token', value: token?.accessToken ?? '' }]);
}, [token?.accessToken, isScriptLoaded]);
const { data, loading, error } = useQuery(GET_CONFIGURATIONS, {
variables: { input: { device: Platform.OS, version: packageJson.version } },
});
const { data: accountInfoData, loading: accountInfoLoading } = useQuery(GET_ACCOUNT_INFO_QUERY);
if (
!error &&
!loading &&
data &&
!accountInfoLoading &&
accountInfoData &&
Platform.OS === 'web' &&
data.getConfigurations.rocketChat.isEnabled
) {
loadRocketChatScript(
data.getConfigurations.rocketChat.hostUrl,
data.getConfigurations.rocketChat.livechatUrl,
setIsScriptLoaded,
);
setGuestName(accountInfoData.getAccountInfo.fullName);
setGuestEmail(getEmail(accountInfoData.getAccountInfo.contactMethods));
}
const loadRocketChatMobile = (webViewRef: any) => {
loadRocketChatMobileScript(
data?.getConfigurations.rocketChat.hostUrl,
data?.getConfigurations.rocketChat.livechatUrl,
webViewRef,
);
setDefaultsOnLoad(setIsScriptLoaded);
setGuestName(accountInfoData.getAccountInfo.fullName);
setGuestEmail(getEmail(accountInfoData.getAccountInfo.contactMethods));
};
const isRocketChatEnabled = data?.getConfigurations.rocketChat.isEnabled;
return (
<Context.Provider
value={{
maximizeWidget,
restartMobileWidget,
setCustomFields,
hideWidget,
showWidget,
isRocketChatEnabled,
loadRocketChatMobile,
}}
>
{children}
</Context.Provider>
);
};
export const useRocketChatContext = () => useContext(Context);