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').
rml('config') field definitions
- pkThe
pkis 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 yourpkselect the "Get Embed Code" link for the appropriate widget on the Settings page. In the Embed Code tab you will find thepkin 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
rmlcalls for the same widget. WhenembedPositionis 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
embedPositioncan beinline,bottomRight,bottomLeft,dockRight, ordockLeft.inlineInserts 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.bottomRightDisplays the embedded room in the bottom right of your webpage. By default, a chip/tab (see collapsedModebelow) 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.bottomLeftInserts the embedded room in the bottom left of your webpage. By default, a chip/tab (see collapsedModebelow) 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.dockRightTells 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 collapsedModebelow) 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.dockLeftTells 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 collapsedModebelow) 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 (seecollapsedModebelow) 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, andhiddenare the options.hiddenwill 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 isinlineor collapsedMode is set tohidden.options:collapsedModeOfflineLabelThe offline label of the collapsed room. Not applicable when the embedPosition isinlineor 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 isinlineor collapsedMode is set tohidden. Defaults totrue.options:chatLayoutThis option changes the position of the room's messages. Choose betweenstackedandsideBySide.stackedmessages are left justified and stack on top of each other as they come into the room. ThesideBySidelayout 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 tofalseif you don't want to render the greeting message (the first message shown in a room). Defaults totrue.options:showRoomMemberList(optional) Set tofalseif you don't want to render the room member list chip. Defaults totrue.options:unfocusedUnreadAlert(optional) Set totrueif 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:offlineGreetingMessage(optional) Text 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, andenabledproperty that can be adjusted. The presence ofofflineMessageFieldsin therml('config')call will override all fields set in your widget's "Offline Mode" tab in the app settings. An example of theofflineMessageFieldsobject 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, andenabledproperty that can be adjusted. The presence ofselfIdentifyFormFieldsin 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 theselfIdentifyFormFieldsobject can be found in therml('config')code block.displayName,first,last,email,opt1, andopt2are the only fields that can be used. You can change the label to fit your scenario.NOTE:
selfIdentifyFormFieldsis only for the insecure register call,rml('register'), and will be ignored if used withrml('registerSecure').NOTE:
opt1andopt2will be displayed in the room's user info sidebar.NOTE: Do not supply any user options (i.e. userID, displayName, traits, etc) in the
rml('register')API call if using self identify since the register call, which is called everytime the page loads, will override any matching fields provided in the self identify form.options:selfIdentifyButtonLabel(optional) Text of the self/user identify form submit button.options:topBarNotificationsToggle(optional) Display an email notifications toggle in the room's top bar. Defaults totrue.NOTE: Only displays if the user has an email assigned to their account. Either send in their email in the
rml('register')call or use the self identify feature to capture your user's email.options:topBarNotificationsToggleType(optional) Use either a switch or bell icon to toggle email notifications on or off.topBarNotificationsToggleneeds to betruefor this setting to work. Defaults toswitch.options:roles(optional) You can define a set of user roles that will be displayed next to your user's message display name (aka "role chip"). You can customize each role chip's appearance in thisrolesobject. The roles object just defines which roles will be available. You will have to include a role option when you register your user in either therml('register')orrml('registerSecure')API call. For example if you have a "staff" role defined in this roles object (like the one in the supplied code block example) you would includerole: 'staff'in the options object of your register call.NOTE: Name is the only required field for each role. The other field values are standard CSS values.
name(required) Name of the role that will be displayed in the role chip backgroundColor(optional) Background color of role chip. Default is #aaaaaa.color(optional) Font color of role chip text. Default is #ffffff.fontSize(optional) Font size of role chip text. Default is 10px.fontFamily(optional) Font family of role chip text. Default is -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, Ubuntu, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol.borderRadius(optional) Border radius of role chip. Default is 2px.padding(optional) Padding around role chip. Default is 0 3px 1px.options:styles(optional) You can override certain styles in the embedded room. Here are the allowed overrides:--rml-btn-primary-background-colorBackground color of primary buttons (i.e. offline form submit button) --rml-btn-primary-background-color-hoverBackground color of hovered primary buttons --rml-btn-primary-background-color-activeBackground color of selected primary buttons --rml-btn-primary-text-colorText color of primary buttons --rml-btn-secondary-background-colorBackground color of secondary buttons (i.e. message edit buttons) --rml-btn-secondary-background-color-hoverBackground color of a hovered secondary buttons --rml-btn-secondary-background-color-activeBackground color of selected/active secondary buttons --rml-btn-secondary-text-colorText color of secondary buttons --rml-collapsed-background-colorBackground color of the chip or tab of the collapsed room --rml-collapsed-background-color-hoverBackground color of the hovered chip or tab of the collapsed room --rml-collapsed-background-color-activeBackground color of the selected/active chip or tab of the collapsed room --rml-collapsed-text-colorText color of the chip or tab of the collapsed room --rml-font-familyFont-family for the room --rml-icon-themeChoose between darkorlightthemed icons in the room--rml-link-colorColor of links and link URLs --rml-link-color-hoverColor of hovered links and link URLs --rml-msg-text-colorColor of the msg text --rml-msg-background-colorColor of the msg background --rml-msg-background-color-hoverBackground color of a hovered msg --rml-msg-system-text-colorColor of the msg system text (i.e. timestamp) --rml-msg-system-text-background-colorBackground color of the msg system text --rml-msg-system-font-familyFont family of the msg system text --rml-msg-system-font-sizeFont size of the msg system text --rml-msg-system-border-radiusBorder radius of the msg system text --rml-ui-chrome-background-colorBackground color of the room chrome --rml-ui-chrome-text-colorText color of the room chrome --rml-ui-chrome-active-background-colorActive background color of elements in the room chrome --rml-ui-chrome-active-text-colorActive text color of elements in the room chrome --rml-unfocused-unread-background-colorBackground color of the alert that displays if the room has a new message and isn't focused.
Only applies whenunfocusedUnreadAlert: true--rml-unfocused-unread-colorText 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-colorText color of other users' messages.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-them-link-colorText color of other users' links.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-them-background-colorBackground color of other users' messages.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-me-text-colorText color of the user's messages.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-me-link-colorText color of the user's links.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-me-background-colorBackground color of the user's messages.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-border-radiusBorder radius for all side-by-side messages.
Only applies whenchatLayout: 'sideBySide'--rml-side-by-side-paddingPadding on all side-by-side messages.
Only applies whenchatLayout: 'sideBySide'NOTE:
styleskeys 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-themeNOTE: 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 roomElementID: 'rml-room-1', // REQUIRED only if embedPosition: 'inline' 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', topBarNotificationsToggle: true, // defaults to true topBarNotificationsToggleType: 'switch', // 'switch' or 'bellIcon' roles: { staff: { name: 'Staff', // required if you choose to use roles backgroundColor: 'blue', // defaults to #aaaaaa borderRadius: '2px', // defaults to 2px color: 'white', // defaults to #ffffff fontSize: '10px', // defaults to 10px fontFamily: '-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, Ubuntu, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol', padding: '0px 3px 1px', // defaults to '0 3px 1px' }, fan: { name: 'Fan', ... }, }, 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') Insecurely registers the user and room. If possible, it is best to use the
rml('registerSecure')API call overrml('register')because it ensures that Roomlio embed data cannot be tampered with by a malicious user. Howeverrml('register')is good for testing or where user authentication authenticity is not important, for example visitors to your public web site.rml('register')must be called afterrml('config'). You can use the Embed Code tab via the "Get Embed Code" link for the appropriate widget on the Settings page for different combinations.Embed Type and User Naming
Because there are many options when embedding rooms, we try to spell out the different use cases below. When registering the users for each embedded room you have to be explicit on how your users will be named, and what room or rooms will be rendered by the embed code. Don't worry, we will provide validations if you pass in the wrong fields per type or leave off required fields. NOTE: When using
rml('registerSecure')you do not need to pass inembedTypeoruserNamingbecause in that scenario users can only be specified via the API.Please don't hesitate to reach out to us via chat in bottom right with any questions. This can be tricky at first!
rml('register') field definitions
- embedTypeWhen using
rml('register')you need to choose anembedTypewhich can be eithersingleRoomorallRooms. Most common issingleRoom.allRoomsis used when you want to embed all rooms a user belongs to including navigation to switch rooms. Depending on your choice, different fields may be required, optional or not allowed. - userNameWhen using
rml('register')you need to be explicit on how you will name the users of the embedded rooms. Use the code block tabs on the right or use our simple Embed Code generator in Roomlio Settings.apiSpecifiedWhen you explicity know who a user is and you can pass in that information via register call (most common). visitorSpecifiedLets users fill in a prechat form with customizable fields to determine who they are geoVisitors will get a displayname based on their approximate geo location, eg. seattle-wa-us-63f918 - 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
rmlcalls for the same widget. WhenembedPositionis 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: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. You can omit
roomKeyand Roomlio will create a unique key behind the scenes for you. - options:roomNameDisplay name of the room shown to users in the sidebar of the Roomlio App. Will show up in the email notification if you utilize our email notifications feature.
- options:userIDYour internal user id, or something that uniquely identifies the user to Roomlio.
NOTE: Do not use
userIDif you're going to be using our geolocation names (e.g. you're not going to know who your users will be). - 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:emailEmail of user. Providing email will allow us to prepopulate the email field on the offline and user identify forms. NOTE: It will not be visible to other users.
- options:roleRole of the user. Use the key of the role defined in the
rml('config')rolesoption.NOTE: Use the key of the role defined in the
rolesobject, not the rolename. - 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: 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 override the self identify form info.
Embed Type:User Naming:apiSpecifiedvisitorSpecifiedgeorml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'singleRoom', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'apiSpecified', // required. other options are 'visitorSpecified' and 'geo' (see more details in docs to left) // See https://app.roomlio.dev/#/settings for different combinations options: { // Room options roomKey: 'kraken1234', // required. needs to be unique per room, required for roomName: 'Kraken-Hockey', // recommended. the room name that will be shown in any room lists // User options userID: 'abc1234', // required. uniquely identifies the user displayName: 'jsmith99', // required first: 'John', // optional last: 'Smith', // optional email: '<user email here>', // optional but needed if you want to utilize email notifications role: 'staff', // corresponds to a role key defined in the rml('config') roles option // traits are for any of your own custom attributes you want attached to user traits: { color: 'purple', account: 'acct1234', plan: 'pro', }, }, });rml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'singleRoom', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'visitorSpecified', // required. other options are 'apiSpecified' and 'geo' (see more details in docs to left) // NOTE: you also need to specify 'selfIdentifyFormFields' in rml('config') call for 'visitorSpecified' user naming to work // See https://app.roomlio.dev/#/settings for different combinations options: { // Room options roomKey: 'kraken1234', // required. needs to be unique per room, required for roomName: 'Kraken-Hockey', // recommended. the room name that will be shown in any room lists }, });rml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'singleRoom', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'geo', // required. other options are 'apiSpecified' and 'visitorSpecified' (see more details in docs to left) // See https://app.roomlio.dev/#/settings for different combinations });rml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'allRooms', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'apiSpecified', // required. other options are 'visitorSpecified' and 'geo' (see more details in docs to left) // See https://app.roomlio.dev/#/settings for different combinations options: { // User options userID: 'abc1234', // required. uniquely identifies the user displayName: 'jsmith99', // required first: 'John', // optional last: 'Smith', // optional email: '<user email here>', // optional but needed if you want to utilize email notifications role: 'staff', // corresponds to a role key defined in the rml('config') roles option // traits are for any of your own custom attributes you want attached to user traits: { color: 'purple', account: 'acct1234', plan: 'pro', }, }, });rml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'allRooms', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'visitorSpecified', // required. other options are 'apiSpecified' and 'geo' (see more details in docs to left) // NOTE: you also need to specify 'selfIdentifyFormFields' in rml('config') call for 'visitorSpecified' user naming to work // See https://app.roomlio.dev/#/settings for different combinations });rml('register', { roomElementID: '<your-div-id-to-replace-with-embedded-room>', // required. the ID of the div where Roomlio will mount the embedded room. embedType: 'allRooms', // required. other option is 'allRooms' (see more details in docs to left) userNaming: 'geo', // required. other options are 'apiSpecified' and 'visitorSpecified' (see more details in docs to left) // See https://app.roomlio.dev/#/settings for different combinations });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 theregisterSecureAPI 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:roomKeybelow.rml('registerSecure') field definitions
- 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
rmlcalls for the same widget. WhenembedPositionis 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
registerSecurecall. NOTE: Protect your HMAC key like an API key or password. - 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. Will show up in the email notification if you utilize our email notifications feature.
- 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: trueto allow both secure and insecure users to chat in the same room. Default isfalse. - options:userIDYour internal user id, or something that uniquely identifies the user to Roomlio
- options:isModeratorAllows a user to moderate chat content, including removing spam messages or banning abusive users.
- 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:emailEmail of user. Providing email will allow us to prepopulate the email field on the offline and user identify forms. NOTE: It will not be visible to other users.
- options:roleRole of the user. Use the key of the role defined in the
rml('config')rolesoption.NOTE: Use the key of the role defined in the
rolesobject, not the rolename. - 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: 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 override the self identify form info.
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', role: 'staff', // corresponds to a role defined in the rml('config') roles option isModerator: true, // optional email: '<user email here>', // optional }; var rmlPayload = { apiName: 'register', userID: currentUser.id, displayName: currentUser.displayName, first: currentUser.firstName, // optional last: currentUser.lastName, // optional role: currentUser.role, // optional isModerator: currentUser.isModerator, // optional email: currentUser.email, // optional // Replace with desired roomKey and roomName values roomKey: 'abc1234', roomName: 'Smith Inc', allowInsecureUsers: false, // default is false }; 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', 'role': 'staff', # corresponds to a role defined in the rml('config') roles option 'isModerator': true, 'email: '<user email here>', } rml_payload = { 'apiName': 'register', 'userID': current_user['id'], 'displayName': current_user['displayName'], 'first': current_user['firstName'], # optional 'last': current_user['lastName'], # optional 'role': current_user['role'], # optional 'isModerator': current_user['isModerator'], # optional 'email': current_user['email'], # optional # Replace with desired roomKey and roomName values 'roomKey': 'abc1234', 'roomName': 'Smith Inc', 'allowInsecureUsers': false, # default is false } 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, 'email' => '<user email here>', 'role' => 'staff', // corresponds to a role key defined in the rml('config') roles option ); $rml_payload = array( 'apiName' => 'register', 'userID' => $current_user['id'], 'displayName' => $current_user['displayName'], 'first' => $current_user['firstName'], // optional 'last' => $current_user['lastName'], // optional 'role' => $current_user['role'], // optional 'isModerator' => $current_user['isModerator'], // optional 'email' => $current_user['email'], // optional // Replace with desired roomKey and roomName values 'roomKey' => 'abc1234', 'roomName' => 'Smith Inc', 'allowInsecureUsers' => false, // default is false ); $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 Role string IsModerator bool Email string }{ ID: "123456", DisplayName: "jsmith", FirstName: "John", LastName: "Smith", Role: "staff", // corresponds to a role key defined in the rml('config') roles option IsModerator: true, Email: "<user email here>", } 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"` Role string `json:"role,omitempty"` Email string `json:"email,omitempty"` AllowInsecureUsers bool `json:"allowInsecureUsers"` 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 // not required Role: currentUser.Role, // not required Email currentUser.Email, // not required AllowInsecureUsers: false, // default is false RoomKey: "abc1234", // Replace with desired roomKey and roomName values 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", 'role' => "staff", # corresponds to a role key defined in the rml('config') roles option 'isModerator' => true, 'email' => '<user email here>', } rml_payload = { 'apiName' => 'register', 'userID' => current_user['id'], 'displayName' => current_user['displayName'], 'first' => current_user['firstName'], # optional 'last' => current_user['lastName'], # optional 'role' => current_user['role'], # optional 'isModerator' => current_user['isModerator'], # optional 'email' => current_user['email'], # optional # Replace with desired roomKey and roomName values 'roomKey' => 'abc1234', 'roomName' => 'Smith Inc', 'allowInsecureUsers' => false # default is false } 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("role", "staff"); // corresponds to a role key defined in the rml('config') roles option currentUser.put("isModerator", true); currentUser.put("email", "<user email here>"); 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("role", currentUser.get("role")); // optional rmlPayload.put("isModerator", currentUser.get("isModerator")); // optional rmlPayload.put("email", currentUser.get("email")); // optional // Replace with desired roomKey and roomName values rmlPayload.put("roomKey", "abc1234"); rmlPayload.put("roomName", "Smith Inc"); rmlPayload.put("allowInsecureUsers", false) // default is false 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: truein 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-eventevent 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 whattypeof 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_openedevent 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_closedevent 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_focusevent 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_focusoutevent will be emitted.// rml_new_focus object { type: 'rml_new_focusout', payload: { roomElementID: '<room-element-id>'; } }