Roomlio Embed JS API
Embedding a room on your site is as simple as copy and pasting the embed code from the settings page into your site’s HTML. Some javascript will run on your site that will add a secure iframe containing your room where your users can begin conversing with others.
The embed code consists of three parts:
- A Roomlio div that you will place where you want the room to show (we offer different modes that don’t require you to add a div to your HTML).
- Two Roomlio javascript method calls,
rml('config')
and eitherrml('register')
orrml('registerSecure')
.rml('config')
is where you can make modifications to your room on the client side (position, languages, styles, etc).rml('register')
orrml('registerSecure')
notifies our backend about the user and room so Roomlio will be ready to send and receive messages. - The Roomlio javascript that runs the room on your site.
That’s it! Keep on reading below to learn more specifics about embedding a room onto your site. Please don't hesitate to reach out to Roomlio support if you have any question or need some help.
Roomlio provides two authentication modes. Simple and Secure (advanced)
Simple mode (i.e. calling rml('register')
) is useful for testing out Roomlio and some use cases where you don't need to be absolutely sure a user is who they say they are.
Secure Auth mode (i.e. calling rml('registerSecure')
) is highly recommended for production environments where you need to guarantee the authenticity of users. Since we use a javascript API to register the users, when not using secure mode nothing prevents a malicious user from pretending to be another user by using a browser's dev console. To implement Secure mode, use the shared HMAC secret key (provided in the Embed Code tab of the settings page for your widget) on your backend to generate a HMAC hash before registering the user. Base64 encode the generated HMAC hash and then pass the result to our rml('registerSecure')
API call. If all this sounds confusing, make sure to look at the examples we provide in the Embed Code tab for your widget for securely generating a HMAC hash in most of the popular server-side programming languages. IMPORTANT: treat your HMAC secret key like a password or API secret key, because it is a secret that should not be made public.
Please don't hesitate to reach out to Roomlio support for help.
Roomlio provides you with API methods that allow you to configure your rooms, pass in your user information, and more.
Use this to configure your Roomlio room. rml('config') must be called prior to rml('register'). This api call allows you to dynamically set configuration for widget. If values are not set here, we use the settings from the Roomlio App for the widget called by the embed code. Reasons you may want to set the configuration values dynamically would be to support multiple languages, change labels programatically and anything else you want to customize with code.
NOTE: Must be called before you call rml('register')
or rml('registerSecure')
.
- pkThe
pk
is your "publishable key" for your Roomlio account. It identifies your embed code with your Roomlio account. It is not a secret value, but it is unique per Roomlio account. To fetch yourpk
select the "Get Embed Code" link for the appropriate widget on the Settings page. In the Embed Code tab you will find thepk
in the Client Embed Coderml('config')
call HTML.NOTE: Required when you set
embedPosition: 'inline'
. - roomElementIDThe "id" of the div that you have in your markup that Roomlio will replace with an embedded room. This value must be the same on all
rml
calls for the same widget. WhenembedPosition
is set tobottomRight
,bottomLeft
,dockRight
, ordockLeft
, this value still needs to be present, but you do not need a corresponding div in your markup with that ID. - options:embedPosition
embedPosition
can beinline
,bottomRight
,bottomLeft
,dockRight
, ordockLeft
.inline
Inserts a roomlio room where you tell Roomlio to place it. In order to communicate to Roomlio where to insert the inline room, you must put a div in the page with the ID that matches the ID passed in roomElementID
.bottomRight
Displays the embedded room in the bottom right of your webpage. By default, a chip/tab (see collapsedMode
below) will appear when the room is collapsed that can be used to open the room when selected. The room will be "on top" of your page; open or collapsed.bottomLeft
Inserts the embedded room in the bottom left of your webpage. By default, a chip/tab (see collapsedMode
below) will appear when the room is collapsed that can be used to open the room when selected. The room will be "on top" of your page; open or collapsed.dockRight
Tells Roomlio to put the embedded room on the right side spanning the entire height of the page. An open room will shift your page over to the left and will sit on the same plain as your page. By default, a chip/tab (see collapsedMode
below) will appear when the room is collapsed that can be used to open the room when selected. The chip/tab will be "on top" of your page.dockLeft
Tells Roomlio to put the embedded room on the left side spanning the entire height of the page. An open room will shift your page over to the right and will sit on the same plain as your page. By default, a chip/tab (see collapsedMode
below) will appear when the room is collapsed that can be used to open the room when selected. The chip/tab will be "on top" of your page.NOTE: For all embedPositions, with the exception of
inline
, you can hide the default chip/tab (seecollapsedMode
below) and use your own button/link in combination with our JS API to open and close it.options:collapsedModeStyle of the room when it's collapsed (i.e. closed).chip
,tab
, andhidden
are the options.hidden
will hide the default chip/tab in case you want to use your own button/link in combination with our JS API to open and close it. Not applicable when the embedPosition isinline
.options:collapsedModeOnlineLabelThe online label of the collapsed room. Not applicable when the embedPosition isinline
or collapsedMode is set tohidden
.options:collapsedModeOfflineLabelThe offline label of the collapsed room. Not applicable when the embedPosition isinline
or collapsedMode is set tohidden
.options:startHiddenWill hide the room when the page loads. Handy when you want your users to select a custom button/link in your UI to reveal the room. This will require you to use the rml('show') API call when your custom button/link is selected.options:autoExpandAuto expand a collapsed room when a new message comes into the room. Not applicable when the embedPosition isinline
or collapsedMode is set tohidden
. Defaults totrue
.options:chatLayoutThis option changes the position of the room's messages. Choose betweenstacked
andsideBySide
.stacked
messages are left justified and stack on top of each other as they come into the room. ThesideBySide
layout places the user's messages on the right side of the room and everyone else's on the left side. Default isstacked
.options:showGreetingMessage(optional) Set tofalse
if you don't want to render the greeting message (the first message shown in a room). Defaults totrue
.options:showRoomMemberList(optional) Set tofalse
if you don't want to render the room member list chip. Defaults totrue
.options:unfocusedUnreadAlert(optional) Set totrue
if you want to render a visual alert in embedded room when the room has a new message and is not in focus. Default isfalse
. The alert will disappear after the user focuses on the room.options:unfocusedUnreadAlertMessage(optional) Message on the unread message alerts above. Defaults to "Unread Messages".options:unfocusedUnreadAlertFlashTime(optional) The time in seconds before the unread alert flashes. Default is 30 seconds. Set to large number if you don't want flashing alerts.options:greetingMessageUsername(optional) This is the username displayed in the greeting message. (first message displayed to a user on an embedded chat room).options:greetingMessage(optional) The first messages shown when a user opens an embedded chat room.options:offlineGreetingMessageText shown above the offline message form telling the user that you're offline.options:offlineMessageFields(optional) You can change the labels of the offline form fields, make them required or not-required, and show or hide them. Each field has alabel
,required
, andenabled
property that can be adjusted. The presence ofofflineMessageFields
in therml('config')
call will override all fields set in your widget's "Offline Mode" tab in the app settings. An example of theofflineMessageFields
object can be found in therml('config') code block.
options:offlineSendButton(optional) Text of the offline message form submit button.options:offlineThankYou(optional) Message displayed in the room after a visitor submits the offline form.options:offlineForwardingEmail(optional) Email to forward offline messages.options:offlineSubject(optional) Subject of the email sent to theofflineForwardingEmail
.options:selfIdentifyGreetingMsg(optional) Text shown above the self/user identify form telling the user about the form.options:selfIdentifyFormFields(optional) You can change the labels of the self/user identify form fields, make them required or not-required, and show or hide them. Each field has alabel
,required
, andenabled
property that can be adjusted. The presence ofselfIdentifyFormFields
in therml('config')
call will turn on the form and override all fields set in your widget's "User Identify Form" tab in the app settings. An example of theselfIdentifyFormFields
object can be found in therml('config')
code block.displayName
,first
,last
,email
,opt1
, andopt2
are the only fields that can be used. You can change the label to fit your scenario.NOTE:
opt1
andopt2
will be displayed in the room's user info sidebar.NOTE: Don't supply a traits object in the
rml('register')
API call if using self identify since the register call will override any info provided in the self identify since the register call is called everytime the page loads.options:selfIdentifyButtonLabel(optional) Text of the self/user identify form submit button.options:styles(optional) You can override certain styles in the embedded room. Here are the allowed overrides:--rml-btn-primary-background-color
Background color of primary buttons (i.e. offline form submit button) --rml-btn-primary-background-color-hover
Background color of hovered primary buttons --rml-btn-primary-background-color-active
Background color of selected primary buttons --rml-btn-primary-text-color
Text color of primary buttons --rml-btn-secondary-background-color
Background color of secondary buttons (i.e. message edit buttons) --rml-btn-secondary-background-color-hover
Background color of a hovered secondary buttons --rml-btn-secondary-background-color-active
Background color of selected/active secondary buttons --rml-btn-secondary-text-color
Text color of secondary buttons --rml-collapsed-background-color
Background color of the chip or tab of the collapsed room --rml-collapsed-background-color-hover
Background color of the hovered chip or tab of the collapsed room --rml-collapsed-background-color-active
Background color of the selected/active chip or tab of the collapsed room --rml-collapsed-text-color
Text color of the chip or tab of the collapsed room --rml-font-family
Font-family for the room --rml-icon-theme
Choose between dark
orlight
themed icons in the room--rml-link-color
Color of links and link URLs --rml-link-color-hover
Color of hovered links and link URLs --rml-msg-text-color
Color of the msg text --rml-msg-background-color
Color of the msg background --rml-msg-background-color-hover
Background color of a hovered msg --rml-msg-system-text-color
Color of the msg system text (i.e. timestamp) --rml-msg-system-text-background-color
Background color of the msg system text --rml-msg-system-font-family
Font family of the msg system text --rml-msg-system-font-size
Font size of the msg system text --rml-msg-system-border-radius
Border radius of the msg system text --rml-ui-chrome-background-color
Background color of the room chrome --rml-ui-chrome-text-color
Text color of the room chrome --rml-unfocused-unread-background-color
Background color of the alert that displays if the room has a new message and isn't focused.
Only applies whenunfocusedUnreadAlert: true
--rml-unfocused-unread-color
Text color of the alert that displays if the room has a new message and isn't focused.
Only applies whenunfocusedUnreadAlert: true
--rml-side-by-side-them-text-color
Text color of other users' messages.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-them-link-color
Text color of other users' links.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-them-background-color
Background color of other users' messages.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-me-text-color
Text color of the user's messages.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-me-link-color
Text color of the user's links.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-me-background-color
Background color of the user's messages.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-border-radius
Border radius for all side-by-side messages.
Only applies whenchatLayout: 'sideBySide'
--rml-side-by-side-padding
Padding on all side-by-side messages.
Only applies whenchatLayout: 'sideBySide'
NOTE:
styles
keys and values need to be strings. Styles that have color values can be hexidecimal, rgb, rgba, hsl, or color keywords (i.e. just like CSS).NOTE:
--rml-collapsed-...
overrides do not apply to inline rooms (akaembedPosition: 'inline'
).NOTE: CSS styles will not work for
--rml-icon-theme
NOTE: If you would like to override something not in this list, feel free to reach out and request an override!
rml('config', { pk: '<your pk here>', // REQUIRED only if embedPosition: 'inline' roomElementID: 'rml-room-1', // REQUIRED widgetID: '<your widgetID here>', options: { embedPosition: 'inline', // 'inline', 'bottomRight', 'bottomLeft', 'dockRight', or 'dockLeft' collapsedMode: 'tab', // 'chip', 'tab', or 'hidden'; not used for embedPosition: 'inline' collapsedModeOnlineLabel: 'How can we help you?', // not used for embedPosition: 'inline' collapsedModeOfflineLabel: 'Contact Us.', // not used for embedPosition: 'inline' startHidden: false, // defaults to false autoExpand: true, // defaults to true chatLayout: 'stacked', // 'stacked' or 'sideBySide' showGreetingMessage: true, // defaults to true, if false, no need to provide greetingMessageUsername/greetingMessage showRoomMemberList: true, // defaults to true, false will hide the chip and sidebar showing users in a room unfocusedUnreadAlert: true, // optionally show an alert in room if there is a new message and room not in focus unfocusedUnreadAlertMessage: 'Unread Messages', // label on optional unread alert unfocusedUnreadAlertFlashTime: 30, // time in seconds before alert starts to flash greetingMessageUsername: 'Support Team', greetingMessage: 'Welcome to Example. :wave: Type a message below if you have any questions!', offlineGreetingMessage: 'Hi, we are not around right now. Leave us a message and we will get back to you.', offlineMessageFields: { message: { label: 'Message', required: true, enabled: true }, email: { label: 'Email', required: true, enabled: true }, name: { label: 'Name', required: false, enabled: true }, opt1: { label: 'Company', required: false, enabled: true }, opt2: { label: 'Favorite Band', required: false, enabled: true }, opt3: { label: 'Address', required: false, enabled: true }, }, offlineSendButton: 'Send', offlineThankYou: 'Thank you for sending your message! We will get back to you shortly!', offlineForwardingEmail: '<your email address>', offlineSubject: 'New Roomlio offline message', selfIdentifyFormFields: { displayName: { label: 'Display Name', required: true, enabled: true }, // always required and enabled first: { label: 'First Name', required: false, enabled: true }, last: { label: 'Last Name', required: false, enabled: true }, email: { label: 'Email', required: false, enabled: true }, // email will not be seen by other embedded chat users opt1: { label: 'Company', required: false, enabled: true }, opt2: { label: 'City', required: false, enabled: true }, }, selfIdentifyGreetingMsg: 'Your public chat info.', selfIdentifyButtonLabel: 'Start chatting now', styles: { // button styles '--rml-btn-primary-background-color': 'purple', '--rml-btn-primary-background-color-hover': 'darkPurple', '--rml-btn-primary-background-color-active': 'lightPurple', '--rml-btn-primary-text-color': '#fff', '--rml-btn-secondary-background-color': 'lightGray', '--rml-btn-secondary-background-color-hover': 'gray', '--rml-btn-secondary-background-color-active': '#222222', '--rml-btn-secondary-text-color': 'white', // collapsed mode styles (do not apply when embedPosition equals 'inline') '--rml-collapsed-background-color': 'rgba(255, 0, 0, 1)', '--rml-collapsed-background-color-hover': 'darkRed', '--rml-collapsed-background-color-active': '#8e4e4e', '--rml-collapsed-text-color': 'rgb(255, 255, 255)', // font styles '--rml-font-family': 'Courier, monospace, serif', '--rml-icon-theme': 'light', // 'light' or 'dark' '--rml-link-color': 'rgba(0, 255, 0, 1)', '--rml-link-color-hover': 'darkGreen', // message styles '--rml-msg-text-color': '#212121', '--rml-msg-background-color': '#fff', '--rml-msg-background-color-hover': '#dddddd', // message system styles (i.e. timestamps, 'edited' label) '--rml-msg-system-text-color': 'white', '--rml-msg-system-text-background-color': 'gray', '--rml-msg-system-text-font-family': 'Courier, monospace, serif', '--rml-msg-system-text-font-size': '9px', '--rml-msg-system-text-border-radius': '4px', // UI chrome styles '--rml-ui-chrome-background-color': 'gray', '--rml-ui-chrome-text-color': '#212121', // unread message alert styles '--rml-unfocused-unread-background-color': 'red', '--rml-unfocused-unread-color': 'black', // side-by-side styles (only apply when chatLayout: 'sideBySide') '--rml-side-by-side-them-text-color': 'white', '--rml-side-by-side-them-link-color': '#ccc', '--rml-side-by-side-them-background-color': '#ff0000', '--rml-side-by-side-me-text-color': '#fff', '--rml-side-by-side-me-link-color': 'gray', '--rml-side-by-side-me-background-color': '#0000ff', '--rml-side-by-side-border-radius': '4px', '--rml-side-by-side-padding': '2px 6px', }, }, });
rml('register') Registers the user and room. If possible, it is best to use
rml('registerSecure')
API call overrml('register')
because it ensures that Roomlio embed data cannot be tampered with by a malicious user.rml('register')
is good for quick testing or where user authentication is not important.rml('register')
must be called afterrml('config')
. All "options" are optional for `register`. See the Embed Code tab via the "Get Embed Code" link for the appropriate widget on the Settings page for different combinations. If you just provide adisplayName
, we will display that for the user. If you provide first/last name as well, we will use that for display name instead. If roomKey/roomName is left off, we will name the room after the geo location of the user. Again, it is best to refer to the Embed Code tab for the widget on the Settings page for all the different combinations.- roomElementIDThe "id" of the div that you have in your markup that Roomlio will replace with an embedded room. This value must be the same on all
rml
calls for the same widget. WhenembedPosition
is set tobottomRight
,bottomLeft
,dockRight
, ordockLeft
, this value still needs to be present, but you do not need a corresponding div in your markup with that ID. - options:userIDYour internal user id, or something that uniquely identifies the user to Roomlio
- options:displayNameDisplay name of user, will be shown if no first/last name provided
- options:firstFirst name of user
- options:lastLast name of the user
- options:roomKeyA unique key to identify a room. Different keys mean different rooms. If a room key is changed, the embed code will generate an entirely new room. Generally your room keys should never change, but you can change roomName and maintain same room. Eg. If you have different rooms for each account in your system, your account ID would be the room key.
- options:roomNameDisplay name of the room shown to users in the sidebar of the Roomlio App
- options:traitsTraits are the place to send in your custom data. They can be anything you want to display in users' profiles. Note:
email
in the traits object will get special treatment. For instance, we will prepopulate it in the email input of the room offline form.NOTE: Don't supply a traits object here if you plan on using the self/user identify form to get data from your users. Using traits here will overrided the self identify form info.
- options:allowInsecureUsersBoolean. By default we do not allow insecure users to enter rooms that contain secure users. However, sometimes this situation is okay and you can set
allowInsecureUsers: true
to allow both secure and insecure users to chat in the same room. Default isfalse
.
rml('register', { roomElementID: 'your-div-id-to-replace-with-embedded-room', options: { // All options are "optional" for `register`. See https://app.roomlio.dev/#/settings for different combinations userID: 'abc1234', displayName: 'jsmith99', first: 'John', last: 'Smith', roomKey: 'kraken1234', roomName: 'Kraken-Hockey', traits: { color: 'purple', account: 'acct1234', plan: 'pro', email: '<user email here>', }, allowInsecureUsers: false, // Default is false }, });
rml('registerSecure') Securely registers the user and room. If possible, it is best to use this API call over
rml('register')
. It ensures that Roomlio embed data cannot be tampered with by a malicious user. Must be called afterrml('config')
. This API call will require you to securely build and sign your payload on the server side of your site. Your client (i.e. frontend code) will call your server (i.e. backend) to retrieve the register payload that contains an HMAC (authentication code) generated using a shared secret (usually on an API endpoint that requires authentication). Then make theregisterSecure
API call with payload and HMAC. Again, we highly recommend registering Roomlio users securely. Doing so will guarantee that all user info is accurate and authentic because you sign the payload with a shared secret.All "options" are optional for
registerSecure
. See the Embed Code tab via the "Get Embed Code" link for the appropriate widget on the Settings page for different combinations. If you just provide adisplayName
, we will display that for the user. If you provide first/last name as well, we will use that for display name instead. If roomKey/roomName is left off, we will name the room after the geo location of the user. Again, it is best to refer to the Embed Code tab for the widget on the Settings page for all the different combinations.GENERATING NEW ROOMS AUTOMATICALLY
See
options:roomKey
below.- roomElementIDThe "id" of the div that you have in your markup that Roomlio will replace with an embedded room. This value must be the same on all
rml
calls for the same widget. WhenembedPosition
is set tobottomRight
,bottomLeft
,dockRight
, ordockLeft
, this value still needs to be present, but you do not need a corresponding div in your markup with that ID. - payloadMACSigned HMAC authentication code. Use the HMAC key provided in the Embed Code tab of the settings page for your widget to create a hash of the payload, and then base64 encode it so the payload is a string when you send it in the
registerSecure
call. NOTE: Protect your HMAC key like an API key or password. - options:isModeratorAllows a user to moderate chat content, including removing spam messages or banning abusive users.
- options:userIDYour internal user id, or something that uniquely identifies the user to Roomlio
- options:displayNameDisplay name of user, will be shown if no first/last name provided
- options:firstFirst name of user
- options:lastLast name of the user
- options:roomKeyA unique key to identify a room. Different keys mean different rooms. If a room key is changed, the embed code will generate an entirely new room. Generally your room keys should never change, but you can change roomName and maintain same room. Eg. If you have different rooms for each account in your system, your account ID would be the room key.
- options:roomNameDisplay name of the room shown to users in the sidebar of the Roomlio App
- options:traitsTraits are the place to send in your custom data. They can be anything you want to display in users' profiles. Note:
email
in the traits object will get special treatment. For instance, we will prepopulate it in the email input of the room offline form.NOTE: Don't supply a traits object here if you plan on using the self/user identify form to get data from your users. Using traits here will overrided the self identify form info.
- options:allowInsecureUsersBoolean. By default we do not allow insecure users to enter rooms that contain secure users. However, sometimes this situation is okay and you can set
allowInsecureUsers: true
to allow both secure and insecure users to chat in the same room. Default isfalse
.
NodePython3PHPGoRubyJava// SERVER SIDE - NODE const express = require('express'); const app = express(); const crypto = require('crypto'); const cors = require('cors'); module.exports = function (app) { app.get('/registerParams', cors(), function (request, response) { // This would be based on your app authentication, hard coded for // this demo. ID and username should be unique across your app. var currentUser = { id: '123456', displayName: 'jsmith', firstName: 'John', lastName: 'Smith', isModerator: true, // optional }; var rmlPayload = { apiName: 'register', userID: currentUser.id, displayName: currentUser.displayName, first: currentUser.firstName, // optional last: currentUser.lastName, // optional isModerator: currentUser.isModerator, // optional // Replace with desired roomKey and roomName values roomKey: 'abc1234', roomName: 'Smith Inc', }; var payloadStr = JSON.stringify(rmlPayload); var hmacKey = '<your HMAC key>'; var message = JSON.stringify(rmlPayload); var hash = crypto.createHmac('sha256', hmacKey).update(message); var payloadMAC = hash.digest('base64'); response.json({ payloadMAC: payloadMAC, payloadStr: payloadStr, }); }); };
# SERVER SIDE - PYTHON 3 # main.py # where your Python app starts import hashlib import hmac import base64 import json from flask import Flask, jsonify app=Flask(__name__, static_folder='..') @app.route('/registerParams') def register_params(): # This would be based on your app authentication, hard coded for # this demo. ID and username should be unique across your app. current_user = { 'id': '123456', 'displayName': 'jsmith', 'firstName': 'John', 'lastName': 'Smith', 'isModerator': true, } rml_payload = { 'apiName': 'register', 'userID': current_user['id'], 'displayName': current_user['displayName'], 'first': current_user['firstName'], # optional 'last': current_user['lastName'], # optional 'isModerator': current_user['isModerator'], # optional # Replace with desired roomKey and roomName values 'roomKey': 'abc1234', 'roomName': 'Smith Inc', } payload_str = json.dumps(rml_payload) hash = hmac.new( bytes('<your HMAC key>', 'utf-8'), bytes(payload_str, 'utf-8'), hashlib.sha256) payload_mac = str(base64.b64encode(hash.digest()), 'utf-8') response = { 'payloadStr': payload_str, 'payloadMAC': payload_mac, } return jsonify(response)
// SERVER SIDE - PHP <?php if ($_SERVER['REQUEST_URI'] == '/registerParams') { // This would be based on your app authentication, hard coded for // this demo. ID and username should be unique across your app. $current_user = array( 'id' => "123456", 'displayName' => "jsmith", 'firstName' => "John", 'lastName' => "Smith", 'isModerator' => true, ); $rml_payload = array( 'apiName' => 'register', 'userID' => $current_user['id'], 'displayName' => $current_user['displayName'], 'first' => $current_user['firstName'], // optional 'last' => $current_user['lastName'], // optional 'isModerator' => $current_user['isModerator'], // optional // Replace with desired roomKey and roomName values 'roomKey' => 'abc1234', 'roomName' => 'Smith Inc', ); $payload_str = json_encode($rml_payload); $payload_mac = base64_encode(hash_hmac('sha256', $payload_str, '<your HMAC key', true)); $response = array( 'payloadStr' => $payload_str, 'payloadMAC' => $payload_mac, ); header('Content-Type: application/json'); echo json_encode($response); } ?>
// SERVER SIDE - GO package main import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "net/http" ) func registerParamsHandler(w http.ResponseWriter, r *http.Request) { // This would be based on your app authentication, hard coded for // this demo. ID and displayName should be unique across your app. var currentUser = struct { ID string DisplayName string FirstName string LastName string IsModerator bool }{ ID: "123456", DisplayName: "jsmith", FirstName: "John", LastName: "Smith", IsModerator: true, } var rmlPayload = struct { APIName string `json:"apiName"` UserID string `json:"userID"` DisplayName string `json:"displayName"` First string `json:"first,omitempty"` Last string `json:"last,omitempty"` IsModerator bool `json:"isModerator,omitempty"` RoomKey string `json:"roomKey"` RoomName string `json:"roomName"` }{ APIName: "register", UserID: currentUser.ID, DisplayName: currentUser.DisplayName, First: currentUser.FirstName, // not required Last: currentUser.LastName, // not required IsModerator currentUser.IsModerator // no required // Replace with desired roomKey and roomName values RoomKey: "abc1234", RoomName: "Smith Inc", } payloadStr, _ := json.Marshal(rmlPayload) HMACKey := "<your HMAC key>" h := hmac.New(sha256.New, []byte(HMACKey)) h.Write(payloadStr) hsum := h.Sum(nil) payloadMAC := base64.StdEncoding.EncodeToString(hsum) result := struct { PayloadStr string `json:"payloadStr"` PayloadMAC string `json:"payloadMAC"` }{ string(payloadStr), payloadMAC, } js, _ := json.Marshal(result) w.Header().Set("Content-Type", "application/json") w.Write(js) }
# SERVER SIDE - RUBY require 'sinatra' require 'openssl' require 'base64' require 'json' get '/registerParams' do # This would be based on your app authentication, hard coded for # this demo. ID and username should be unique across your app. current_user = { 'id' => "123456", 'displayName' => "jsmith", 'firstName' => "John", 'lastName' => "Smith", 'isModerator' => true, } rml_payload = { 'apiName' => 'register', 'userID' => current_user['id'], 'displayName' => current_user['displayName'], 'first' => current_user['firstName'], # optional 'last' => current_user['lastName'], # optional 'isModerator' => current_user['isModerator'], # optional # Replace with desired roomKey and roomName values 'roomKey' => 'abc1234', 'roomName' => 'Smith Inc', } payload_str = rml_payload.to_json payload_mac = Base64.encode64( OpenSSL::HMAC.digest( 'sha256', '<your HMAC key', payload_str, )) {'payloadStr' => payload_str, 'payloadMAC' => payload_mac}.to_json end
// SERVER SIDE - JAVA package com.rmlhmac.controller; import java.util.HashMap; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.core.io.ByteArrayResource; import java.io.IOException; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.json.JSONObject; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; import javax.xml.bind.DatatypeConverter; @Controller public class MyController { @GetMapping(value = "/registerParams", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Object> registerParams() { HashMap<String, String> currentUser = new HashMap<>(); // This would be based on your app authentication, hard coded for // this demo. ID and displayName should be unique across your app. currentUser.put("id", "123456"); currentUser.put("displayName", "jsmith"); currentUser.put("firstName", "John"); currentUser.put("lastName", "Smith"); currentUser.put("isModerator", true); JSONObject rmlPayload = new JSONObject(); rmlPayload.put("apiName", "register"); rmlPayload.put("userID", currentUser.get("id")); rmlPayload.put("displayName", currentUser.get("displayName")); rmlPayload.put("first", currentUser.get("firstName")); // optional rmlPayload.put("last", currentUser.get("lastName")); // optional rmlPayload.put("isModerator", currentUser.get("isModerator")); // optional // Replace with desired roomKey and roomName values rmlPayload.put("roomKey", "abc1234"); rmlPayload.put("roomName", "Smith Inc"); String payloadStr = rmlPayload.toString(); String payloadMac = ""; try { String hmacKey = "<your HMAC key"; Mac hasher = Mac.getInstance("HmacSHA256"); hasher.init(new SecretKeySpec(hmacKey.getBytes(), "HmacSHA256")); byte[] hash = hasher.doFinal(payloadStr.getBytes()); payloadMac = DatatypeConverter.printBase64Binary(hash); } catch (NoSuchAlgorithmException e) {} catch (InvalidKeyException e) {} HashMap<String, String> response = new HashMap<>(); response.put("payloadStr", payloadStr); response.put("payloadMAC", payloadMac); return new ResponseEntity<Object>(response, HttpStatus.OK); } }
// CLIENT SIDE (async () => { // Replace with the URL of the registerParams endpoint of your // server (see the server embed code for more info). const signedPayload = await fetch( `<your server endpoint domain>/registerParams`, ); const jsonPayload = await signedPayload.json(); rml('registerSecure', { roomElementID: 'your-div-id-to-replace-with-embedded-room', payloadMAC: jsonPayload.payloadMAC, options: jsonPayload.payloadStr, }); })();
rml('open') Open the room. Handy if you decide to use your own button/link to open the room. Not applicable if you set
embedPosition: 'inline'
. This call will be a must if you setcollapsedMode: 'hidden'
.rml('open', { roomElementID: 'rml-room-1', // id of room you want to open });
rml('close') Close the room. Handy if you decide to use your own button/link to close the room. Not applicable if you set
embedPosition: 'inline'
.rml('close', { roomElementID: 'rml-room-1', // id of room you want to close });
rml('reset') Clears local cache settings in the embedded room which may be useful for debugging Roomlio embed code as a developer.
rml('reset', { roomElementID: 'rml-room-1', // id of room in which you want clear the local cache. });
rml('show') Show the room on the page. Handy if you want to use your own UI to show the Roomlio room. Can be used in tandem with
rml('hide')
. Use thestartHidden: true
in therml('config')
call if you want the room hidden initially.rml('show', { roomElementID: 'rml-room-1', // id of room in which you want to show. });
rml('hide') Hides the room on the page. Handy if you want to use your own UI to hide the Roomlio room. Can be used in tandem with
rml('show')
.rml('hide', { roomElementID: 'rml-room-1', // id of room in which you want to hide. });
EVENTS rml-event Roomlio will emit a
rml-event
event when certain actions relating to a room occur that will aid you in integrating a room into your website. You just have to add an event listener and listen for whattype
of event it is (see below).// Example of how to listen for the rml-event document.addEventListener('rml-event', (event) => { switch (event.detail.type) { case 'rml_opened': // Do something... break; case 'rml_closed': // Do something... break; case 'rml_state_change': // Do something... break; case 'rml_new_msg': // Do something... break; case 'rml_new_focus': // Do something... break; case 'rml_new_focusout': // Do something... break; } });
- rml_openedWhen a room is opened the
rml_opened
event is emitted. Does not emit whenrml('config')
hasembedPosition: 'inline'
// rml_opened object { type: 'rml_opened', payload: { roomElementID: '<room-element-id>' } }
- rml_closed
When a room is closed the
rml_closed
event is emitted. Does not emit whenrml('config')
hasembedPosition: 'inline'
// rml_closed object { type: 'rml_closed', payload: { roomElementID: '<room-element-id>' } }
- rml_state_changeEmits when the room's associated widget transitions on or off. It also emits when the room is initialized so the initial state can be known w/o the widget actually being turned on or off. Useful to trigger an online or offline state of the custom button on your website.
// rml_state_change object { type: 'rml_state_change', payload: { state: 'on' } }
- rml_new_msgEmits when a new message is received in a room. Can be used to display your own new message count or notification on your website.
// rml_new_msg object { type: "rml_new_msg" payload: { currentUserEmbed: "<current-user-id>", msg: { body: "Do you have a question?" createdAt: "2021-01-21T20:12:18.302159Z" editedAt: "0001-01-01T00:00:00Z" first: "Winston" id: "<msg-id>" last: "Smith" links: [] roomID: "<room-id>" roomName: "support-room" tmpID: "<tmp-id>" userID: "<user-id>" userType: "member" username: "winstonSmith" } } }
- rml_new_focusWhen the room is focused the
rml_new_focus
event will be emitted. Handy if you want to clear your own new message count or notifications on your site.// rml_new_focus object { type: 'rml_new_focus', payload: { roomElementID: '<room-element-id>'; } }
- rml_new_focusoutWhen the room is unfocused the
rml_new_focusout
event will be emitted.// rml_new_focus object { type: 'rml_new_focusout', payload: { roomElementID: '<room-element-id>'; } }