├── LICENSE ├── ISSUE_TEMPLATE.md ├── smooch.5.7.16.min.js └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | License : https://smooch.io/terms 2 | 3 | All files located in the node_modules and external directories are 4 | externally maintained libraries used by this software which have their 5 | own licenses; we recommend you read them, as their terms may differ from 6 | the terms above. 7 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **For support questions, please visit [our help page](https://smooch.io/help/)**. 2 | 3 | This repository's issues are reserved for bug reports only. 4 | 5 | **I'm submitting a ...** 6 | 7 | - [ ] bug report 8 | - [ ] support request => Please do not submit support request here, see note at the top of this template. 9 | 10 | **What is the current behavior?** 11 | 12 | **Please provide the steps to reproduce and, if possible, a minimal demo of the problem** via 13 | https://plnkr.co, https://codepen.io/, or similar (e.g. a GitHub repository). 14 | 15 | **What is the expected behavior?** 16 | 17 | **Please tell us about your environment:** 18 | 19 | - Delivery method: [CDN | npm] 20 | - Version (can be found using `Smooch.VERSION` in your browser): 21 | - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] 22 | - OS: [Windows | OS X | Linux (which distro?)] + version 23 | 24 | **Other information** (e.g. detailed explanation, stack traces, related issues, suggestions how to fix, links for us to have context, eg. Stack Overflow, etc) 25 | -------------------------------------------------------------------------------- /smooch.5.7.16.min.js: -------------------------------------------------------------------------------- 1 | /*! For license information please see smooch.5.7.16.min.js.LICENSE.txt */ 2 | (()=>{var t={62988:(t,e,n)=>{var o=n(61755),r=n(26665).each;function i(t,e){this.query=t,this.isUnconditional=e,this.handlers=[],this.mql=window.matchMedia(t);var n=this;this.listener=function(t){n.mql=t.currentTarget||t,n.assess()},this.mql.addListener(this.listener)}i.prototype={constuctor:i,addHandler:function(t){var e=new o(t);this.handlers.push(e),this.matches()&&e.on()},removeHandler:function(t){var e=this.handlers;r(e,(function(n,o){if(n.equals(t))return n.destroy(),!e.splice(o,1)}))},matches:function(){return this.mql.matches||this.isUnconditional},clear:function(){r(this.handlers,(function(t){t.destroy()})),this.mql.removeListener(this.listener),this.handlers.length=0},assess:function(){var t=this.matches()?"on":"off";r(this.handlers,(function(e){e[t]()}))}},t.exports=i},38177:(t,e,n)=>{var o=n(62988),r=n(26665),i=r.each,s=r.isFunction,a=r.isArray;function c(){if(!window.matchMedia)throw new Error("matchMedia not present, legacy browsers require a polyfill");this.queries={},this.browserIsIncapable=!window.matchMedia("only all").matches}c.prototype={constructor:c,register:function(t,e,n){var r=this.queries,c=n&&this.browserIsIncapable;return r[t]||(r[t]=new o(t,c)),s(e)&&(e={match:e}),a(e)||(e=[e]),i(e,(function(e){s(e)&&(e={match:e}),r[t].addHandler(e)})),this},unregister:function(t,e){var n=this.queries[t];return n&&(e?n.removeHandler(e):(n.clear(),delete this.queries[t])),this}},t.exports=c},61755:t=>{function e(t){this.options=t,!t.deferSetup&&this.setup()}e.prototype={constructor:e,setup:function(){this.options.setup&&this.options.setup(),this.initialised=!0},on:function(){!this.initialised&&this.setup(),this.options.match&&this.options.match()},off:function(){this.options.unmatch&&this.options.unmatch()},destroy:function(){this.options.destroy?this.options.destroy():this.off()},equals:function(t){return this.options===t||this.options.match===t}},t.exports=e},26665:t=>{t.exports={isFunction:function(t){return"function"==typeof t},isArray:function(t){return"[object Array]"===Object.prototype.toString.apply(t)},each:function(t,e){for(var n=0,o=t.length;n{var o=n(38177);t.exports=new o}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var i=e[o]={exports:{}};return t[o](i,i.exports,n),i.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";const t="sLpKhIF7eEv-snNG6Miz1Q==";function e(t){"complete"!==document.readyState&&"loaded"!==document.readyState&&"interactive"!==document.readyState||!document.body?document.addEventListener("DOMContentLoaded",(function(){t()})):t()}function o(t){var e=["screen"];return t.minHeight&&e.push("(min-height: ".concat(t.minHeight,"px)")),t.maxHeight&&e.push("(max-height: ".concat(t.maxHeight,"px)")),t.minWidth&&e.push("(min-width: ".concat(t.minWidth,"px)")),t.maxWidth&&e.push("(max-width: ".concat(t.maxWidth,"px)")),e.join(" and ")}var r=n(24974),i=n.n(r),s={lg:{minHeight:668,minWidth:1200},md:[{minHeight:508,minWidth:768,maxWidth:1199},{minHeight:508,maxHeight:667,minWidth:768}],sm:{maxHeight:507,minWidth:768},xs:{maxWidth:767}},a=["lg","md","sm","xs"];function c(t){for(var e=0;et.length)&&(e=t.length);for(var n=0,o=Array(e);n\n \n \n ".concat("",'\n \n 30 | ``` 31 | 32 | then initialize the Web Messenger by placing this snippet towards the end of the `body` section of your page. 33 | 34 | ```html 35 | 40 | ``` 41 | 42 | ### Browserify and Webpack 43 | 44 | Install from npm 45 | 46 | ``` 47 | npm install --save smooch 48 | ``` 49 | 50 | Require and init 51 | 52 | ```javascript 53 | import Smooch from 'smooch'; 54 | 55 | Smooch.init({ integrationId: '' }).then(function () { 56 | // Your code after init is complete 57 | }); 58 | ``` 59 | 60 | ## Browser support 61 | 62 | Web Messenger supports all popular browsers. 63 | 64 | #### Desktop versions 65 | 66 | - Chrome: Latest and one major version behind 67 | - Edge: Latest and one major version behind 68 | - Firefox: Latest and one major version behind 69 | - Internet Explorer: 11+ 70 | - Safari: Latest and one major version behind 71 | 72 | #### Mobile versions 73 | 74 | - Stock browser on Android 4.1+ 75 | - Safari on iOS 8+ 76 | 77 | #### Other browsers 78 | 79 | Web Messenger is likely compatible with other and older browsers but we only test against the versions above. 80 | 81 | ## Region configuration 82 | 83 | Web messenger is supported in the following [regions](https://docs.smooch.io/guide/regions/): 84 | 85 | | Region | Region identifier | 86 | | -------------- | ------------------- | 87 | | United States | _Leave unspecified_ | 88 | | European Union | `eu-1` | 89 | 90 | To target the EU region, the region identifier is passed to `Smooch.init()`: 91 | 92 | ```javascript 93 | 106 | ``` 107 | 108 | If you are a licensed Zendesk customer, use `configBaseUrl` instead of `region`. `configBaseUrl` specifies the URL where the config request is sent. For example: 109 | 110 | ```javascript 111 | 124 | ``` 125 | 126 | ## API 127 | 128 | ### Individual functions 129 | 130 | #### init(options) 131 | 132 | Initializes the Smooch widget in the web page using the specified options. It returns a promise that will resolve when the Web Messenger is ready. Note that except `on` and `off`, all methods needs to be called after a successful `init`. 133 | 134 | ##### Options 135 | 136 | | Option | Optional? | Default value | Description | 137 | | -------------------------------- | --------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 138 | | integrationId | No | - | Your integration id | 139 | | externalId | Yes | - | Optional. User's external id, which can be passed in `init()` as an alternative to `login()` (see [below](#authenticating-the-user-init-vs-login)) | 140 | | jwt | Yes | - | Optional. User's authentication token, which can be passed in `init()` as an alternative to `login()` (see [below](#authenticating-the-user-init-vs-login)) | 141 | | authCode | Yes | - | An auth code for linking to an existing conversation (see more details [here](https://docs.smooch.io/rest/#get-auth-code)) | 142 | | locale | Yes | `en-US` | Locale used for date formatting using the `-` format. Language codes can be found [here](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) and country codes [here](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2).
**Note 1 : ** The country part is optional, and if a country is either not recognized or supported, it will fallback to using the generic language. If the language isn't supported, it will fallback to `en-US`.
**Note 2:** this is _only_ used for date formatting and doesn't provide built-in translations for Web Messenger. Refer to the [documentation](https://docs.smooch.io/guide/web-messenger/#strings-customization) for how to handle translations. | 143 | | soundNotificationEnabled | Yes | `true` | Enables the sound notification for new messages | 144 | | imageUploadEnabled | Yes | `true` | Enables the image upload feature. (deprecated: use menuItems.imageUpload; if this option is `false`, it will disable `menuItems.imageUpload` and `menuItems.fileUpload`) | 145 | | fixedHeader | Yes | `false` | When enabled, the introduction pane will be pinned at the top of the conversation instead of scrolling with it. | 146 | | embedded | Yes | False | Tells the widget it will be embedded. (see Embedded section below) | 147 | | displayStyle | Yes | `button` | Choose how the messenger will appear on your website. Must be either `button` or `tab`. | 148 | | buttonIconUrl | Yes | - | When the `displayStyle` is `button`, you have the option of selecting your own button icon. The image must be at least 200 x 200 pixels and must be in either JPG, PNG, or GIF format. | 149 | | buttonWidth | Yes | `58px` | When the `displayStyle` is `button`, you have the option of specifying the button width. | 150 | | buttonHeight | Yes | `58px` | When the `displayStyle` is `button`, you have the option of specifying the button height. | 151 | | businessName | Yes | - | A custom business name. | 152 | | businessIconUrl | Yes | - | A custom business icon url. The image must be at least 200 x 200 pixels and must be in either JPG, PNG, or GIF format. | 153 | | backgroundImageUrl | Yes | - | A background image url for the conversation. Image will be tiled to fit the window. | 154 | | integrationOrder | Yes | - | Array of integration IDs. When set, only integrations from this list will be displayed. If an empty array is used, no integrations will be displayed. _Note_: Listing an integration in the array doesn't guarantee that it will be displayed in the Web Messenger. | 155 | | customColors | Yes | [See below.](#customcolors) | Colors used in the Web Messenger UI. | 156 | | customText | Yes | See the example below | Strings used in the Web Messenger UI. You can use these to either customize the text or translate it. _Note_: Some strings include variables (surrounded by `{}`) which must remain in your customized text. | 157 | | menuItems | Yes | [See below.](#menuitems) | Choose menu items. | 158 | | notificationChannelPromptEnabled | Yes | `true` | Enables displaying a prompt to new users after their first message to suggest linking their chat instance with their other 3rd-party apps. | 159 | | browserStorage | Yes | `localStorage` | Choose the storage type to use for storing user identity in the browser. Must be either `localStorage` or `sessionStorage`. [Learn more](https://docs.smooch.io/guide/web-messenger/#browser-storage) | 160 | | delegate | Yes | `undefined` | Sets a delegate on the conversation. See the [delegate](#delegate) section for more details. | 161 | | prechatCapture | Yes | [See below.](#prechatcapture) | Enables automatically capturing a user's name and email via a form before the start of a conversation. Disables the chat input until the form has been submitted. | 162 | | canUserSeeConversationList | Yes | `true` | Allows users to view their list of conversations. | 163 | 164 | ##### `customColors` 165 | 166 | | Option | Optional? | Default value | Description | 167 | | ----------------- | --------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------- | 168 | | brandColor | Yes | `65758e` | This color will be used in the messenger header and the button or tab in idle state. Must be a 3 or 6-character hexadecimal color. | 169 | | conversationColor | Yes | `0099ff` | This color will be used for customer messages, quick replies and actions in the footer. Must be a 3 or 6-character hexadecimal color. | 170 | | actionColor | Yes | `0099ff` | This color will be used for call-to-actions inside your messages. Must be a 3 or 6-character hexadecimal color. | 171 | 172 | ##### `customText` 173 | 174 | The list of localizable strings. These strings can be modified. _If an option is not given a custom string, the default value will be used._ 175 | 176 | Please note that all error messages are prefixed with `errorPrefix` (default: `Error:`). For example, if you set `actionPaymentError` to `An error occurred while processing the card.`, the message shown to the user will be `Error: An error occurred while processing the card.` If you want to remove the prefix, set `errorPrefix` to an empty string. 177 | 178 | | Option | Default value | 179 | | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 180 | | actionPaymentCompleted | Payment Completed | 181 | | actionPaymentError | {errorPrefix} An error occurred while processing the card. `
` Please try again or use a different card. | 182 | | actionPostbackError | {errorPrefix} An error occurred while processing your action. Please try again. | 183 | | clickToRetry | Message not delivered. Click to retry. | 184 | | clickToRetryForm | Form not submitted. Click anywhere on the form to retry. | 185 | | connectNotificationText | Sync your conversation and continue messaging us through your favorite app. | 186 | | connectNotificationSingleText | Be notified when you get a reply. | 187 | | conversationListHeaderText | My conversations | 188 | | conversationListRelativeTimeJustNow | Just now | 189 | | conversationListRelativeTimeMinute | 1 minute ago | 190 | | conversationListRelativeTimeMinutes | {value} minutes ago | 191 | | conversationListRelativeTimeHour | 1 hour ago | 192 | | conversationListRelativeTimeHours | {value} hours ago | 193 | | conversationListRelativeTimeYesterday | Yesterday | 194 | | conversationListTimestampFormat | MM/DD/YY | 195 | | conversationListPreviewAnonymousText | Someone | 196 | | conversationListPreviewCarouselText | {user} sent a message | 197 | | conversationListPreviewFileText | {user} sent a file | 198 | | conversationListPreviewFormText | {user} sent a form | 199 | | conversationListPreviewFormResponseText | {user} filled a form | 200 | | conversationListPreviewImageText | {user} sent an image | 201 | | conversationListPreviewLocationRequestText | {user} sent a location request | 202 | | conversationListPreviewUserText | You | 203 | | conversationTimestampHeaderFormat | MMMM D YYYY, h:mm A | 204 | | couldNotConnect | Offline. You will not receive messages. | 205 | | couldNotConnectRetry | Reconnecting... | 206 | | couldNotConnectRetrySuccess | You're back online! | 207 | | couldNotLoadConversations | Couldn’t load conversations. | 208 | | emailChangeAddress | Change my email | 209 | | emailDescription | To be notified by email when you get a reply, enter your email address. | 210 | | emailFieldLabel | Email | 211 | | emailFieldPlaceholder | Your email address | 212 | | emailFormButton | Submit | 213 | | emailLinkingErrorMessage | {errorPrefix} Please submit a valid email address. | 214 | | errorPrefix | Error: | 215 | | fetchHistory | Load more | 216 | | fetchingHistory | Retrieving history... | 217 | | fileTooLargeError | {errorPrefix} Max file size limit exceeded ({size}) | 218 | | fileTypeError | {errorPrefix} Unsupported file type. | 219 | | formErrorEntryRequired | {errorPrefix} This entry is required | 220 | | formErrorInvalidEmail | {errorPrefix} Email is invalid | 221 | | formErrorNoLongerThan | {errorPrefix} Must contain no more than ({characters}) characters | 222 | | formErrorNoShorterThan | {errorPrefix} Must contain at least ({characters}) characters | 223 | | formErrorUnknown | {errorPrefix} This doesn't look quite right | 224 | | formFieldSelectPlaceholderFallback | Choose one... | 225 | | frontendEmailChannelDescription | To talk to us using email just send a message to our email address and we\'ll reply shortly: | 226 | | headerText | How can we help? | 227 | | imageClickToReload | Click to reload image. | 228 | | imageClickToView | Click to view {size} image. | 229 | | imagePreviewNotAvailable | Preview not available. | 230 | | inputPlaceholder | Type a message... | 231 | | inputPlaceholderBlocked | Complete the form above... | 232 | | introAppText | Message us below or from your favorite app. | 233 | | lineChannelDescription | To talk to us using LINE, scan this QR code using the LINE app and send us a message. | 234 | | linkError | {errorPrefix} An error occurred when attempting to generate a link for this channel. Please try again. | 235 | | linkChannelPageHeader | Sync your conversation | 236 | | locationNotSupported | Your browser does not support location services or it’s been disabled. Please type your location instead. | 237 | | locationSecurityRestriction | This website cannot access your location. Please type your location instead. | 238 | | locationSendingFailed | {errorPrefix} Could not send location | 239 | | locationServicesDenied | {errorPrefix} This website cannot access your location. Allow access in your settings or type your location instead. | 240 | | messageError | {errorPrefix} An error occured while sending your message. Please try again. | 241 | | messageIndicatorTitlePlural | (`{count}`) New messages | 242 | | messageIndicatorTitleSingular | (`{count}`) New message | 243 | | messageRelativeTimeDay | `{value}`d ago | 244 | | messageRelativeTimeHour | `{value}`h ago | 245 | | messageRelativeTimeJustNow | Just now | 246 | | messageRelativeTimeMinute | `{value}`m ago | 247 | | messageTimestampFormat | h:mm A | 248 | | messageDelivered | Delivered | 249 | | messageSeen | Seen | 250 | | messageSending | Sending... | 251 | | messageTooLongError | {errorPrefix} Max message size limit exceeded ({size}). | 252 | | messengerChannelDescription | Connect your Facebook Messenger account to be notified when you get a reply and continue the conversation on Facebook Messenger. | 253 | | newConversationButtonText | New Conversation | 254 | | notificationSettingsChannelsDescription | Sync this conversation by connecting to your favorite messaging app to continue the conversation your way. | 255 | | notificationSettingsChannelsTitle | Other Channels | 256 | | notificationSettingsConnected | Connected | 257 | | notificationSettingsConnectedAs | Connected as `{username}` | 258 | | prechatCaptureGreetingText | Hi there 👋\nTo start off, we\'d like to know a little bit more about you: | 259 | | prechatCaptureNameLabel | Your name | 260 | | prechatCaptureNamePlaceholder | Type your name... | 261 | | prechatCaptureEmailLabel | Email | 262 | | prechatCaptureEmailPlaceholder | name@company.com | 263 | | prechatCaptureConfirmationText | Thanks for that! What can we help you with? | 264 | | prechatCaptureMailgunLinkingConfirmation | You\'ll be notified here and by email at {email} once we reply. | 265 | | sendButtonText | Send | 266 | | settingsHeaderText | Settings | 267 | | shareLocation | Location | 268 | | smsBadRequestError | {errorPrefix} We were unable to communicate with this number. Try again or use a different one. | 269 | | smsCancel | Cancel | 270 | | smsChangeNumber | Change my number | 271 | | smsChannelDescription | Connect your SMS number to be notified when you get a reply and continue the conversation over SMS. | 272 | | smsChannelPendingDescription | Check your messages at `{number}` to confirm your phone number. | 273 | | smsContinue | Send | 274 | | smsInvalidNumberError | {errorPrefix} Please submit a valid phone number. | 275 | | smsLinkCancelled | Link to `{appUserNumber}` was cancelled. | 276 | | smsLinkPending | Pending | 277 | | smsPingChannelError | {errorPrefix} There was an error sending a message to your number. | 278 | | smsSendText | Send me a text | 279 | | smsStartTexting | Start Texting | 280 | | smsTooManyRequestsError | {errorPrefix} A connection for that number was requested recently. Please try again in {minutes} minutes. | 281 | | smsTooManyRequestsOneMinuteError | {errorPrefix} A connection for that number was requested recently. Please try again in 1 minute. | 282 | | smsUnhandledError | {errorPrefix} Something went wrong. Please try again. | 283 | | syncConversation | Sync conversation | 284 | | tapToRetry | Message not delivered. Tap to retry. | 285 | | tapToRetryForm | Form not submitted. Tap anywhere on the form to retry. | 286 | | telegramChannelDescription | Connect your Telegram account to be notified when you get a reply and continue the conversation on Telegram | 287 | | unsupportedMessageType | Unsupported message type. | 288 | | unsupportedActionType | Unsupported action type. | 289 | | uploadDocument | File | 290 | | uploadInvalidError | {errorPrefix} Invalid file. | 291 | | uploadPhoto | Image | 292 | | uploadVirusError | {errorPrefix} A virus was detected in your file and it has been rejected | 293 | | viberChannelDescription | Connect your Viber account to be notified when you get a reply and continue the conversation on Viber. To get started, scan the QR code using the Viber app. | 294 | | viberChannelDescriptionMobile | Connect your Viber account to be notified when you get a reply and continue the conversation on Viber. To get started, install the Viber app and tap Connect. | 295 | | viberQRCodeError | {errorPrefix} An error occurred while fetching your Viber QR code. Please try again. | 296 | | wechatChannelDescription | Connect your WeChat account to be notified when you get a reply and continue the conversation on WeChat. To get started, scan this QR code using the WeChat app. | 297 | | wechatChannelDescriptionMobile | Connect your WeChat account to be notified when you get a reply and continue the conversation on WeChat. To get started, save this QR code image and upload it ``QR code scanner``. | 298 | | wechatQRCodeError | {errorPrefix} An error occurred while fetching your WeChat QR code. Please try again. | 299 | | whatsappChannelDescriptionDesktop | Sync your account to WhatsApp by scanning the QR code or clicking the link below.\nThen, send the pre-populated message to validate the sync request. (Your code: {{code}}). | 300 | | whatsappChannelDescriptionMobile | Sync your account to WhatsApp by clicking the link below.\nThen, send the pre-populated message to validate the sync request. (Your code: {{code}}). | 301 | | whatsappLinkingError | {errorPrefix} An error occurred while fetching your WhatsApp linking information. Please try again. | 302 | 303 | [See below](#example) for an example. 304 | 305 | ##### `customScreenReaderAnnouncement` 306 | 307 | The list of localizable strings. These strings can be modified. _If an option is not given a custom string, the default value will be used._ 308 | 309 | | Option | Description | 310 | | ------------- | -------------------------- | 311 | | supportTyping | `{author}` is typing | 312 | | supportSays | `{author}` says: | 313 | | sentImage | `{author}` sent an image | 314 | | sentFile | `{author}` sent a file | 315 | | sentCarousel | `{author}` sent a carousel | 316 | | sentLocation | `{author}` sent a location | 317 | 318 | ##### `menuItems` 319 | 320 | | Option | Optional? | Default value | Description | 321 | | ------------- | --------- | ------------- | ------------------------------------- | 322 | | imageUpload | Yes | `true` | Enables the image upload menu item. | 323 | | fileUpload | Yes | `true` | Enables the file upload menu item. | 324 | | shareLocation | Yes | `true` | Enables the share location menu item. | 325 | 326 | [See below](#example) for an example. 327 | 328 | ##### `prechatCapture` 329 | 330 | | Option | Optional? | Default value | Description | 331 | | ------------------ | --------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 332 | | avatarUrl | Yes | `undefined` | Sets the URL of the avatar to use for the automatic reply to the prechat capture messages. | 333 | | enabled | Yes | `false` | Enables the prechat capture experience. | 334 | | enableEmailLinking | Yes | `true` | Automatically links the user's email to the app's Mailgun integration if it exists. If the property `fields` is defined, the first field of type `email` will be used. | 335 | | fields | Yes | - | Overrides the default Prechat Capture [fields](https://docs.smooch.io/guide/web-messenger/#prechat-capture) to define a [custom form](https://docs.smooch.io/guide/web-messenger/#custom-prechat-capture). | 336 | 337 | [beforeSend delegate](#beforesend) will apply to the user's submitted message. 338 | 339 | [See below](#example) for an example. 340 | 341 | `prechatCapture` uses the following [`customText`](#customText) options: 342 | 343 | | Option | Description | 344 | | ---------------------------------------- | ----------------------------------------------------------------------------- | 345 | | prechatCaptureGreetingText | Text for the initial greeting message. | 346 | | prechatCaptureNameLabel | Label displayed for the default form's first field. | 347 | | prechatCaptureNamePlaceholder | Placeholder for the default form's first field. | 348 | | prechatCaptureEmailLabel | Label displayed for the default form's second field. | 349 | | prechatCaptureEmailPlaceholder | Placeholder for the default form's second field. | 350 | | prechatCaptureConfirmationText | Text for the confirmation message sent when the form is completed. | 351 | | prechatCaptureMailgunLinkingConfirmation | Text for the notification message when a user has linked their email address. | 352 | 353 | ##### Example 354 | 355 | ```javascript 356 | var skPromise = Smooch.init({ 357 | integrationId: '', 358 | // For authenticated mode 359 | jwt: 'your_jwt', 360 | externalId: 'user_external_id', 361 | locale: 'en-US', 362 | 363 | customColors: { 364 | brandColor: '65758e', 365 | conversationColor: '65758e', 366 | actionColor: '65758e', 367 | }, 368 | 369 | menuItems: { 370 | imageUpload: true, 371 | fileUpload: true, 372 | shareLocation: true, 373 | }, 374 | 375 | fixedHeader: false, 376 | 377 | prechatCapture: { 378 | avatarUrl: 'http://domain.com/images/avatar.png', 379 | enabled: true, 380 | enableEmailLinking: true, 381 | fields: [ 382 | { 383 | type: 'email', 384 | name: 'email', 385 | label: 'Email', 386 | placeholder: 'your@email.com', 387 | }, 388 | { 389 | type: 'text', 390 | name: 'company-website', 391 | label: 'Company website', 392 | placeholder: 'mycompany.com', 393 | }, 394 | { 395 | type: 'select', 396 | name: 'company-size', 397 | label: 'Company size', 398 | placeholder: 'Choose a number...', 399 | options: [ 400 | { 401 | name: '1-10', 402 | label: '1-10 employees', 403 | }, 404 | { 405 | name: '11-50', 406 | label: '11-50 employees', 407 | }, 408 | { 409 | name: '51+', 410 | label: '51+ employees', 411 | }, 412 | ], 413 | }, 414 | ], 415 | }, 416 | 417 | customText: { 418 | actionPaymentCompleted: 'Payment Completed', 419 | actionPaymentError: 420 | 'An error occurred while processing the card.
Please try again or use a different card.', 421 | actionPostbackError: 'An error occurred while processing your action. Please try again.', 422 | clickToRetry: 'Message not delivered. Click to retry.', 423 | clickToRetryForm: 'Form not submitted. Click anywhere on the form to retry.', 424 | connectNotificationText: 'Sync your conversation and continue messaging us through your favorite app.', 425 | connectNotificationSingleText: 'Be notified when you get a reply.', 426 | conversationListHeaderText: 'My conversations', 427 | conversationListPreviewAnonymousText: 'Someone', 428 | conversationListPreviewCarouselText: '{user} sent a message', 429 | conversationListPreviewFileText: '{user} sent a file', 430 | conversationListPreviewFormText: '{user} sent a form', 431 | conversationListPreviewFormResponseText: '{user} filled a form', 432 | conversationListPreviewImageText: '{user} sent an image', 433 | conversationListPreviewLocationRequestText: '{user} sent a location request', 434 | conversationListPreviewUserText: 'You', 435 | conversationListRelativeTimeJustNow: 'Just now', 436 | conversationListRelativeTimeMinute: '1 minute ago', 437 | conversationListRelativeTimeMinutes: '{value} minutes ago', 438 | conversationListRelativeTimeHour: '1 hour ago', 439 | conversationListRelativeTimeHours: '{value} hours ago', 440 | conversationListRelativeTimeYesterday: 'Yesterday', 441 | conversationListTimestampFormat: 'MM/DD/YY', 442 | conversationTimestampHeaderFormat: 'MMMM D YYYY, h:mm A', 443 | couldNotConnect: 'Offline. You will not receive messages.', 444 | couldNotConnectRetry: 'Reconnecting...', 445 | couldNotConnectRetrySuccess: "You're back online!", 446 | couldNotLoadConversations: 'Couldn’t load conversations.', 447 | emailChangeAddress: 'Change my email', 448 | emailDescription: 'To be notified by email when you get a reply, enter your email address.', 449 | emailFieldLabel: 'Email', 450 | emailFieldPlaceholder: 'Your email address', 451 | emailFormButton: 'Submit', 452 | emailLinkingErrorMessage: 'Please submit a valid email address.', 453 | errorPrefix: 'Error:', 454 | fetchHistory: 'Load more', 455 | fetchingHistory: 'Retrieving history...', 456 | fileTooLargeError: 'Max file size limit exceeded ({size})', 457 | fileTypeError: 'Unsupported file type.', 458 | formErrorEntryRequired: 'This entry is required', 459 | formErrorInvalidEmail: 'Email is invalid', 460 | formErrorNoLongerThan: 'Must contain no more than ({characters}) characters', 461 | formErrorNoShorterThan: 'Must contain at least ({characters}) characters', 462 | formErrorUnknown: "This doesn't look quite right", 463 | formFieldSelectPlaceholderFallback: 'Choose one...', 464 | frontendEmailChannelDescription: 465 | "To talk to us using email just send a message to our email address and we'll reply shortly:", 466 | headerText: 'How can we help?', 467 | imageClickToReload: 'Click to reload image.', 468 | imageClickToView: 'Click to view {size} image.', 469 | imagePreviewNotAvailable: 'Preview not available.', 470 | inputPlaceholder: 'Type a message...', 471 | inputPlaceholderBlocked: 'Complete the form above...', 472 | introAppText: 'Message us below or from your favorite app.', 473 | lineChannelDescription: 'To talk to us using LINE, scan this QR code using the LINE app and send us a message.', 474 | linkError: 'An error occurred when attempting to generate a link for this channel. Please try again.', 475 | linkChannelPageHeader: 'Sync your conversation', 476 | locationNotSupported: 477 | 'Your browser does not support location services or it’s been disabled. Please type your location instead.', 478 | locationSecurityRestriction: 'This website cannot access your location. Please type your location instead.', 479 | locationSendingFailed: 'Could not send location', 480 | locationServicesDenied: 481 | 'This website cannot access your location. Allow access in your settings or type your location instead.', 482 | messageIndicatorTitlePlural: '({count}) New messages', 483 | messageIndicatorTitleSingular: '({count}) New message', 484 | messageRelativeTimeDay: '{value}d ago', 485 | messageRelativeTimeHour: '{value}h ago', 486 | messageRelativeTimeJustNow: 'Just now', 487 | messageRelativeTimeMinute: '{value}m ago', 488 | messageTimestampFormat: 'h:mm A', 489 | messageDelivered: 'Delivered', 490 | messageSeen: 'Seen', 491 | messageSending: 'Sending...', 492 | messengerChannelDescription: 493 | 'Connect your Facebook Messenger account to be notified when you get a reply and continue the conversation on Facebook Messenger.', 494 | newConversationButtonText: 'New Conversation', 495 | notificationSettingsChannelsDescription: 496 | 'Sync this conversation by connecting to your favorite messaging app to continue the conversation your way.', 497 | notificationSettingsChannelsTitle: 'Other Channels', 498 | notificationSettingsConnected: 'Connected', 499 | notificationSettingsConnectedAs: 'Connected as {username}', 500 | prechatCaptureGreetingText: "Hi there 👋\nTo start off, we'd like to know a little bit more about you:", 501 | prechatCaptureNameLabel: 'Your name', 502 | prechatCaptureNamePlaceholder: 'Type your name...', 503 | prechatCaptureEmailLabel: 'Email', 504 | prechatCaptureEmailPlaceholder: 'name@company.com', 505 | prechatCaptureConfirmationText: 'Thanks for that! What can we help you with?', 506 | prechatCaptureMailgunLinkingConfirmation: "You'll be notified here and by email at {email} once we reply.", 507 | sendButtonText: 'Send', 508 | settingsHeaderText: 'Settings', 509 | shareLocation: 'Location', 510 | smsBadRequestError: 'We were unable to communicate with this number. Try again or use a different one.', 511 | smsCancel: 'Cancel', 512 | smsChangeNumber: 'Change my number', 513 | smsChannelDescription: 514 | 'Connect your SMS number to be notified when you get a reply and continue the conversation over SMS.', 515 | smsChannelPendingDescription: 'Check your messages at {number} to confirm your phone number.', 516 | smsContinue: 'Send', 517 | smsInvalidNumberError: 'Please submit a valid phone number.', 518 | smsLinkCancelled: 'Link to {appUserNumber} was cancelled.', 519 | smsLinkPending: 'Pending', 520 | smsPingChannelError: 'There was an error sending a message to your number.', 521 | smsSendText: 'Send me a text', 522 | smsStartTexting: 'Start Texting', 523 | smsTooManyRequestsError: 524 | 'A connection for that number was requested recently. Please try again in {minutes} minutes.', 525 | smsTooManyRequestsOneMinuteError: 526 | 'A connection for that number was requested recently. Please try again in 1 minute.', 527 | smsUnhandledError: 'Something went wrong. Please try again.', 528 | syncConversation: 'Sync conversation', 529 | tapToRetry: 'Message not delivered. Tap to retry.', 530 | tapToRetryForm: 'Form not submitted. Tap anywhere on the form to retry.', 531 | telegramChannelDescription: 532 | 'Connect your Telegram account to be notified when you get a reply and continue the conversation on Telegram', 533 | unsupportedMessageType: 'Unsupported message type.', 534 | unsupportedActionType: 'Unsupported action type.', 535 | uploadDocument: 'File', 536 | uploadInvalidError: 'Invalid file', 537 | uploadPhoto: 'Image', 538 | uploadVirusError: 'A virus was detected in your file and it has been rejected', 539 | viberChannelDescription: 540 | 'Connect your Viber account to be notified when you get a reply and continue the conversation on Viber. To get started, scan the QR code using the Viber app.', 541 | viberChannelDescriptionMobile: 542 | 'Connect your Viber account to be notified when you get a reply and continue the conversation on Viber. To get started, install the Viber app and tap Connect.', 543 | viberQRCodeError: 'An error occurred while fetching your Viber QR code. Please try again.', 544 | wechatChannelDescription: 545 | 'Connect your WeChat account to be notified when you get a reply and continue the conversation on WeChat. To get started, scan this QR code using the WeChat app.', 546 | wechatChannelDescriptionMobile: 547 | "Connect your WeChat account to be notified when you get a reply and continue the conversation on WeChat. To get started, save this QR code image and upload it in the QR code scanner.", 548 | wechatQRCodeError: 'An error occurred while fetching your WeChat QR code. Please try again.', 549 | whatsappChannelDescriptionDesktop: 550 | 'Sync your account to WhatsApp by scanning the QR code or clicking the link below.\nThen, send the pre-populated message to validate the sync request. (Your code: {{code}}).', 551 | whatsappChannelDescriptionMobile: 552 | 'Sync your account to WhatsApp by clicking the link below.\nThen, send the pre-populated message to validate the sync request. (Your code: {{code}}).', 553 | whatsappLinkingError: 'An error occurred while fetching your WhatsApp linking information. Please try again.', 554 | unableToLoadImage: 'Unable to load image', 555 | }, 556 | }).then(function () { 557 | // Your code after init is complete 558 | }); 559 | 560 | skPromise.then(function () { 561 | // do something 562 | }); 563 | 564 | // pass it around... 565 | 566 | skPromise.then(function () { 567 | //do something else 568 | }); 569 | ``` 570 | 571 | #### open() 572 | 573 | Opens the conversation widget (noop when embedded) 574 | 575 | ```javascript 576 | Smooch.open(); 577 | ``` 578 | 579 | #### close() 580 | 581 | Closes the conversation widget (noop when embedded) 582 | 583 | ```javascript 584 | Smooch.close(); 585 | ``` 586 | 587 | #### isOpened() 588 | 589 | Tells if the widget is currently opened or closed. 590 | 591 | ```javascript 592 | Smooch.isOpened(); 593 | ``` 594 | 595 | #### login(externalId, jwt) 596 | 597 | Logs a user in the Web Messenger, retrieving the conversations the user already had on other browser sessions and/or devices. Note that you don't need to call this after `init` if you already passed the external id and jwt as arguments in the call to `init`, in which case it's done internally as part of the initialization sequence. This returns a `Promise` that resolves when the Web Messenger is ready again. 598 | 599 | ```javascript 600 | Smooch.login('external-id', 'some-jwt'); 601 | ``` 602 | 603 | #### logout() 604 | 605 | Logs out the current user and reinitialize the widget with an anonymous user. This returns a promise that resolves when the Web Messenger is ready again. 606 | 607 | ```javascript 608 | Smooch.logout(); 609 | ``` 610 | 611 | #### destroy() 612 | 613 | Destroys the Web Messenger and makes it disappear. The Web Messenger has to be reinitialized with `init` to be working again because it also clears up the integration id from the Web Messenger. It will also unbind all listeners you might have with `Smooch.on`. 614 | 615 | ```javascript 616 | Smooch.destroy(); 617 | ``` 618 | 619 | #### sendMessage(message, conversationId) 620 | 621 | Sends a message to the targeted conversation on the user's behalf. 622 | 623 | ```javascript 624 | Smooch.sendMessage( 625 | { 626 | type: 'text', 627 | text: 'hello', 628 | }, 629 | '', 630 | ); 631 | 632 | // OR 633 | 634 | Smooch.sendMessage('hello', ''); 635 | ``` 636 | 637 | #### startTyping(conversationId) 638 | 639 | Sends an event indicating that the user has started typing. 640 | 641 | Typing updates are automatically throttled, so you may call this method as often as necessary. The typing stop event will automatically fire 10 seconds after the most recent call to this method. 642 | 643 | If **conversationId** is not provided, the currently loaded conversation will be used. 644 | 645 | ```javascript 646 | Smooch.startTyping(); 647 | 648 | // OR 649 | 650 | Smooch.startTyping(''); 651 | ``` 652 | 653 | #### stopTyping(conversationId) 654 | 655 | Sends an event indicating that the user has stopped typing. 656 | 657 | If **conversationId** is not provided, the currently loaded conversation will be used. 658 | 659 | ```javascript 660 | Smooch.stopTyping(); 661 | 662 | // OR 663 | 664 | Smooch.stopTyping(''); 665 | ``` 666 | 667 | #### triggerPostback(actionId, conversationId) 668 | 669 | Trigger a [postback](https://docs.smooch.io/guide/structured-messages/#postback-buttons) action to the targeted conversation on the user's behalf. 670 | 671 | The `actionId` is the `id` property of the targeted action. 672 | 673 | If you have the `id` of the targetted `postback` action, you can pass it directly to `triggerPostback`. 674 | 675 | ```javascript 676 | const actionId = '5a747faa065bbe4e7804f2a4'; 677 | Smooch.triggerPostback(actionId, ''); 678 | ``` 679 | 680 | Otherwise, you can get the `id` of an action by using `Smooch.getConversationById()`, e.g. 681 | 682 | ```javascript 683 | Smooch.getConversationById('62565b5c2b4039adff80b7fd').then((conversation) => console.log(conversation.messages)); 684 | 685 | // [ 686 | // { 687 | // "text": "Do you want to continue?", 688 | // "actions": [ 689 | // { 690 | // "payload": "text:continue", 691 | // "text": "Continue conversation", 692 | // "id": "5a7c65211aaa9b61f69c95e3", 693 | // "type": "postback" 694 | // } 695 | // ], 696 | // "type": "text", 697 | // "role": "business", 698 | // "id": "5a7c65211aaa9b61f69c95e2", 699 | // // ... 700 | // } 701 | // ] 702 | 703 | // Indicate to Smooch that the user has clicked on the "Continue conversation" postback action. 704 | Smooch.triggerPostback(conversation.messages[0].actions[0].id); 705 | ``` 706 | 707 | #### updateUser(user) 708 | 709 | Updates the current user's information. If no user has been created yet, the Web Messenger will store the information and apply it to the user model when it is created. 710 | 711 | ```javascript 712 | Smooch.updateUser({ 713 | givenName: 'Updated', 714 | surname: 'Name', 715 | email: 'updated@email.com', 716 | avatarUrl: 'https://pictureurl.com/avatar_icon.png', 717 | metadata: { 718 | justGotUpdated: true, 719 | }, 720 | }); 721 | ``` 722 | 723 | #### getUser() 724 | 725 | Returns the current user. 726 | 727 | ```javascript 728 | var user = Smooch.getUser(); 729 | 730 | // user object payload 731 | 732 | user = { 733 | id: 'e70b153989345b0e178174b1', 734 | externalId: 'username', 735 | signedUpAt: '2019-09-26T14:48:58.167Z', 736 | hasPaymendInfo: false, 737 | metadata: {}, 738 | surname: 'Surname', 739 | givenName: 'Given Name', 740 | email: 'email@domain.com', 741 | avatarUrl: 'https://pictureurl.com/avatar_icon.png', 742 | }; 743 | ``` 744 | 745 | #### getConversationById(conversationId) 746 | 747 | Returns a `Promise` whose payload is a conversation if it exists. If **conversationId** is not given, the current loaded conversation will be returned. 748 | 749 | ```javascript 750 | Smooch.getConversationById('62565b5c2b4039adff80b7fd').then((conversation) => { 751 | console.log(conversation); 752 | }); 753 | 754 | // or 755 | 756 | Smooch.getConversationById().then((currentConversation) => { 757 | console.log(currentConversation); 758 | }); 759 | 760 | // Data object 761 | conversation = { 762 | id: '5aa4d7efdb32b10340db0223', 763 | lastUpdatedAt: 1581010017.596, 764 | businessLastRead: 1581010017.596, 765 | description: 'Conversation description', 766 | displayName: 'Conversation name', 767 | iconUrl: 'https://pictureurl.com/conversation_icon.png', 768 | type: 'sdkGroup', 769 | participants: [ 770 | { 771 | id: '5f0cb8222c884d031ec05dd9', 772 | userId: 'e70b153989345b0e178174b1', 773 | unreadCount: 0, 774 | lastRead: 1581010017.596, 775 | }, 776 | ], 777 | metadata: {}, 778 | messages: [ 779 | { 780 | role: 'user', 781 | userId: 'e70b153989345b0e178174b1', 782 | displayName: 'Some user', 783 | id: '5e6022c9cb55158bfd53f845', 784 | type: 'text', 785 | received: 1583358665.139, 786 | text: 'Hello', 787 | source: { 788 | type: 'web', 789 | id: 'c38ae913af7c4ef3800b339ee529c579', 790 | integrationId: '5d8274d4aa780a5483f0ee56', 791 | }, 792 | }, 793 | { 794 | role: 'business', 795 | displayName: 'Business display name', 796 | id: '5f0cb834bc8ea9e41b2af269', 797 | type: 'text', 798 | received: 1594669108.896, 799 | text: 'Greetings!', 800 | source: { 801 | type: 'slack', 802 | }, 803 | }, 804 | ], 805 | }; 806 | ``` 807 | 808 | #### getConversations() 809 | 810 | Returns a list of conversations for the current user that were fetched during app initialization as well as the paginated results. 811 | 812 | Note: 813 | 814 | - The `messages` property in each conversation may only have the most recent message in the conversation. The full message list will be available either when the conversation was loaded to the view or [Smooch.getConversationById](#getconversationbyidconversationid) gets called. 815 | - In the event that the client reconnects due to a network issue, the list may only contain the `10` most recent conversations for the user. All the additional conversations that were fetched as a result of pagination will be discarded. 816 | 817 | See [Smooch.getConversationById](#getconversationbyidconversationid) for the definition of a conversation 818 | 819 | ```javascript 820 | var conversations = Smooch.getConversations(); 821 | // Your code after receiving the current user's loaded conversations 822 | ``` 823 | 824 | #### getDisplayedConversation() 825 | 826 | Returns the conversation being viewed by the user if it exists or `null` if the current user is in the conversations list view. 827 | 828 | See [Smooch.getConversationById](#getconversationbyidconversationid) for the conversation definition 829 | 830 | ```javascript 831 | var conversation = Smooch.getDisplayedConversation(); 832 | ``` 833 | 834 | #### getMoreConversations() 835 | 836 | Fetches and returns the next 10 most active conversations of the current user. This call also appends the conversations to the conversation list view. 837 | 838 | See [Smooch.getConversationById](#getconversationbyidconversationid) for the conversation definition 839 | 840 | ```javascript 841 | Smooch.getMoreConversations().then((nextConversations) => { 842 | // Your code after receiving the next set of conversations for the user 843 | }); 844 | ``` 845 | 846 | #### hasMoreConversations() 847 | 848 | Returns a `boolean` indicating whether the user has more conversations that can be fetched for the conversation list view. 849 | 850 | ```javascript 851 | var hasMore = Smooch.hasMoreConversations(); 852 | 853 | if (hasMore) { 854 | console.log('More conversations available to fetch...'); 855 | } else { 856 | console.log('There are no more conversations remaining for the user'); 857 | } 858 | ``` 859 | 860 | #### loadConversation(conversationId) 861 | 862 | Loads a conversation into the current session 863 | 864 | ```javascript 865 | Smooch.loadConversation(''); 866 | ``` 867 | 868 | #### updateConversation(conversationId, options) 869 | 870 | Updates the targeted conversation. 871 | 872 | ```javascript 873 | Smooch.updateConversation('', { 874 | displayName: 'display name', 875 | iconUrl: 'https://www.example.png', 876 | description: 'description', 877 | metadata: { 878 | any: 'info', 879 | }, 880 | }).then((updatedConversation) => { 881 | // Your code after receiving the current user's updated conversation 882 | }); 883 | ``` 884 | 885 | where the fields are optional and could be set to `null` in the case integrators want to unset the value of the fields. 886 | 887 | #### createConversation(options) 888 | 889 | Creates a conversation on behalf of current user. If the user does not exist, it first creates the user and then a conversation associated with it. 890 | 891 | All the options are optional. 892 | 893 | ```javascript 894 | Smooch.createConversation({ 895 | displayName: "Friday's Order", 896 | iconUrl: 'https://www.zen-tacos.com/tacos.png', 897 | description: 'Order #13377430', 898 | metadata: { 899 | isFirstTimeCustomer: true, 900 | }, 901 | messages: [ 902 | { 903 | text: 'Hi there! I have a question about my order.', 904 | type: 'text', 905 | }, 906 | ], 907 | }).then((conversation) => { 908 | // Your code after receiving the current user's new conversation 909 | }); 910 | ``` 911 | 912 | To create more than one conversation using this method, or to allow your user to create more conversations via the conversation list's `New Conversation` button, you must: 913 | 914 | - have the [Multi-Conversations feature](https://docs.smooch.io/rest/#operation/updateApp) enabled on your account 915 | - [update your Web Messenger integration](https://docs.smooch.io/rest/#operation/updateIntegration) and set `canUserCreateMoreConversations` to `true` 916 | 917 | Note that this API does not allow creating [`sdkGroup` conversations](https://docs.smooch.io/guide/multi-party-conversations/#new-platform-capabilities). This type of conversation must be created by using the public API. 918 | 919 | #### markAllAsRead(conversationId) 920 | 921 | Marks all unread messages as read. 922 | 923 | If **conversationId** is not provided, the currently loaded conversation will have its messages marked as read. 924 | 925 | ```javascript 926 | Smooch.markAllAsRead(); 927 | 928 | // or 929 | 930 | Smooch.markAllAsRead(''); 931 | ``` 932 | 933 | #### showNotificationChannelPrompt() 934 | 935 | Displays a prompt to the user suggesting the linking of the current chat instance with other 3rd-party apps. 936 | 937 | ```javascript 938 | Smooch.showNotificationChannelPrompt(); 939 | ``` 940 | 941 | #### setPredefinedMessage(message) 942 | 943 | Prefills the user's chat input with a predefined message. 944 | 945 | ```javascript 946 | Smooch.setPredefinedMessage(message); 947 | ``` 948 | 949 | #### setDelegate(delegate) 950 | 951 | Sets a delegate on the conversation. Smooch must be initialized before calling this method. See the [delegate](#delegate) section for more details. 952 | 953 | ```javascript 954 | Smooch.setDelegate(delegate); 955 | ``` 956 | 957 | ### Delegate 958 | 959 | Smooch allows you to set a delegate to receive callbacks when important changes happen in the conversation. 960 | To set a delegate, pass the `delegate` parameter in to [init options](#options), or use the [setDelegate](#setdelegatedelegate) method. The `delegate` object may optionally contain `beforeDisplay`, `beforeSend`, `beforePostbackSend` and `onInvalidAuth` delegate functions. 961 | 962 | Passing `delegate` as part of `init` options is the preferred method. The `setDelegate` method can be used to change or remove delegate behaviors after a conversation has been initialized. 963 | 964 | A `data` object is passed down with all the delegate events except `onInvalidAuth`. This is a read-only object containing a truncated version of the conversation associated with the event. 965 | 966 | `beforeSend` delegate will apply to the `formResponse` message sent when a [Prechat Capture](https://docs.smooch.io/guide/web-messenger/#prechat-capture) form is completed. 967 | 968 | ```javascript 969 | const delegate = { 970 | beforeDisplay(message, data) { 971 | if (data.conversation.id === '') { 972 | message.displayName = 'Acme Blank'; 973 | } 974 | 975 | return message; 976 | }, 977 | beforeSend(message, data) { 978 | return message; 979 | }, 980 | beforePostbackSend(postback, data) { 981 | return postback; 982 | }, 983 | onInvalidAuth() { 984 | return new Promise((resolve) => resolve('')); 985 | }, 986 | }; 987 | 988 | // Passing delegate as an init parameter 989 | Smooch.init({ 990 | integrationId: '', 991 | delegate, 992 | }); 993 | 994 | // Using setDelegate 995 | Smooch.init({ integrationId: '' }).then(() => { 996 | Smooch.setDelegate(delegate); 997 | }); 998 | 999 | // Message object for beforeDisplay and beforeSend delegates 1000 | 1001 | message = { 1002 | id: '5f0cb8226a5b27e41834f8f8', 1003 | displayName: 'username', 1004 | role: 'user', 1005 | userId: 'e70b153989345b0e178174b1', 1006 | avatarUrl: 'https://imageurl.com/avatar.png', 1007 | type: 'text', 1008 | received: 1594669090.954, 1009 | source: { 1010 | type: 'web', 1011 | id: 'e91e070a9c4e4eb7b73fb0a376b340c7', 1012 | integrationId: '5d72af033fbb2c05c87d5d94', 1013 | }, 1014 | metadata: { 1015 | isHidden: true, 1016 | }, 1017 | }; 1018 | 1019 | // Data object 1020 | data = { 1021 | conversation: { 1022 | id: '', 1023 | lastUpdatedAt: 1581010017.596, 1024 | type: 'sdkGroup', 1025 | participants: [ 1026 | { 1027 | id: '', 1028 | userId: '', 1029 | unreadCount: 0, 1030 | lastRead: 1581010017.596, 1031 | }, 1032 | ], 1033 | metadata: {}, 1034 | }, 1035 | }; 1036 | ``` 1037 | 1038 | #### beforeDisplay 1039 | 1040 | The `beforeDisplay` delegate allows a message to be hidden or modified before it is displayed in the conversation. This delegate should return a falsy value such as `null` to hide the message. It can also return a modified message object in order to change what the user will see rendered in their conversation history. Note that this change affects the client side rendering only; the server side copy of this message can not be modified by this delegate. 1041 | 1042 | Learn more about filtering and transforming messages in [our guide](https://docs.smooch.io/guide/web-messenger#filtering-and-transforming-messages). 1043 | 1044 | ```javascript 1045 | Smooch.init({ 1046 | integrationId: '', 1047 | delegate: { 1048 | beforeDisplay(message, data) { 1049 | if (data.conversation.id === '' && message.metadata && message.metadata.isHidden) { 1050 | return null; 1051 | } 1052 | 1053 | return message; 1054 | }, 1055 | }, 1056 | }); 1057 | ``` 1058 | 1059 | #### beforeSend 1060 | 1061 | The `beforeSend` delegate method allows you to modify properties of a message before sending it to Smooch. 1062 | The modified message must be returned for it to take effect. 1063 | 1064 | A common usage of this method is to [add message metadata](https://docs.smooch.io/guide/using-metadata/#sdks-and-metadata). 1065 | 1066 | Note that when a file or an image is uploaded, only the message `metadata` may be updated. Other message properties such as `type` or `text` won't be considered. 1067 | 1068 | ```javascript 1069 | Smooch.init({ 1070 | integrationId: '' 1071 | delegate: { 1072 | beforeSend(message, data) { 1073 | if (data.conversation.id === '') { 1074 | message.metadata = { 1075 | any: 'info' 1076 | }; 1077 | } 1078 | 1079 | return message; 1080 | } 1081 | } 1082 | }); 1083 | ``` 1084 | 1085 | #### beforePostbackSend 1086 | 1087 | The `beforePostbackSend` delegate method allows you to modify properties of a postback before sending it to Smooch. 1088 | The modified postback must be returned for it to take effect. 1089 | 1090 | A common usage of this method is to [add postback metadata](https://docs.smooch.io/guide/web-messenger#transforming-postback). 1091 | 1092 | ```javascript 1093 | Smooch.init({ 1094 | integrationId: '', 1095 | delegate: { 1096 | beforePostbackSend(postback, data) { 1097 | if (data.conversation.id === '') { 1098 | postback.metadata = { 1099 | any: 'info', 1100 | }; 1101 | } 1102 | 1103 | return postback; 1104 | }, 1105 | }, 1106 | }); 1107 | ``` 1108 | 1109 | #### onInvalidAuth 1110 | 1111 | The `onInvalidAuth` delegate notifies the delegate of a failed request due to invalid credentials and allows the implementer to set a new auth token in order to retry the request. The delegate returns a `Promise` that resolves a new valid JWT asynchronously. 1112 | 1113 | ```javascript 1114 | Smooch.init({ 1115 | integrationId: '', 1116 | delegate: { 1117 | onInvalidAuth() { 1118 | return new Promise((resolve) => resolve('')); 1119 | }, 1120 | }, 1121 | }); 1122 | ``` 1123 | 1124 | ### Events 1125 | 1126 | If you want to make sure your events are triggered, try to bind them before calling `Smooch.init`. 1127 | 1128 | To bind an event, use `Smooch.on(, );`. To unbind events, you can either call `Smooch.off(, handler)` to remove one specific handler, call `Smooch.off()` to remove all handlers for an event, or call `Smooch.off()` to unbind all handlers. 1129 | 1130 | #### ready 1131 | 1132 | ```javascript 1133 | // This event triggers when init completes successfully... Be sure to bind before calling init! 1134 | Smooch.on('ready', function(){ 1135 | console.log('the init has completed!'); 1136 | }); 1137 | 1138 | Smooch.init(...).then(function() { 1139 | // init also returns a promise, so you can alternatively specify a .then() callback 1140 | }); 1141 | ``` 1142 | 1143 | #### destroy 1144 | 1145 | ```javascript 1146 | // This event triggers when the widget is destroyed. 1147 | Smooch.on('destroy', function () { 1148 | console.log('the widget is destroyed!'); 1149 | }); 1150 | 1151 | Smooch.destroy(); 1152 | ``` 1153 | 1154 | #### participant:added 1155 | 1156 | ```javascript 1157 | // This event triggers when a participant is added to a conversation 1158 | Smooch.on('participant:added', function (participant, data) { 1159 | console.log(`A participant was added to conversation ${data.conversation.id}: `, participant); 1160 | }); 1161 | ``` 1162 | 1163 | #### participant:removed 1164 | 1165 | ```javascript 1166 | // This event triggers when a participant is removed from a conversation 1167 | Smooch.on('participant:removed', function (participant, data) { 1168 | console.log(`A participant was removed from conversation ${data.conversation.id}: `, participant); 1169 | }); 1170 | ``` 1171 | 1172 | #### conversation:added 1173 | 1174 | ```javascript 1175 | // This event triggers when a conversation is added 1176 | Smooch.on('conversation:added', function (participants, data) { 1177 | console.log(`Conversation ${data.conversation.id} was added with following participants: `, participants); 1178 | }); 1179 | ``` 1180 | 1181 | #### conversation:read 1182 | 1183 | ```javascript 1184 | // This event triggers when a participant in a sdkGroup chat reads a message 1185 | Smooch.on('conversation:read', function (payload, data) { 1186 | if (payload.role === 'business') { 1187 | console.log(`Conversation ${data.conversation.id} was read by the business`); 1188 | } else if (payload.role === 'user') { 1189 | console.log(`Conversation ${data.conversation.id} was read by userId: ${payload.userId}`); 1190 | } 1191 | }); 1192 | 1193 | // Payload and data objects. If the conversation was read by the business, the userId property will not exist 1194 | payload = { 1195 | userId: '', 1196 | lastRead: 1581010017.596, 1197 | role: 'user', 1198 | }; 1199 | 1200 | data = { 1201 | conversation: { 1202 | id: '', 1203 | }, 1204 | }; 1205 | ``` 1206 | 1207 | #### conversation:removed 1208 | 1209 | ```javascript 1210 | // This event triggers when a conversation is removed 1211 | Smooch.on('conversation:removed', function (data) { 1212 | console.log(`Conversation ${data.conversation.id} was removed`); 1213 | }); 1214 | 1215 | // data object 1216 | data = { 1217 | conversation: { 1218 | id: '', 1219 | }, 1220 | }; 1221 | ``` 1222 | 1223 | #### message:received 1224 | 1225 | ```javascript 1226 | // This event triggers when the user receives a message 1227 | Smooch.on('message:received', function (message, data) { 1228 | console.log(`The user received a message in conversation ${data.conversation.id}: `, message); 1229 | }); 1230 | 1231 | // data object 1232 | data = { 1233 | conversation: { 1234 | id: '', 1235 | }, 1236 | }; 1237 | ``` 1238 | 1239 | #### message:sent 1240 | 1241 | ```javascript 1242 | // This event triggers when the user sends a message 1243 | Smooch.on('message:sent', function (message, data) { 1244 | console.log(`The user sent a message in conversation ${data.conversation.id}: `, message); 1245 | }); 1246 | 1247 | // data object 1248 | data = { 1249 | conversation: { 1250 | id: '', 1251 | }, 1252 | }; 1253 | ``` 1254 | 1255 | #### message 1256 | 1257 | ```javascript 1258 | // This event triggers when a message was added to the conversation 1259 | Smooch.on('message', function (message, data) { 1260 | console.log(`A message was added in the conversation ${data.conversation.id}: `, message); 1261 | }); 1262 | 1263 | // data object 1264 | data = { 1265 | conversation: { 1266 | id: '', 1267 | }, 1268 | }; 1269 | ``` 1270 | 1271 | #### unreadCount 1272 | 1273 | ```javascript 1274 | // This event triggers when the number of unread messages changes 1275 | Smooch.on('unreadCount', function (unreadCount, data) { 1276 | console.log(`the number of unread messages was updated for conversation ${data.conversation.id}:`, unreadCount); 1277 | }); 1278 | 1279 | // data object 1280 | data = { 1281 | conversation: { 1282 | id: '', 1283 | }, 1284 | }; 1285 | ``` 1286 | 1287 | #### widget:opened 1288 | 1289 | ```javascript 1290 | // This event triggers when the widget is opened 1291 | Smooch.on('widget:opened', function () { 1292 | console.log('Widget is opened!'); 1293 | }); 1294 | ``` 1295 | 1296 | #### widget:closed 1297 | 1298 | ```javascript 1299 | // This event triggers when the widget is closed 1300 | Smooch.on('widget:closed', function () { 1301 | console.log('Widget is closed!'); 1302 | }); 1303 | ``` 1304 | 1305 | #### log:debug 1306 | 1307 | ```javascript 1308 | // This event triggers when the codes emits debug information 1309 | Smooch.on('log:debug', function (e) { 1310 | console.log('Timestamp:', e.timestamp); // (Float) Date.now() when it was emitted 1311 | console.log('Message:', e.message); // (String) Message being logged 1312 | console.log('Data:', e.data); // (Object) Extra details to be logged 1313 | }); 1314 | ``` 1315 | 1316 | #### connected 1317 | 1318 | ```javascript 1319 | // This event triggers when an active connection has been established for the first time, 1320 | // or when the connection has been re-established after a `disconnected` or `reconnecting` event. 1321 | Smooch.on('connected', function (data) { 1322 | console.log('Connected with conversation', data.conversation.id); 1323 | }); 1324 | ``` 1325 | 1326 | #### disconnected 1327 | 1328 | ```javascript 1329 | // This event triggers when an active connection is lost 1330 | // While disconnected, the client will not be able to receive messages or load a conversation 1331 | Smooch.on('disconnected', function (data) { 1332 | console.log('Disconnected with conversation', data.conversation.id); 1333 | }); 1334 | 1335 | // data object 1336 | data = { 1337 | conversation: { 1338 | id: '', 1339 | }, 1340 | }; 1341 | ``` 1342 | 1343 | #### reconnecting 1344 | 1345 | ```javascript 1346 | // This event triggers when an active connection is lost and there is an attempt to reconnect 1347 | // While reconnecting, the client will not be able to receive messages or load a conversation 1348 | Smooch.on('reconnecting', function (data) { 1349 | console.log('Reconnecting with conversation', data.conversation.id); 1350 | }); 1351 | 1352 | // data object 1353 | data = { 1354 | conversation: { 1355 | id: '', 1356 | }, 1357 | }; 1358 | ``` 1359 | 1360 | #### typing:start 1361 | 1362 | ```javascript 1363 | // This event triggers when the business starts typing. The associated conversation is passed in the argument. 1364 | Smooch.on('typing:start', function (data) { 1365 | console.log(`${data.name} started typing!`, data.conversation.id); 1366 | }); 1367 | 1368 | // If the name and avatarUrl for the typing user is known it will be available as properties in the data object 1369 | 1370 | // Data object 1371 | data = { 1372 | conversation: { 1373 | id: '', 1374 | }, 1375 | avatarUrl: 'http://path.com/to/avatar-url-of-user', 1376 | name: 'Name of Typing User', 1377 | }; 1378 | ``` 1379 | 1380 | #### typing:stop 1381 | 1382 | ```javascript 1383 | // This event triggers when the business stops typing. The associated conversation is passed in the argument. 1384 | Smooch.on('typing:stop', function (data) { 1385 | console.log(`${data.name} stopped typing!`, data.conversation.id); 1386 | }); 1387 | 1388 | // data object 1389 | data = { 1390 | conversation: { 1391 | id: '', 1392 | }, 1393 | }; 1394 | ``` 1395 | 1396 | ### Embedded mode 1397 | 1398 | As describe above, to activate the embedded mode, you need to pass `embedded: true` when calling `Smooch.init`. By doing so, you are disabling the auto-rendering mechanism and you will need to call `Smooch.render` manually. This method accepts a DOM element which will be used as the container where the widget will be rendered. 1399 | 1400 | ```javascript 1401 | Smooch.init({ 1402 | integrationId: '', 1403 | embedded: true, 1404 | }).then(() => { 1405 | var user = Smooch.getUser(); 1406 | // your code 1407 | }); 1408 | 1409 | Smooch.render(document.getElementById('chat-container')); 1410 | ``` 1411 | 1412 | Be sure to place `.render()` outside of the `.init().then()` function. If you place it inside the function, a race condition happens and unexpected results can occur. 1413 | 1414 | The embedded widget will take full width and height of the container. You must give it a height, otherwise, the widget will collapse. 1415 | 1416 | ### Authenticating the user: init() vs login() 1417 | 1418 | For [authenticated user scenarios](https://docs.smooch.io/guide/authenticating-users/), a user's credentials can be passed in to either `init()` or `login()`. The question remains: when should you use which? 1419 | 1420 | When `init()` is called without an `externalId` and `jwt`, the UI will be initialized in an anonymous user context, and the user will be able to send messages as an anonymous user. After `init()` has completed, `login()` may be called to authenticate the user and resume any existing conversation. This is useful if you want your users to be able to send messages before they've logged in to your website. Once a user does login and the browser is issued a valid `jwt`, `login()` may be called so that the user may continue the conversation in an authenticated session. Note that this may trigger a [merge event](https://docs.smooch.io/guide/merging-users/#merging-because-of-a-login-event) if the anonymous user already exists in Sunshine Conversations at the time of calling `login()`. 1421 | 1422 | If however your use case requires that all users be logged in before they may send messages, then you should consider passing `externalId` and `jwt` directly to the `init()` call upfront. 1423 | 1424 | ## Content Security Policy 1425 | 1426 | If your deployment requires [CSP compatibility](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), add the following meta tag to your configuration. 1427 | 1428 | ```html 1429 | 1450 | ``` 1451 | 1452 | Note that an equivalent configuration can be done [server side](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy). 1453 | 1454 | According to the channels you use, other domains may need to be added (these are used to display QR codes to link the Web Messenger conversation): 1455 | 1456 | - LINE: https://qr-official.line.me 1457 | - Stripe: https://\*.stripe.com 1458 | - WeChat: https://mp.weixin.qq.com 1459 | - WhatsApp: https://wa.me 1460 | 1461 | Note that your CSP configuration should also include any domains used to host images or files sent in messages. 1462 | If you require `blob:` to be excluded for `img-src`, you must disable the image upload feature via the [init settings](#initoptions). 1463 | 1464 | ## Acknowledgements 1465 | 1466 | https://github.com/lipis/flag-icon-css 1467 | --------------------------------------------------------------------------------