From 2a6517881f902c017191d8099774d3c55011d21c Mon Sep 17 00:00:00 2001 From: Brad Umbaugh Date: Mon, 8 Jul 2024 14:48:38 -0600 Subject: [PATCH] [DOCS-4729] README updates for Embedded Messaging (#412) * First round of edits * More updates to the README * Extensive updates * Further updates * minor fixes * Added some placeholders * Some minor updateS * Removing icon * Responding to Mitch's feedback * Update README.md Co-authored-by: Paul Jung * Minor fix as suggested by paul * Typo --------- Co-authored-by: Paul Jung --- README.md | 2547 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 1953 insertions(+), 594 deletions(-) diff --git a/README.md b/README.md index 39028b5d..419ce38e 100644 --- a/README.md +++ b/README.md @@ -2,182 +2,233 @@ # Iterable's Web SDK -[Iterable](https://www.iterable.com) is a growth marketing platform that helps +[Iterable](https://www.iterable.com) is a growth-marketing platform that helps you to create better experiences for—and deeper relationships with—your customers. -Use it to send customized email, SMS, push notification, in-app message, web push -notification campaigns to your customers. +Use it to send customized email, SMS, push notification, in-app message, +embedded message, and web push notification campaigns to your customers. -This SDK helps you integrate your Web apps with Iterable. +This SDK helps you integrate your web apps with Iterable. # Table of contents +- [Other documentation](#other-documentation) - [Installation](#installation) -- [API](#api) -- [Usage](#usage) +- [Functions](#functions) +- [Classes, interfaces, types, and enums](#classes-interfaces-types-and-enums) - [FAQ](#faq) -- [A Note About Imports](#a-note-about-imports) -- [About Links](#about-links) +- [Link handling](#link-handling) - [TypeScript](#typescript) - [Contributing](#contributing) - [License](#license) +# Other documentation + +This document contains reference information about the Web SDK. For other +information, please see: + +- [In-Browser Messaging Overview](https://support.iterable.com/hc/articles/4418166649748) +- [Embedded Messaging Overview](https://support.iterable.com/hc/articles/23060529977364) +- [Overview of Iterable's Web SDK](https://support.iterable.com/hc/articles/10359708795796) +- [Setting up Iterable's Web SDK](https://support.iterable.com/hc/articles/4419628585364) +- [Embedded Messages with Iterable's Web SDK](https://support.iterable.com/hc/articles/27537816889108) + +# Using the SDK + +In general, to use the SDK, you'll need to follow these steps: + +1. In Iterable, [create a JWT-enabled, web API key](https://support.iterable.com/hc/articles/360043464871). + The SDK can use this key to authenticate with Iterable's API endpoints. This + will ensure the SDK has access to all the necessary. Save the API key and + its associated JWT secret, since you'll need them both. + +2. Work with your Engineering team to create a web service the SDK can call + to fetch a valid JWT token for the signed-in user. To learn more about how + to do this, read [JWT-Enabled API Keys](https://support.iterable.com/hc/articles/360050801231). + +3. [Install](#installation) the SDK in your web app. + +4. Use the API key to initialize the SDK, as described in [`initialize`](#initialize) + and [`initializeWithConfig`](#initializewithconfig). When you initialize the + SDK, pass in a method that can call the web service (created in step 2) + to fetch a valid JWT token for the signed-in user. + +5. To identify the user to the SDK, call `setEmail` or `setUserID` (returned by + [`initialize`](#initialize) or [`initializeWithConfig`](#initializewithconfig)). + The SDK uses the user's `email` or `userId` to fetch a valid JWT token from + your server. + +6. After the SDK successfully sets the user's `email` or `userId` and the SDK + fetches a JWT token, you can make API requests to Iterable. For example, you + can call [`track`](#track) to track events, or [`getInAppMessages`](#getinappmessages) + to fetch in-app messages, etc. Other methods are described [below](#functions). + # Installation -To install this SDK through NPM: +To install the SDK, use Yarn, npm, or a `script` tag: -``` -$ npm install @iterable/web-sdk -``` +- npm -with yarn: + ``` + npm install @iterable/web-sdk + ``` -``` -$ yarn add @iterable/web-sdk -``` +- Yarn -or with a CDN: + ``` + yarn add @iterable/web-sdk + ``` -```js - -``` +- `script` tag -# Iterable's European data center (EUDC) + ```js + + ``` -If your Iterable project is hosted on Iterable's [European data center (EUDC)](https://support.iterable.com/hc/articles/17572750887444), -you'll need to configure Iterable's Web SDK to interact with Iterable's EU-based -API endpoints. +# Functions -To do this, on the web server that hosts your site, set the `IS_EU_ITERABLE_SERVICE` -environment variable to `true`. Some customers have reported issues with setting -the environment variable. If you run into this, try migrating to [`initializeWithConfig`](#initializeWithConfig). -You can then turn on the EU API usage by making these changes: +Iterable's Web SDK exposes the following functions, which you can use in your +website code. -```ts -import { initializeWithConfig } from '@iterable/web-sdk'; +For information about the data the SDK sends and receives when making calls to +Iterable's API, see the [API Overview](https://support.iterable.com/hc/articles/204780579). -const { clearRefresh, setEmail, setUserID, logout } = initializeWithConfig({ - authToken: 'my-API-key', - configOptions: { - isEuIterableService: true, - }, - /* - _email_ will be defined if you call _setEmail_ - _userID_ will be defined if you call _setUserID_ - */ - generateJWT: ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) -} -); +| Method Name | Description | +| --------------------------------------------------------------------------------- | ----------- | +| [`filterHiddenInAppMessages`](#filterhiddeninappmessages) | From an array of passed-in in-app messages, filters out messages that have already been read, messages that should not be displayed, and messages that only contain JSON data. | +| [`filterOnlyReadAndNeverTriggerMessages`](#filteronlyreadandnevertriggermessages) | From an array of passed-in in-app messages, filters out messages that have already been read and messages that should not be displayed. | +| [`getInAppMessages`](#getInAppMessages) | Fetches in-app messages by calling [`GET /api/inApp/getMessages`](https://support.iterable.com/hc/articles/204780579#get-api-inapp-getmessages). | +| [`initialize`](#initialize) | Initializes the SDK with an API key and a JWT refresh method. Returns methods you can use to identify the current user, work with JWT tokens, and log the user out (see [`WithJWT`](#withjwt)). | +| [`initializeWithConfig`](#initializeWithConfig) | Similar to `initialize`, but also takes a set of configuration options as a parameter. Returns methods you can use to identify the current user, work with JWT tokens, and log the user out (see [`WithJWT`](#withjwt)). | +| [`IterableEmbeddedCard`](#iterableembeddedcard) | Returns a string of the HTML for an out-of-the-box [card](https://support.iterable.com/hc/articles/23230946708244#cards) view for an embedded message. | +| [`IterableEmbeddedBanner`](#iterableembeddedbanner) | Returns a string of the HTML for an out-of-the-box [banner](https://support.iterable.com/hc/articles/23230946708244#banners) view for an embedded message. | +| [`IterableEmbeddedNotification`](#iterableembeddednotification) | Returns a string of the HTML for an out-of-the-box [notification](https://support.iterable.com/hc/articles/23230946708244#notifications) view for an embedded message. | +| [`sortInAppMessages`](#sortinappmessages) | Sorts an array of in-app messages by priority, and then creation date. | +| [`track`](#track) | Tracks a custom event by calling [`POST /api/events/track`](https://support.iterable.com/hc/articles/204780579#post-api-events-track). | +| [`trackEmbeddedClick`](#trackEmbeddedClick) | Tracks an [`embeddedClick`](https://support.iterable.com/hc/articles/23061677642260#embeddedclick-events) event by calling [`POST /api/embedded-messaging/events/click`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-click). | +| [`trackEmbeddedReceived`](#trackEmbeddedReceived) | Tracks an [`embeddedReceived`](https://support.iterable.com/hc/articles/23061677642260#embeddedreceived-events) event by calling [`POST /api/embedded-messaging/events/received`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-received). | +| [`trackEmbeddedSession`](#trackEmbeddedSession) | Tracks an [`embeddedSession`](https://support.iterable.com/hc/articles/23061677642260#embeddedsession-events) event and related [`embeddedImpression`](https://support.iterable.com/hc/articles/23061677642260#embeddedimpression-events) events by calling [`POST /api/embedded-messaging/events/session`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-session). | | +| [`trackInAppClick`](#trackInAppClick) | Tracks an `inAppClick` event by calling [`POST /api/events/trackInAppClick`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappclick). | +| [`trackInAppClose`](#trackInAppClose) | Tracks an `inAppClose` event by calling [`POST /api/events/trackInAppClose`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappclose). | +| [`trackInAppConsume`](#trackInAppConsume) | Deletes an in-app message from the server by calling [`POST /api/events/trackInAppConsume`](https://support.iterable.com/hc/articles/204780579#post-api-events-inappconsume). | +| [`trackInAppDelivery`](#trackInAppDelivery) | Tracks an `inAppDelivery` event by calling [`POST /api/events/trackInAppDelivery`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappdelivery). | +| [`trackInAppOpen`](#trackInAppOpen) | Tracks an `inAppOpen` event by calling [`POST /api/events/trackInAppOpen`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappopen). | +| [`trackPurchase`](#trackPurchase) | Tracks a `purchase` event by calling [`POST /api/commerce/trackPurchase`](https://support.iterable.com/hc/articles/204780579#post-api-commerce-trackpurchase). | +| [`updateCart`](#updateCart) | Updates the shopping cart items on the user's Iterable profile by calling [`POST /api/commerce/updateCart`](https://support.iterable.com/hc/articles/204780579#post-api-commerce-updatecart). | +| [`updateSubscriptions`](#updateSubscriptions) | Updates the user's subscriptions by calling [`POST /api/users/updateSubscriptions`](https://support.iterable.com/hc/articles/204780579#post-api-users-updatesubscriptions). | +| [`updateUser`](#updateUser) | Updates the data on a user's Iterable profile by calling [`POST /api/users/updateUser`](https://support.iterable.com/hc/articles/204780579#post-api-users-update). | +| [`updateUserEmail`](#updateUserEmail) | Updates the current user's `email` by calling [`POST /api/users/updateEmail`](https://support.iterable.com/hc/articles/204780579#post-api-users-updateemail). Causes the SDK to fetch a JWT for the new email address. | + +Notes: + +- The SDK does not track `inAppDelete` events. + +- :rotating_light: Due to a limitation in WebKit (which affects iOS web browsers, + like Safari), in-app messages displayed in an iOS web browser browser can't + automatically track `inAppClick` events or handle custom CTAs. This will impact + analytics for all Safari and mobile iOS users. + +## `filterHiddenInAppMessages` + +From an array of passed-in in-app messages, filters out messages that have +already been read, messages that should not be displayed, and messages that only +contain JSON data. + +```ts +const filterHiddenInAppMessages = ( + messages: Partial[] = [] +): Partial[] ``` -# API +See also: + +- [`InAppMessage`](#inappmessage) -Below are the methods this SDK exposes. See [Iterable's API Docs](https://api.iterable.com/api/docs) -for information on what data to pass and what payload to receive from the HTTP -requests. +## `filterOnlyReadAndNeverTriggerMessages` -| Method Name | Description | -| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [`getInAppMessages`](#getInAppMessages) | Either fetch and return in-app messages as a Promise or (if the `options` argument is provided) return methods to fetch, pause/resume, and/or display in-app messages. | -| [`initialize`](#initialize) | Return methods for identifying users and setting a JWT | -| [`initializeWithConfig`](#initializeWithConfig) | Return methods for identifying users and setting a JWT while also taking a set of configuration options. | -| [`refreshJwtToken`](#refreshJwtToken) | Fetch a new JWT token for the specified user and configure the SDK to use it for future requests. Only for manual token refresh. | -| [`track`](#track) | Track custom events | -| [`trackInAppClick`](#trackInAppClick) :rotating_light: | Track when a user clicks on a button or link within a message | -| [`trackInAppClose`](#trackInAppClose) | Track when an in-app message is closed | -| [`trackInAppConsume`](#trackInAppConsume) | Track when a message has been consumed. Deletes the in-app message from the server so it won't be returned anymore | -| [`trackInAppDelivery`](#trackInAppDelivery) | Track when a message has been delivered to a user's device | -| [`trackInAppOpen`](#trackInAppOpen) | Track when a message is opened and marks it as read | -| [`trackPurchase`](#trackPurchase) | Track purchase events | -| [`updateCart`](#updateCart) | Update `shoppingCartItems` field on user profile | -| [`updateSubscriptions`](#updateSubscriptions) | Updates user's subscriptions | -| [`updateUser`](#updateUser) | Change data on a user's profile or create a user if none exists | -| [`updateUserEmail`](#updateUserEmail) | Change a user's email and reauthenticate user with the new email address (in other words, the SDK will call `setEmail` for you) | +From an array of passed-in in-app messages, filters out messages that have +already been read and messages that should not be displayed. -The SDK does not track `inAppDelete` events. +```ts +const filterOnlyReadAndNeverTriggerMessages = ( + messages: Partial[] = [] +): Partial[] +``` -:rotating_light: Due to a limitation in WebKit (which affects iOS web browsers, -Safari included) web in-app messages displayed in an iOS web browser browser -can't automatically fire trackInAppClick events or handle custom CTAs. This will -impact analytics for all Safari and mobile iOS users. +See also: -# Usage +- [`InAppMessage`](#inappmessage) -## getInAppMessages +## `getInAppMessages` -API [(see required API payload here)](https://api.iterable.com/api/docs#In-app_getMessages): +Fetches in-app messages by calling [`GET /api/inApp/getMessages`](https://support.iterable.com/hc/articles/204780579#get-api-inapp-getmessages). ```ts -getInAppMessages: ( +// Returns a promise that resolves to an InAppMessageResponse, which has an +// array of fetched in-app messages. +function getInAppMessages( + payload: InAppMessagesRequestParams +): IterablePromise; + +// Returns methods to request messages from the server, pause message display, +// restart message display, and trigger the display of a message. +function getInAppMessages( payload: InAppMessagesRequestParams, - options?: { display: 'deferred' | 'immediate' } -) => Promise | PaintInAppMessageData; -``` - -:rotating_light: Notice: v1.0.0 of this SDK deprecates support for -`showMessagesAutomatically?: boolean`. If needed, please update your -getInAppMessages requests to use `options: { display: 'deferred' | 'immediate' -}` instead. - -SDK-specific Options: - -Along with the API parameters, you can pass these options to the SDK method to -have in-app messages behave differently. - -| Property Name | Description | Value | Default | -| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | ----------- | -| animationDuration | How long (in ms) it should take messages to animate in and out | `number` | `400` | -| bottomOffset | How much space (px or %) to create between the bottom of the screen and a message. Not applicable for center, top, or full-screen messages. | `string` | `undefined` | -| displayInterval | How long (in ms) to wait before showing the next in-app message after closing the currently opened one | `number` | `30000` | -| handleLinks | How to open links. If `undefined`, use browser-default behavior. `open-all-new-tab` opens all in new tab, `open-all-same-tab` opens all in same tab, `external-new-tab` opens only off-site links in new tab, otherwise same tab. Overrides the target attribute defined on link elements. | `'open-all-new-tab' \| 'open-all-same-tab' \| 'external-new-tab'` | `undefined` | -| onOpenScreenReaderMessage | The text a screen reader should read when opening the message. | `string` | `undefined` | -| onOpenNodeToTakeFocus | The DOM element that should receive keyboard focus when the in-app message opens. Any query selector is valid. If not specified, the first interactive element receives focus. | `string` | `undefined` | -| rightOffset | The amount of space (px or %) to create between the right of the screen and the message. Not applicable for center or full-screen messages. | `string` | `undefined` | -| topOffset | How much space (px or %) to create between the top of the screen and a message. Not applicable for center, bottom, or full-screen messages. | `string` | `undefined` | -| closeButton | Properties that define a custom close button to display on a message. | `CloseButtonOptions` (see below) | `undefined` | - -Close Button Options: - -| Property Name | Description | Value | Default | -| -------------------------- | ---------------------------------------------------------------------------- | -------------------------- | ------------- | -| color | The button's color (does not affect custom icons) | `string` | `undefined` | -| iconPath | Custom pathname to an image or SVG to use (instead of the default "X") | `string` | `undefined` | -| position | Where the button should display on an in-app message | `'top-right \| 'top-left'` | `'top-right'` | -| isRequiredToDismissMessage | If `true`, users cannot dismiss in-app messages by clicking outside of them. | `boolean` | `undefined` | -| sideOffset | How much space to leave between the button and side of the container | `string` | `'4%'` | -| size | How large to set the width, height, and font-size | `string \| number` | `24` | -| topOffset | How much space to leave between the button and the top of the container | `string` | `'4%'` | + options: { + display: DisplayOptions; + } +): GetInAppMessagesResponse -Example: +``` -Calling `getInAppMessages` with `options` not set returns a JSON response from -Iterable. This response includes an `inAppMessages` field, and each item in the -list has a `content.html` field that's an `iframe` with an embedded in-app -message. The `iframe`'s `sandbox` attribute is set, isolating its render and -preventing any malicious JavaScript execution. +`payload` options (see [`InAppMessagesRequestParams`](#inappmessagesrequestparams)): + +| Property Name | Description | Value | Default | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | ----------- | +| `animationDuration` | How long (in ms) it should take messages to animate in and out | `number` | `400` | +| `bottomOffset` | How much space (px or %) to create between the bottom of the screen and a message. Not applicable for center, top, or full-screen messages. | `string` | `undefined` | +| `closeButton` | Properties that define a custom close button to display on a message. | `CloseButtonOptions` (see below) | `undefined` | +| `displayInterval` | How long (in ms) to wait before showing the next in-app message after closing the currently open one | `number` | `30000` | +| `handleLinks` | How to open links. If `undefined`, use browser-default behavior. `open-all-new-tab` opens all in new tab, `open-all-same-tab` opens all in same tab, `external-new-tab` opens only off-site links in new tab, otherwise same tab. Overrides the target attribute defined on link elements. | `'open-all-new-tab' \| 'open-all-same-tab' \| 'external-new-tab'` | `undefined` | +| `onOpenNodeToTakeFocus` | The DOM element that should receive keyboard focus when the in-app message opens. Any query selector is valid. If not specified, the first interactive element receives focus. | `string` | `undefined` | +| `onOpenScreenReaderMessage` | The text a screen reader should read when opening the message. | `string` | `undefined` | +| `rightOffset` | The amount of space (px or %) to create between the right of the screen and the message. Not applicable for center or full-screen messages. | `string` | `undefined` | +| `topOffset` | How much space (px or %) to create between the top of the screen and a message. Not applicable for center, bottom, or full-screen messages. | `string` | `undefined` | + +`closeButton` options (see [`CloseButton`](#closebutton)): + +| Property Name | Description | Value | Default | +| --------------------------- | ---------------------------------------------------------------------------- | -------------------------- | ------------- | +| `color` | The button's color (does not affect custom icons) | `string` | `undefined` | +| `iconPath` | Custom pathname to an image or SVG to use (instead of the default "X") | `string` | `undefined` | +| `isRequiredToDismissMessage`| If `true`, users cannot dismiss in-app messages by clicking outside of them. | `boolean` | `undefined` | +| `position` | Where the button should display on an in-app message | `'top-right' \| 'top-left'`| `'top-right'` | +| `sideOffset` | How much space to leave between the button and side of the container | `string` | `'4%'` | +| `size` | How large to set the width, height, and font-size | `string \| number` | `24` | +| `topOffset` | How much space to leave between the button and the top of the container | `string` | `'4%'` | + +Example: ```ts import { getInAppMessages } from '@iterable/web-sdk'; getInAppMessages({ count: 20, packageName: 'mySite1' }) .then((resp) => { - /* This will be an iframe element that can be attached to the DOM */ + // This is an iframe element that can be attached to the DOM const messageIframe = resp.data.inAppMessages[0].content.html; document.body.appendChild(messageIframe); - - /* Additional styling logic can be done here to customly render the message */ + // Additional styling logic can be done here to render the message in a + // custom way }) .catch(); ``` -This code places an in-app on the page, but it won't be visible. To render it, -you'll need to modify the page's CSS, setting up whatever styles you'd like. -You'll also need to set up click handlers to handle closing the message and -tracking events (in-app click, etc.). +This code, which doesn't include the `options` parameter, fetches in-app messages +from Iterable and places the first one on the page. However, it won't be visible. +To render it, modify the page's CSS to display the message as necessary. You'll +also need to set up click handlers to handle click events, close the message, +etc. -Or, to show messages automatically: +Here's some example code that shows messages automatically: ```ts import { getInAppMessages } from '@iterable/web-sdk'; @@ -188,7 +239,7 @@ const { request, pauseMessageStream, resumeMessageStream } = getInAppMessages( packageName: 'my-website', displayInterval: 5000, onOpenScreenReaderMessage: - 'hey screen reader here telling you something just popped up on your screen!', + 'The screen reader will read this', onOpenNodeToTakeFocus: 'input', closeButton: { color: 'red', @@ -202,8 +253,8 @@ const { request, pauseMessageStream, resumeMessageStream } = getInAppMessages( request().then().catch(); ``` -Or, if you want to show messages with your own custom filtering/sorting and -choose to display later: +This example uses custom sorting and filtering, and displays messages at the +app's discretion: ```ts import { @@ -222,8 +273,7 @@ const { count: 20, packageName: 'my-website', displayInterval: 5000, - onOpenScreenReaderMessage: - 'hey screen reader here telling you something just popped up on your screen!', + onOpenScreenReaderMessage: 'The screen reader will read this', onOpenNodeToTakeFocus: 'input', closeButton: { color: 'red', @@ -236,485 +286,1797 @@ const { request() .then((response) => { - /* do your own manipulation here */ - const filteredMessages = doStuffToMessages(response.data.inAppMessages); + // Do your own manipulation here + const filteredMessages = yourOwnSortingAndFiltering(response.data.inAppMessages); - /* also feel free to take advantage of the sorting/filtering methods used internally */ + // Or, feel free to take advantage of the sorting/filtering methods used + // internally const furtherManipulatedMessages = sortInAppMessages( filterHiddenInAppMessages(response.data.inAppMessages) ) as InAppMessage[]; - /* then display them whenever you want */ + // Then display them whenever you want triggerDisplayMessages(furtherManipulatedMessages); }) .catch(); ``` -:rotating_light: PLEASE NOTE, If you choose the `deferred` option, the SDK will -**not** do any filtering or sorting on the messages internally. You will get the -messages exactly as they come down from the API, untouched. This means you may -(for example) show in-app messages marked `read` or show the messages in the -wrong order based on `priority`. +:rotating_light: With the `deferred` option, the SDK does **not** filter or sort +the messages. The messages come back exactly as retrieved from the API, without +modification. This means that you may (for example) show in-app messages marked as +`read`, or show messages in the default order (based on `priority`), rather +than a custom order that you control. + +In this case, to apply the SDK's default sorting and filtering, use the +[`sortInAppMessages`](#sortinappmessages) and [`filterHiddenInAppMessages`](#filterhiddeninappmessages) +methods. Also, see [`filterOnlyReadAndNeverTriggerMessages`](#filteronlyreadandnevertriggermessages), +which is similar to `filterHiddenInAppMessages` but does not filter out +JSON-only messages. + +Notes: + +- :rotating_light: [v1.0.0](https://github.com/Iterable/iterable-web-sdk/releases/tag/v1.0.0) + of this SDK removes support for `showMessagesAutomatically?: boolean`. If needed, + please update your `getInAppMessages` requests to use `options: { display: 'deferred' | 'immediate' }`. + +See also: + +- [`DisplayOptions`](#displayoptions) +- [`GetInAppMessagesResponse`](#getinappmessagesresponse) +- [`InAppMessagesRequestParams`](#inappmessagesrequestparams) +- [`InAppMessageResponse`](#inappmessageresponse) +- [`IterablePromise`](#iterablepromise) + +## `initialize` + +Initializes the SDK with an API key and a JWT refresh method. Returns methods +you can use to identify the current user, work with JWT tokens, and log the +user out (see [`WithJWT`](#withjwt)). + +```ts +function initialize( + authToken: string, + generateJWT: (payload: GenerateJWTPayload) => Promise +): WithJWT; +``` + +`generateJWT` should be a function that takes a `userId` or `email` and uses +it to fetch, from your server, a valid JWT token for that user. The function +should return the token as a string. + +Example: + +```ts +import { initialize } from '@iterable/web-sdk'; + +const { clearRefresh, setEmail, setUserID, logout } = initialize( + '', + // email will be defined if you call setEmail + // userID_ will be defined if you call setUserID + ({ email, userID }) => + yourAsyncJWTGeneratorMethod({ email, userID }).then( + ({ jwt_token }) => jwt_token + ) +); +``` + +See also: + +- [`GenerateJWTPayload`](#generatejwtpayload) +- [`WithJWT`](#withjwt) + +## `initializeWithConfig` + +Similar to `initialize`, but also takes a set of configuration options as a +parameter. Returns methods you can use to identify the current user, work with +JWT tokens, and log the user out (see [`WithJWT`](#withjwt)). + +The configuration options you can pass to this function are useful if you +need to [point the SDK to Iterable's EU API endpoints](#iterables-european-data-center-eudc) +or [allow JavaScript execution in Safari tabs](#safari-allowing-javascript-execution-in-tabs-opened-by-in-app-message-link-clicks). + +```ts +function initializeWithConfig(initializeParams: WithJWTParams): WithJWT; +``` + +Example: + +```ts +import { initializeWithConfig } from '@iterable/web-sdk'; + +const { clearRefresh, setEmail, setUserID, logout } = initializeWithConfig({ + authToken: '', + configOptions: { + isEuIterableService: false, + dangerouslyAllowJsPopups: true, + }, + + // email will be defined if you call setEmail + // userID will be defined if you call setUserID + generateJWT: ({ email, userID }) => + yourAsyncJWTGeneratorMethod({ email, userID }).then( + ({ jwt_token }) => jwt_token + ) +} +); +``` + +`generateJWT` should be a function that takes a `userId` or `email` and uses +it to fetch, from your server, a valid JWT token for that user. The function +should return the token as a string. + +See also: + +- [`WithJWT`](#withjwt) +- [`WithJWTParams`](#withjwtparams) + +## `IterableEmbeddedCard` + +Returns a string of the HTML for an out-of-the-box [card](https://support.iterable.com/hc/articles/23230946708244#cards) +view for an embedded message. + +```ts +const emptyElement = { + id: '', + styles: '' +}; + +function IterableEmbeddedCard({ + appPackageName, + message, + htmlElements = { + parent: emptyElement, + img: emptyElement, + title: emptyElement, + primaryButton: emptyElement, + secondaryButton: emptyElement, + body: emptyElement, + buttonsDiv: emptyElement, + textTitle: emptyElement + }, + errorCallback +}: OOTB): string +``` + +Parameters: + +- `appPackageName` – The package name you use to identify your website to + Iterable's Web SDK. +- `message` – The `IterableEmbeddedMessage` object that represents the + message you want to display. +- `htmlElements` – Custom styles (type [`Elements`](#elements)) for the SDK to use + when displaying the embedded message. For details, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). +- `errorCallback` – A callback that the SDK calls if it encounters an error + when tracking [`embeddedClick`](https://support.iterable.com/hc/articles/23061677642260#embeddedclick-events) + events. + +```js +import { IterableEmbeddedCard } from '@iterable/web-sdk'; + +const card = IterableEmbeddedCard({ + packageName, + message, + htmlElements, + errorCallback: (error) => console.log('handleError: ', error) +}); +``` + +To display the message, set the `innerHTML` of an HTML element to the string +returned by `IterableEmbeddedCard`. + +For more info, see: + +- [Out-of-the-Box Views](https://support.iterable.com/hc/articles/27537816889108#out-of-the-box-views). +- For default card styles, see the [`src/components/card/styles.ts`](https://github.com/Iterable/iterable-web-sdk/blob/main/src/components/card/styles.ts) + in the Web SDK GitHub repository. +- To learn how to apply custom styles, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). + +Also see: + +- [`Elements`](#elements) +- [`OOTB`](#ootb) + +## `IterableEmbeddedBanner` + +Returns a string of the HTML for an out-of-the-box [banner](https://support.iterable.com/hc/articles/23230946708244#banners) +view for an embedded message. + +```ts +function IterableEmbeddedBanner({ + appPackageName, + message, + htmlElements = { + parent: emptyElement, + img: emptyElement, + title: emptyElement, + primaryButton: emptyElement, + secondaryButton: emptyElement, + body: emptyElement, + buttonsDiv: emptyElement, + textTitle: emptyElement, + textTitleImg: emptyElement + }, + errorCallback +}: OOTB): string +``` + +Parameters: + +- `appPackageName` – The package name you use to identify your website to + Iterable's Web SDK. +- `message` – The `IterableEmbeddedMessage` object that represents the message + you want to display. +- `htmlElements` – Custom styles (type [`Elements`](#elements)) for the SDK to use + when displaying the embedded message. For details, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). +- `errorCallback` – A callback that the SDK calls if it encounters an error + when tracking [`embeddedClick`](https://support.iterable.com/hc/articles/23061677642260#embeddedclick-events) + events. + +For example: + +```js +import { IterableEmbeddedBanner } from '@iterable/web-sdk'; + +const banner = IterableEmbeddedBanner({ + packageName, + message, + htmlElements, + errorCallback: (error) => console.log('handleError: ', error) +}); +``` + +To display the message, set the `innerHTML` of an HTML element to the string +returned by `IterableEmbeddedBanner`. + +For more info, see: + +- [Creating an Out-of-the-Box View](https://support.iterable.com/hc/articles/27537816889108). +- For default banner styles, see the [`src/components/banner/styles.ts`](https://github.com/Iterable/iterable-web-sdk/blob/main/src/components/banner/styles.ts) + in the Web SDK GitHub repository. +- To learn how to apply custom styles, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). + +Also see: + +- [`OOTB`](#ootb) +- [`Elements`](#elements) + +## `IterableEmbeddedNotification` + +Returns a string of the HTML for an out-of-the-box [notification](https://support.iterable.com/hc/articles/23230946708244#notifications) +view for an embedded message. + +```ts +function IterableEmbeddedNotification({ + appPackageName, + message, + htmlElements = { + parent: emptyElement, + title: emptyElement, + primaryButton: emptyElement, + secondaryButton: emptyElement, + body: emptyElement, + buttonsDiv: emptyElement, + textTitle: emptyElement + }, + errorCallback +}: OOTB): string +``` + +Parameters: + +- `appPackageName` – The package name you use to identify your website to + Iterable's Web SDK. +- `message` – The `IterableEmbeddedMessage` object that represents the message + you want to display. +- `htmlElements` – Custom styles (type [`Elements`](#elements)) for the SDK to use + when displaying the embedded message. For details, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). +- `errorCallback` – A callback that the SDK calls if it encounters an error + when tracking [`embeddedClick`](https://support.iterable.com/hc/articles/23061677642260#embeddedclick-events) + events. + +```js +import { IterableEmbeddedNotification } from '@iterable/web-sdk'; + +const notification = IterableEmbeddedNotification({ + packageName, + message, + htmlElements, + errorCallback: (error) => console.log('handleError: ', error) +}); +``` + +To display the message, set the `innerHTML` of an HTML element to the string +returned by `IterableEmbeddedNotification`. + +For more info, see: + +- [Creating an Out-of-the-Box View](https://support.iterable.com/hc/articles/27537816889108). +- For default notification styles, see the [`src/components/notification/styles.ts`](https://github.com/Iterable/iterable-web-sdk/blob/main/src/components/notification/styles.ts) +- To learn how to apply custom styles, see [Custom Styles](https://support.iterable.com/hc/articles/27537816889108#custom-styles). + +Also see: + +- [`OOTB`](#ootb) +- [`Elements`](#elements) + +## `sortInAppMessages` + +Sorts an array of in-app messages by priority, and then creation date. + +```ts +const sortInAppMessages = (messages: Partial[] = []) => { + return messages.sort(by(['priorityLevel', 'asc'], ['createdAt', 'asc'])); +}; +``` + +In-app messages can have these [priority values](https://support.iterable.com/hc/articles/7412316462996#display-priority): + +- Low - `priorityLevel` of 400.5 +- Medium - `priorityLevel` of 300.5 +- High - `priorityLevel` of 200.5 +- Critical - `priorityLevel` of 100.5 +- Proof - `priorityLevel` of 100.0 + +Also see: + +- [`InAppMessage`](#inappmessage) + +## `track` + +Tracks a custom event by calling [`POST /api/events/track`](https://support.iterable.com/hc/articles/204780579#post-api-events-track). + +```ts +track: (payload: InAppTrackRequestParams): IterablePromise +``` + +Example: + +```ts +import { track } from '@iterable/web-sdk'; + +track({ eventName: 'my-event' }).then().catch(); +``` + +See also: + +- [`InAppTrackRequestParams`](#inapptrackrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackEmbeddedClick` + +Tracks an [`embeddedClick`](https://support.iterable.com/hc/articles/23061677642260#embeddedclick-events) +event by calling [`POST /api/embedded-messaging/events/click`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-click). + +```ts +const trackEmbeddedClick = ( + payload: IterableEmbeddedClickRequestPayload +): IterablePromise +``` + +Example: + +```js +import { trackEmbeddedReceived } from '@iterable/web-sdk'; + +trackEmbeddedClick({ + messageId: message.metadata.messageId, + buttonIdentifier: button.id, + clickedUrl: defaultUrl, + appPackageName: packageName +}).then((response) => { + if (response.status != 200) { + console.log("Failure tracking embedded click") + } +}).catch((error) => { + console.log("Error tracking embedded click: ", error); +}); +``` + +See also: + +- [`IterableEmbeddedClickRequestPayload`](#iterableembeddedclickrequestpayload) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackEmbeddedReceived` + +Tracks an [`embeddedReceived`](https://support.iterable.com/hc/articles/23061677642260#embeddedreceived-events) +event by calling [`POST /api/embedded-messaging/events/received`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-received). + +Generally, there's no need to call this method, since the SDK automatically +tracks an `embeddedReceived` event for each message it fetches from the server. + +```ts +const trackEmbeddedReceived = ( + messageId: string, + appPackageName: string +): IterablePromise +``` + +Example: + +```ts +import { trackEmbeddedReceived } from '@iterable/web-sdk'; + +trackEmbeddedReceived(messageId, packageName) + .then((response: any) => { + setTrackResponse(JSON.stringify(response.data)); + setTrackingEvent(false); + }) + .catch((error: any) => { + setTrackResponse(JSON.stringify(error.response.data)); + setTrackingEvent(false); + }); +``` + +See also: + +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackEmbeddedSession` + +Tracks an [`embeddedSession`](https://support.iterable.com/hc/articles/23061677642260#embeddedsession-events) +event and related [`embeddedImpression`](https://support.iterable.com/hc/articles/23061677642260#embeddedimpression-events) +events by calling [`POST /api/embedded-messaging/events/session`](https://support.iterable.com/hc/articles/204780579#post-api-embedded-messaging-events-session). + +Generally, rather than calling this method, you'll track sessions and impresions +using the SDK's [`IterableEmbeddedSessionManager`](#iterableembeddedsessionmanager). + +```ts +const trackEmbeddedSession = ( + payload: IterableEmbeddedSessionRequestPayload +): IterablePromise +``` + +Example: + +```ts +import { trackEmbeddedSession } from '@iterable/web-sdk'; + +trackEmbeddedSession(sessionData) + .then((response: any) => { + setTrackResponse(JSON.stringify(response.data)); + setTrackingEvent(false); + }) + .catch((error: any) => { + setTrackResponse(JSON.stringify(error.response.data)); + setTrackingEvent(false); + }); +``` + +See also: + +- [`IterableEmbeddedSessionRequestPayload`](#iterableembeddedsessionrequestpayload) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackInAppClick` + +Tracks an `inAppClick` event by calling [`POST /api/events/trackInAppClick`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappclick). + +```ts +const trackInAppClick = ( + payload: Omit, + sendBeacon = false +): IterablePromise +``` + +Example: + +```ts +import { trackInAppClick } from '@iterable/web-sdk'; + +trackInAppClick({ + messageId: '123', + deviceInfo: { appPackageName: 'my-website' } +}) + .then() + .catch(); +``` + +See also: + +- [`InAppEventRequestParams`](#inappeventrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackInAppClose` + +Tracks an `inAppClose` event by calling [`POST /api/events/trackInAppClose`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappclose). + +```ts +const trackInAppClose = (payload: InAppEventRequestParams): IterablePromise +``` + +Example: + +```ts +import { trackInAppClose } from '@iterable/web-sdk'; + +trackInAppClose({ + messageId: '123', + deviceInfo: { appPackageName: 'my-website' } +}) + .then() + .catch(); +``` + +See also: + +- [`InAppEventRequestParams`](#inappeventrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackInAppConsume` + +Deletes an in-app message from the server by calling [`POST /api/events/trackInAppConsume`](https://support.iterable.com/hc/articles/204780579#post-api-events-inappconsume). + +```ts +const trackInAppConsume = ( + payload: Omit< + InAppEventRequestParams, + 'clickedUrl' | 'closeAction' | 'inboxSessionId' + > +): IterablePromise +``` + +Example: + +```ts +import { trackInAppConsume } from '@iterable/web-sdk'; + +trackInAppConsume({ + messageId: '123', + deviceInfo: { appPackageName: 'my-website' } +}) + .then() + .catch(); +``` + +See also: + +- [`InAppEventRequestParams`](#inappeventrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackInAppDelivery` + +Tracks an `inAppDelivery` event by calling [`POST /api/events/trackInAppDelivery`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappdelivery). + +```ts +const trackInAppDelivery = ( + payload: Omit< + InAppEventRequestParams, + 'clickedUrl' | 'closeAction' | 'inboxSessionId' + > +): IterablePromise +``` + +Example: + +```ts +import { trackInAppDelivery } from '@iterable/web-sdk'; + +trackInAppDelivery({ + messageId: '123', + deviceInfo: { appPackageName: 'my-website' } +}) + .then() + .catch(); +``` + +See also: + +- [`InAppEventRequestParams`](#inappeventrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackInAppOpen` + +Tracks an `inAppOpen` event by calling [`POST /api/events/trackInAppOpen`](https://support.iterable.com/hc/articles/204780579#post-api-events-trackinappopen). + +```ts +const trackInAppOpen = ( + payload: Omit< + InAppEventRequestParams, + 'clickedUrl' | 'inboxSessionId' | 'closeAction' + > +): IterablePromise +``` + +Example: + +```ts +import { trackInAppOpen } from '@iterable/web-sdk'; + +trackInAppOpen({ + messageId: '123', + deviceInfo: { appPackageName: 'my-website' } +}) + .then() + .catch(); +``` + +See also: + +- [`InAppEventRequestParams`](#inappeventrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `trackPurchase` + +Tracks a `purchase` event by calling [`POST /api/commerce/trackPurchase`](https://support.iterable.com/hc/articles/204780579#post-api-commerce-trackpurchase). + +```ts +const trackPurchase = (payload: TrackPurchaseRequestParams): IterablePromise +``` + +Example: + +```ts +import { trackPurchase } from '@iterable/web-sdk'; + +trackPurchase({ + items: [{ id: '123', name: 'keyboard', price: 100, quantity: 2 }], + total: 200 +}) + .then() + .catch(); +``` + +See also: + +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) +- [`TrackPurchaseRequestParams`](#trackpurchaserequestparams) + +## `updateCart` + +Updates the shopping cart items on the user's Iterable profile by calling [`POST /api/commerce/updateCart`](https://support.iterable.com/hc/articles/204780579#post-api-commerce-updatecart). + +```ts +const updateCart = (payload: UpdateCartRequestParams): IterablePromise +``` + +Example: + +```ts +import { updateCart } from '@iterable/web-sdk'; + +updateCart({ + items: [{ id: '123', price: 100, name: 'keyboard', quantity: 1 }] +}) + .then() + .catch(); +``` + +See also: + +- [`UpdateCartRequestParams](#updatecartrequestparams) +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +## `updateSubscriptions` + +Updates the user's subscriptions by calling [`POST /api/users/updateSubscriptions`](https://support.iterable.com/hc/articles/204780579#post-api-users-updatesubscriptions). + +```ts +const updateSubscriptions = ( + payload: Partial = {} +): IterablePromise +``` + +Example: + +```ts +import { updateSubscriptions } from '@iterable/web-sdk'; + +updateSubscriptions({ emailListIds: [1, 2, 3] }) + .then() + .catch(); +``` + +See also: + +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) +- [`UpdateSubscriptionParams`](#updatesubscriptionparams) + +## `updateUser` + +Updates the data on a user's Iterable profile by calling [`POST /api/users/updateUser`](https://support.iterable.com/hc/articles/204780579#post-api-users-update). + +```ts +const updateUser = (payload: UpdateUserParams = {}): IterablePromise +``` + +Example: + +```ts +import { updateUser } from '@iterable/web-sdk'; + +updateUser({ dataFields: {} }).then().catch(); +``` + +See also: + +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) +- [`UpdateUserParams`](#updateuserparams) + +## `updateUserEmail` + +Updates the current user's `email` by calling [`POST /api/users/updateEmail`](https://support.iterable.com/hc/articles/204780579#post-api-users-updateemail). +Causes the SDK to fetch a JWT for the new email address. + +```ts +updateUserEmail: (newEmail: string): IterablePromise +``` + +Example: + +```ts +import { updateUserEmail } from '@iterable/web-sdk'; + +updateUserEmail('user@example.com').then().catch(); +``` + +See also: + +- [`IterablePromise`](#iterablepromise) +- [`IterableResponse`](#iterableresponse) + +# Classes, interfaces, types, and enums + +This section describes classes, interfaces, and enums to be aware of when working +with Embedded Messaging in Iterable's Web SDK. + +| Type | Description | +| --------------------------------------------------------------------------------- | ----------- | +| [`CloseButton`](#closebutton) | Specifies how the SDK should display a close button in a fetched in-app message. Passed as part of [`InAppMessagesRequestParams`](#inappmessagesrequestparams). | +| [`CloseButtonPosition`](#closebuttonposition) | Specifies the position of a close button on an in-app message. | +| [`CommerceItem`](#commerceitem) | An item being purchased or added to a shopping cart. Include when calling [`trackPurchase`](#trackpurchase) or [`updateCart`](#updatecart). | +| [`CommerceUser`](#commerceuser) | Information about the user associated with a purchase or cart update. Include when calling [`trackPurchase`](#trackpurchase) or [`updateCart`](#updatecart). | +| [`DisplayOptions`](#displayoptions) | Display options to pass to [`getInAppMessages`](#getinappmessages) to indicate whether messages should be displayed immediately or later. | +| [`DisplayPosition`](#displayposition) | Describes where an in-app message should be displayed. Part of [`WebInAppDisplaySettings`](#webinappdisplaysettings). | +| [`Elements`](#elements) | Custom styles to apply to `IterableEmbeddedCard`, `IterableEmbeddedBanner`, and `IterableEmbeddedNotification` views for embedded messages. | +| [`GenerateJWTPayload`](#generatejwtpayload) | The payload to pass to the `generateJWT` function when calling [`initialize`](#initialize) or [`initializeWithConfig`](#initializewithconfig). | +| [`ErrorHandler`](#errorhandler) | An error-handling function. Passed as a parameter to [`IterableEmbeddedCard`](#iterableembeddedcard), [`IterableEmbeddedBanner`](#iterableembeddedbanner), and [`IterableEmbeddedNotification`](#iterableembeddednotification), which use the method to handle errors when tracking `embeddedClick` events. | +| [`GetInAppMessagesResponse`](#getinappmessagesresponse) | Return value for [`getInAppMessages`](#getinappmessages), when it's called without the `options` parameter. | +| [`HandleLinks`](#handlelinks) | Describes where in-app links should be opened. Part of [`InAppMessagesRequestParams`](#inappmessagesrequestparams). | +| [`InAppMessage`](#inappmessage) | A single in-app message. | +| [`InAppDisplaySetting`](#inappdisplaysetting) | Display settings for an in-app message, including padding percentages. | +| [`InAppEventRequestParams`](#inappeventrequestparams) | Data to pass to [`trackInAppClick`](#trackinappclick), [`trackInAppClose`](#trackinappclose), [`trackInAppConsume`](#trackinappconsume), [`trackInAppDelivery`](#trackinappdelivery), and [`trackInAppOpen`](#trackinappopen). | +| [`InAppMessagesRequestParams`](#inappmessagesrqeuestparams) | Data to pass to [`getInAppMessages`](#getinappmessages). | +| [`InAppMessageResponse`](#inappmessageresponse) | Return value for [`getInAppMessages`](#getinappmessages), when it's called with the `options` parameter. | +| [`InAppTrackRequestParams`](#inapptrackrequestparams) | Data to pass to [`track`](#track). | +| [`IterableAction`](#iterableaction) | An action associated with a click. The type of the action, and its associated URL. | +| [`IterableActionContext`](#iterableactioncontext) | Information about the context of an `IterableAction`. For example, the associated message type. Only used with embedded messages. | +| [`IterableActionSource`](#iterableactionsource) | An enum of possible message types to which an `IterableAction` can be associated. Currently, only `EMBEDDED` is supported. | +| [`IterableConfig`](#iterableconfig) | A class that can hold configuration information for the SDK. Currently, only `urlHandler` and `customActionHandler` are supported (static properties), and these are only invoked for URLs and custom actions coming from embedded messages. | +| [`IterableCustomActionHandler`](#iterablecustomactionhandler) | An interface that defines `handleIterableCustomAction`, which the SDK can call to handle custom action URLs (`action://`) URLs that result from from clicks on embedded messages. | +| [`IterableEmbeddedButton`](#iterableembeddedbutton) | Payload for a button associated with an embedded message. | +| [`IterableEmbeddedButtonAction`](#iterableembeddedbuttonaction) | Payload for the action associated with an embedded message button. | +| [`IterableEmbeddedClickRequestPayload`](#iterableembeddedclickrequestpayload) | Data to pass to [`trackEmbeddedClick`](#trackembeddedclick). | +| [`IterableEmbeddedDefaultAction`](#iterableembeddeddefaultaction) | The default action associated with an embedded message. Invoked when a user clicks on an embedded message, but outside of its buttons. | +| [`IterableEmbeddedElements`](#iterableembeddedelements) | Content associated with an embedded message — title, body, media URL, buttons, default action, and extra text fields. | +| [`IterableEmbeddedImpression`](#iterableembeddedimpression) | The number of times a given embedded message appeared during a specific session, and the total duration of all those appearances. Also includes other metadata about the impression. | +| [`IterableEmbeddedManager`](#iterableembeddedmanager) | Used to fetch embedded messages from Iterable, and pass them to application code as necessary. | +| [`IterableEmbeddedMessage`](#iterableembeddedmessage) | A single embedded message to display, including title text, body text, buttons, an image URL, click actions, text fields, and JSON data. | +| [`IterableEmbeddedMessageUpdateHandler`](#iterableembeddedmessageupdatehandler) | An object that defines `onMessagesUpdated` and `onEmbeddedMessagingDisabled` methods. If this object is registered as an update listener for embedded messages (you can do this by calling `addUpdateListener` on [`IterableEmbeddedManager`](#iterableembeddedmanager)), the SDK calls these methods as necessary after fetching embedded messages from the server. | +| [`IterableEmbeddedMetadata`](#iterableembeddedmetadata) | Identifying information about an embedded message. | +| [`IterableEmbeddedSession`](#iterableembeddedsession) | Represents a period of time during which a user was on a page where they could potentially view embedded messages. Contains an ID, a start time, and an end time. | +| [`IterableEmbeddedSessionManager`](#iterableembeddedsessionmanager) | Used to track sessions and impressions, and to save them back to Iterable. | +| [`IterableEmbeddedSessionRequestPayload`](#iterableembeddedsessionrequestpayload) | Data to pass to [`trackEmbeddedSession`](#trackembeddedsession). You won't usually interact manually with this interface, since the [`IterableEmbeddedSessionManager`](#iterableembeddedsessionmanager) handles the tracking of sessions and impressions for you. | +| [`IterableEmbeddedText`](#iterableembeddedtext) | Extra text fields sent along with an embedded message. Like custom JSON, these text fields can be used to pass data as part of an embedded message. | +| [`IterableErrorStatus`](#iterableerrorstatus) | Errors that can come back with an [`IterableResponse`](#iterableresponse). | +| [`IterablePromise`](#iterablepromise) | A promise. | +| [`IterableResponse`](#iterableresponse) | A response from Iterable's API. | +| [`IterableUrlHandler`](#iterableurlhandler) | An interface that defines `handleIterableURL`, which the SDK can call to handle standard URLs (`https://`, `custom://`, but not `action://`) that result from from clicks on embedded messages. | +| [`OOTB`](#ootb) | A type that defines the parameters to provide when calling `IterableEmbeddedCard`, `IterableEmbeddedBanner`, and `IterableEmbeddedNotification`. | +| [`Options`](#options) | Configuration options to pass to [`initializeWithConfig`](#initializewithconfig). | +| [`OutOfTheBoxButton`](#outoftheboxbutton) | Custom styles to apply to buttons in an embedded message. The same as `OutOfTheBoxElement`, but with an extra `disabledStyles` string. | +| [`OutOfTheBoxElement`](#outoftheboxelement) | The custom styles to apply to a single element of an embedded message. | +| [`SDKInAppMessagesParams`](#sdkinappmessagesparams) | Parent interface for [`InAppMessagesRequestParams`](#inappmessagesrequestparams). | +| [`TrackPurchaseRequestParams`](#trackpurchaserequestparams) | Parameters to pass to [`trackPurchase`](#trackpurchase). | +| [`UpdateCartRequestParams`](#updatecartrequestparams) | Data to pass to [`updateCart`](#updatecart). | +| [`UpdateSubscriptionParams`](#updatesubscriptionparams) | Data to pass to [`updateSubscriptions`](#updatesubscriptions). | +| [`UpdateUserParams`](#updateuserparams) | Data to pass to [`updateUser`](#updateuser). | +| [`WebInAppDisplaySettings`](#webinappdisplaysettings) | An object that contains information about how to display the associated in-app message. | +| [`WithJWT`](#withjwt) | Return value from [`initialize`](#initialize) and [`initializeWithConfig`](#initializeWithConfig). | +| [`WithJWTParams`](#withjwtparams) | Parameters to pass to [`initializeWithConfig`](#initializewithconfig). | + +## `CloseButton` + +Specifies how the SDK should display a close button a fetched in-app message. +Passed as part of [`InAppMessagesRequestParams`](#inappmessagesrequestparams). + +```ts +type CloseButton = { + color?: string; + iconPath?: string; + // If true, prevent user from dismissing in-app message by clicking outside + // of message + isRequiredToDismissMessage?: boolean; + position?: CloseButtonPosition; + sideOffset?: string; + size?: string | number; + topOffset?: string; +}; +``` + +See also: + +- [`CloseButtonPosition`](#closebuttonposition) + +## `CloseButtonPosition` + +Specifies the position of a close button on an in-app message. + +```ts +declare enum CloseButtonPosition { + TopLeft = "top-left", + TopRight = "top-right" +} +``` + +## `CommerceItem` + +An item being purchased or added to a shopping cart. Include when calling +[`trackPurchase`](#trackpurchase) or [`updateCart`](#updatecart). + +```ts +interface CommerceItem { + id: string; + sku?: string; + name: string; + description?: string; + categories?: string[]; + price: number; + quantity: number; + imageUrl?: string; + url?: string; + dataFields?: Record; +} +``` + +## `CommerceUser` + +Information about the user associated with a purchase or cart update. Include +when calling [`trackPurchase`](#trackpurchase) or [`updateCart`](#updatecart). + +```ts +interface CommerceUser { + dataFields?: Record; + preferUserId?: boolean; + mergeNestedObjects?: boolean; +} +``` + +## `DisplayOptions` + +Display options to pass to [`getInAppMessages`](#getinappmessages) to indicate +whether messages should be displayed immediately or later. + +```ts +declare enum DisplayOptions { + Immediate = "immediate", + Deferred = "deferred" +} +``` + +## `DisplayPosition` + +Describes where an in-app message should be displayed. Part of [`WebInAppDisplaySettings`](#webinappdisplaysettings). + +```ts +declare enum DisplayPosition { + Center = "Center", + TopRight = "TopRight", + BottomRight = "BottomRight", + Full = "Full" +} +``` + +See also: + +- [`WebInAppDisplaySettings`](#webinappdisplaysettings) + +## `Elements` + +Custom styles to apply to `IterableEmbeddedCard`, `IterableEmbeddedBanner`, and +`IterableEmbeddedNotification` views for embedded messages. + +```ts +type Elements = { + // img div + img?: OutOfTheBoxElement; + // title div + title?: OutOfTheBoxElement; + // primary button div + primaryButton?: OutOfTheBoxButton; + // secondary button div + secondaryButton?: OutOfTheBoxButton; + // body button div + body?: OutOfTheBoxElement; + // root OOTB div + parent?: OutOfTheBoxElement; + // button wrapper div + buttonsDiv?: OutOfTheBoxElement; + // title and parent wrapper div + textTitle?: OutOfTheBoxElement; + // textTitleImg div + textTitleImg?: OutOfTheBoxElement; +}; +``` + +See also: + +- [`OutOfTheBoxElement`](#outoftheboxelement) +- [`OutOfTheBoxButton`](#outoftheboxbutton) + +## `GenerateJWTPayload` + +The payload to pass to the `generateJWT` function when calling [`initialize`](#initialize) +or [`initializeWithConfig`](#initializewithconfig). + +```ts +interface GenerateJWTPayload { + email?: string; + userID?: string; +} +``` + +## `ErrorHandler` + +An error-handling function. Passed as a parameter to [`IterableEmbeddedCard`](#iterableembeddedcard), +[`IterableEmbeddedBanner`](#iterableembeddedbanner), and [`IterableEmbeddedNotification`](#iterableembeddednotification), +which use the method to handle errors when tracking `embeddedClick` events. + +```ts +interface ErrorHandler { + (error: any): void; +} +``` + +## `GetInAppMessagesResponse` + +Return value for [`getInAppMessages`](#getinappmessages), when it's called without +the `options` parameter. + +```ts +interface GetInAppMessagesResponse { + pauseMessageStream: () => void; + resumeMessageStream: () => Promise; + request: () => IterablePromise; + triggerDisplayMessages: ( + messages: Partial[] + ) => Promise; +} +``` + +## `HandleLinks` + +Describes where in-app links should be opened. Part of [`InAppMessagesRequestParams`](#inappmessagesrequestparams). + +```ts +declare enum HandleLinks { + OpenAllNewTab = "open-all-new-tab", + OpenAllSameTab = "open-all-same-tab", + ExternalNewTab = "external-new-tab" +} +``` + +## `InAppMessage` + +A single in-app message. + +```ts +interface InAppMessage { + messageId: string; + campaignId: number; + createdAt: number; + expiresAt: number; + content: { + payload?: Record; + html: string | HTMLIFrameElement; + inAppDisplaySettings: { + top: InAppDisplaySetting; + right: InAppDisplaySetting; + left: InAppDisplaySetting; + bottom: InAppDisplaySetting; + bgColor?: { + alpha: number; + hex: string; + }; + shouldAnimate?: boolean; + }; + webInAppDisplaySettings: WebInAppDisplaySettings; + }; + customPayload: Record; + trigger: { + type: string; + }; + saveToInbox: boolean; + inboxMetadata: { + title: string; + subtitle: string; + icon: string; + }; + priorityLevel: number; + read: boolean; +} +``` + +See also: + +- [`InAppDisplaySetting`](#inappdisplaysetting) +- [`WebInAppDisplaySettings`](#webinappdisplaysettings) + +## `InAppDisplaySetting` + +Display settings for an in-app message, including padding percentages. + +```ts +interface InAppDisplaySetting { + percentage?: number; + displayOption?: string; +} +``` + +## `InAppEventRequestParams` + +Data to pass to [`trackInAppClick`](#trackinappclick), [`trackInAppClose`](#trackinappclose), +[`trackInAppConsume`](#trackinappconsume), [`trackInAppDelivery`](#trackinappdelivery), and +[`trackInAppOpen`](#trackinappopen). + +```ts +interface InAppEventRequestParams { + messageId: string; + clickedUrl?: string; + messageContext?: { + saveToInbox?: boolean; + silentInbox?: boolean; + location?: string; + }; + closeAction?: string; + deviceInfo: { + appPackageName: string; + }; + inboxSessionId?: string; + createdAt?: number; +} +``` + +## `InAppMessagesRequestParams` + +Data to pass to [`getInAppMessages`](#getinappmessages). + +```ts +interface InAppMessagesRequestParams extends SDKInAppMessagesParams { + count: number; + SDKVersion?: string; + packageName: string; +} +``` + +See also: + +- [`SDKInAppMessagesParams`](#sdkinappmessagesparams) + +## `InAppMessageResponse` + +Return value for [`getInAppMessages`](#getinappmessages), when it's called with +the `options` parameter. + +```ts +interface InAppMessageResponse { + inAppMessages: Partial[]; +} +``` + +See also: + +- [`InAppMessage`](#inappmessage) + +## `InAppTrackRequestParams` + +Data to pass to [`track`](#track). + +```ts +interface InAppTrackRequestParams { + eventName: string; + id?: string; + createdAt?: number; + dataFields?: Record; + campaignId?: number; + templateId?: number; +} +``` + +## `IterableAction` + +An action associated with a click. The type of the action, and its associated +URL. Only used with embedded messages. + +```ts +interface IterableAction { + type: string; + data: string; +} +``` + +The values for `type` and `data` depend on the type of action assigned to the +campaign in Iterable: + +- For **Open URL** actions, `type` is `openUrl` and `data` contains the URL. +- For **Custom action** actions, `type` is the URL, and `data` is empty. + +## `IterableActionContext` + +Information about the context of an `IterableAction`. For example, the +associated message type. Only used with embedded messages. + +```ts +interface IterableActionContext { + action: IterableAction; + source: IterableActionSource; +} +``` + +See also: + +- [`IterableAction`](#iterableaction) +- [`IterableActionSource`](#iterableactionsource) + +## `IterableActionSource` + +An enum of possible message types to which an `IterableAction` can be associated. +Currently, only `EMBEDDED` is supported. + +```ts +enum IterableActionSource { + EMBEDDED = 'EMBEDDED' +} +``` + +## `IterableConfig` + +A class that can hold configuration information for the SDK. Currently, only +`urlHandler` and `customActionHandler` are supported (static properties), and +these are only invoked for URLs and custom actions coming from embedded messages. + +```ts +class IterableConfig { + public static urlHandler: IterableUrlHandler | null = null; + public static customActionHandler: IterableCustomActionHandler | null = null; +} +``` + +See also: + +- [`IterableUrlHandler`](#iterableurlhandler) +- [`IterableCustomActionHandler`](#iterablecustomactionhandler) + +## `IterableCustomActionHandler` + +An interface that defines `handleIterableCustomAction`, which the SDK can call to +handle custom action URLs (`action://`) URLs that result from from clicks on +embedded messages. + +```ts +interface IterableCustomActionHandler { + handleIterableCustomAction( + action: IterableAction, + actionContext: IterableActionContext + ): boolean; +} +``` + +See also: + +- [`IterableAction`](#iterableaction) +- [`IterableActionContext`](#iterableactioncontext) + +## `IterableEmbeddedButton` + +Payload for a button associated with an embedded message. + +```ts +interface IterableEmbeddedButton { + id: string; + title?: string; + action?: IterableEmbeddedButtonAction; +} +``` + +See also: + +- [`IterableEmbeddedButtonAction`](#iterableembeddedbuttonaction) + +## `IterableEmbeddedButtonAction` + +Payload for the action associated with an embedded message button. + +```ts +interface IterableEmbeddedButtonAction { + type: string; + data?: string; +} +``` + +The values for `type` and `data` depend on the type of action assigned to the +campaign in Iterable: + +- For **Open URL** actions, `type` is `openUrl` and `data` contains the URL. +- For **Custom action** actions, `type` is the URL, and `data` is empty. + +## `IterableEmbeddedClickRequestPayload` + +Data to pass to [`trackEmbeddedClick`](#trackembeddedclick). + +```ts +interface IterableEmbeddedClickRequestPayload { + messageId: string; + buttonIdentifier: string; + targetUrl: string; + appPackageName: string; +} +``` + +## `IterableEmbeddedDefaultAction` + +The default action associated with an embedded message. Invoked when a user +clicks on an embedded message, but outside of its buttons. + +```ts +interface IterableEmbeddedDefaultAction { + type: string; + data?: string; +} +``` + +The values for `type` and `data` depend on the type of action assigned to the +campaign in Iterable: + +- For **Open URL** actions, `type` is `openUrl` and `data` contains the URL. +- For **Custom action** actions, `type` is the URL, and `data` is empty. + +## `IterableEmbeddedElements` + +Content associated with an embedded message — title, body, media URL, +buttons, default action, and extra text fields. + +```ts +interface IterableEmbeddedElements { + title?: string; + body?: string; + mediaUrl?: string; + buttons?: IterableEmbeddedButton[]; + text?: IterableEmbeddedText[]; + defaultAction?: IterableEmbeddedDefaultAction; +} +``` + +See also: + +- [`IterableEmbeddedButton`](#iterableembeddedbutton) +- [`IterableEmbeddedText`](#iterableembeddedtext) +- [`IterableEmbeddedDefaultAction`](#iterableembeddeddefaultaction) + +## `IterableEmbeddedImpression` + +The number of times a given embedded message appeared during a specific session, +and the total duration of all those appearances. Also includes other metadata +about the impression. + +```ts +interface IterableEmbeddedImpression { + messageId: string; + displayCount: number; + displayDuration: number; + placementId?: number; +} +``` + +## `IterableEmbeddedManager` + +Used to fetch embedded messages from Iterable, and pass them to application code +as necessary. + +```ts +class IterableEmbeddedManager { + appPackageName: string; + constructor(appPackageName: string); + syncMessages(packageName: string, callback: () => void, placementIds?: number[]): Promise; + getMessages(): IterableEmbeddedMessage[]; + getMessagesForPlacement(placementId: number): IterableEmbeddedMessage[]; + addUpdateListener(updateListener: IterableEmbeddedMessageUpdateHandler): void; + getUpdateHandlers(): IterableEmbeddedMessageUpdateHandler[]; + click(clickedUrl: string | null): void; +} +``` + +Descriptions: + +- `appPackageName` – The package name you use to identify your website. Set + this value by passing it to the constructror. + +- `syncMessages` – Fetches embedded messages for which the signed-in user is + eligible. If `placementIds` is provided, fetches only messages for those + placements. Calls `callback` after fetching messages. + +- `getMessages` – Returns all embedded messages that the SDK has already fetched. + Does not fetch messages from the server. + +- `getMessagesForPlacement` – Returns all embedded messages for a given placement + ID. Does not fetch messages from the server. + +- `addUpdateListener` – Registers an object that implements the + `IterableEmbeddedMessageUpdateHandler` interface. The SDK calls the object's + `onMessagesUpdated` and `onEmbeddedMessagingDisabled` methods as necessary + after fetching embedded messages from the server. + +- `getUpdateHandlers` – Returns all objects that have been registered as update + listeners. -If you want to keep the default sorting and filtering, please take advantage of -the `sortInAppMessages` and `filterHiddenInAppMessages` methods the SDK -provides. Also see `filterOnlyReadAndNeverTriggerMessages`, which is similar to -`filterHiddenInAppMessages` but does not filter out JSON-only messages. +- `click` – Passes the provided URL (depending on its type) to the URL handler + or custom action handler defined on `IterableConfig`. `action://` URLs are + passed to the custom action handler, and other URLs are passed to the URL + handler. The SDK does not currently support `iterable://` URLs for + embedded messages. -## initialize +See also: -API: +- [`IterableEmbeddedMessage`](#iterableembeddedmessage) +- [`IterableEmbeddedMessageUpdateHandler`](#iterableembeddedmessageupdatehandler) +- [`IterableConfig`](#iterableconfig) +- [`IterableUrlHandler`](#iterableurlhandler) +- [`IterableCustomActionHandler`](#iterablecustomactionhandler) -```ts -initialize: (authToken: string, generateJWT: ({ email?: string, userID?: string }) => Promise) => { - clearRefresh: () => void; - setEmail: (email: string) => Promise; - setUserID: (userId: string) => Promise; - logout: () => void; -} -``` +## `IterableEmbeddedMessage` -Example: +A single embedded message to display, including title text, body text, buttons, +an image URL, click actions, text fields, and JSON data. ```ts -import { initialize } from '@iterable/web-sdk'; - -const { clearRefresh, setEmail, setUserID, logout } = initialize( - 'my-API-key', - /* - _email_ will be defined if you call _setEmail_ - _userID_ will be defined if you call _setUserID_ - */ - ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) -); +interface IterableEmbeddedMessage { + metadata: IterableEmbeddedMetadata; + elements?: IterableEmbeddedElements; + payload?: Record; +} ``` -## initializeWithConfig +See also: -API: +- [`IterableEmbeddedMetadata`](#iterableembeddedmetadata) +- [`IterableEmbeddedElements`](#iterableembeddedelements) -```ts -type Options = { - logLevel: 'none' | 'verbose'; - baseURL: string; - isEuIterableService: boolean; - dangerouslyAllowJsPopups: boolean; -}; +## `IterableEmbeddedMessageUpdateHandler` -interface InitializeParams { - authToken: string; - configOptions: Partial; - generateJWT?: (payload: GenerateJWTPayload) => Promise; -} +An object that defines `onMessagesUpdated` and `onEmbeddedMessagingDisabled` +methods. If this object is registered as an update listener for embedded messages +(you can do this by calling `addUpdateListener` on [`IterableEmbeddedManager`](#iterableembeddedmanager)), +the SDK calls these methods as necessary after fetching embedded messages from +the server. -initializeWithConfig: (initializeParams: InitializeParams) => { - clearRefresh: () => void; - setEmail: (email: string) => Promise; - setUserID: (userId: string) => Promise; - logout: () => void; +```ts +interface IterableEmbeddedMessageUpdateHandler { + onMessagesUpdated: () => void; + onEmbeddedMessagingDisabled: () => void; } ``` -Example: +Descriptions: -```ts -import { initializeWithConfig } from '@iterable/web-sdk'; +- `onMessagesUpdated` – Called by the SDK after it fetches embedded messages + from Iterable. Use this method to display messages. -const { clearRefresh, setEmail, setUserID, logout } = initializeWithConfig({ - authToken: 'my-API-key', - configOptions: { - isEuIterableService: false, - dangerouslyAllowJsPopups: true, - }, - /* - _email_ will be defined if you call _setEmail_ - _userID_ will be defined if you call _setUserID_ - */ - generateJWT: ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) -} -); -``` +- `onEmbeddedMessagingDisabled` – Called by the SDK if there are errors fetching + embedded messages from Iterable. Use this method to display an empty state + or hide the placement. -## refreshJwtToken +## `IterableEmbeddedMetadata` -API: +Identifying information about an embedded message. ```ts -refreshJwtToken: (authTypes: string) => Promise; +interface IterableEmbeddedMetadata { + messageId: string; + campaignId?: number; + isProof?: boolean; + placementId?: number; +} ``` -Example: +## `IterableEmbeddedSession` -```ts -import { initialize } from '@iterable/web-sdk'; +Represents a period of time during which a user was on a page where they could +potentially view embedded messages. Contains an ID, a start time, and an end +time. -refreshJwtToken('user@example.com').then().catch(); +```ts +interface IterableEmbeddedSession { + id: string; + start?: number; + end?: number; +} ``` -## track +## `IterableEmbeddedSessionManager` -API [(see required API payload here)](https://api.iterable.com/api/docs#events_track): +Used to track sessions and impressions, and to save them back to Iterable. ```ts -track: (payload: InAppTrackRequestParams) => Promise; +class IterableEmbeddedSessionManager { + appPackageName: string; + session: EmbeddedSession; + constructor(appPackageName: string); + startSession(): void; + endSession(): Promise; + startImpression(messageId: string, placementId: number): void; + pauseImpression(messageId: string): void; +} ``` -Example: +Descriptions: -```ts -import { track } from '@iterable/web-sdk'; +- `appPackageName` – The package name you use to identify your website. Set + this value by passing it to the constructor. -track({ eventName: 'my-event' }).then().catch(); -``` +- `session` – The current session. Set by calling `startSession` and `endSession`. -## trackInAppClick +- `startSession` – Starts a new session. A session is a period of time when a + user is on a page where embedded messages can be displayed. -API [(see required API payload here)](https://api.iterable.com/api/docs#events_trackInAppClick): +- `endSession` – Ends the active session, and saves data about the session and + its associated impressions back to Iterable. -```ts -trackInAppClick: (payload: InAppEventRequestParams) => Promise; -``` +- `startImpression` – Starts a new impression for a given message ID and placement + ID. An impression captures the number of times a given messages is visible during + a given session, and the total duration of all those appearances. -Example: +- `pauseImpression` – Pauses the impression for a given message ID. Call this method + when a message is no longer visible. If the message becomes visible again, + call `startImpression` to resume the impression. -```ts -import { trackInAppClick } from '@iterable/web-sdk'; +## `IterableEmbeddedSessionRequestPayload` -trackInAppClick({ - messageId: '123', - deviceInfo: { appPackageName: 'my-website' } -}) - .then() - .catch(); +Data to pass to [`trackEmbeddedSession`](#trackembeddedsession). You won't usually +interact manually with this interface, since the [`IterableEmbeddedSessionManager`](#iterableembeddedsessionmanager) +handles the tracking of sessions and impressions for you. + +```ts +interface IterableEmbeddedSessionRequestPayload { + session: IterableEmbeddedSession; + impressions?: IterableEmbeddedImpression[]; + appPackageName: string; +} ``` -## trackInAppClose +See also: -API [(see required API payload here)](https://api.iterable.com/api/docs#events_trackInAppClose): +- [`IterableEmbeddedSession`](#iterableembeddedsession) +- [`IterableEmbeddedImpression`](#iterableembeddedimpression) -```ts -trackInAppClose: (payload: InAppEventRequestParams) => Promise; -``` +## `IterableEmbeddedText` -Example: +Extra text fields sent along with an embedded message. Like custom JSON, these +text fields can be used to pass data as part of an embedded message. ```ts -import { trackInAppClose } from '@iterable/web-sdk'; - -trackInAppClose({ - messageId: '123', - deviceInfo: { appPackageName: 'my-website' } -}) - .then() - .catch(); +interface IterableEmbeddedText { + id: string; + text?: string; +} ``` -## trackInAppConsume +## `IterableErrorStatus` -API [(see required API payload here)](https://api.iterable.com/api/docs#events_inAppConsume): +Errors that can come back with an [`IterableResponse`](#iterableresponse). ```ts -trackInAppConsume: (payload: InAppEventRequestParams) => - Promise; +type IterableErrorStatus = + | 'Success' + | 'BadApiKey' + | 'BadParams' + | 'BadJsonBody' + | 'QueueEmailError' + | 'GenericError' + | 'InvalidEmailAddressError' + | 'DatabaseError' + | 'EmailAlreadyExists' + | 'Forbidden' + | 'JwtUserIdentifiersMismatched' + | 'InvalidJwtPayload'; ``` -Example: +## `IterablePromise` -```ts -import { trackInAppConsume } from '@iterable/web-sdk'; +A promise. -trackInAppConsume({ - messageId: '123', - deviceInfo: { appPackageName: 'my-website' } -}) - .then() - .catch(); +```ts +IterablePromise = AxiosPromise; ``` -## trackInAppDelivery +## `IterableResponse` -API [(see required API payload here)](https://api.iterable.com/api/docs#events_trackInAppDelivery): +A response from Iterable's API. ```ts -trackInAppDelivery: (payload: InAppEventRequestParams) => - Promise; +interface IterableResponse { + code: IterableErrorStatus; + msg: string; + params?: null | Record; +} ``` -Example: +## `IterableUrlHandler` -```ts -import { trackInAppDelivery } from '@iterable/web-sdk'; +An interface that defines `handleIterableURL`, which the SDK can call to handle +standard URLs (`https://`, `custom://`, but not `action://`) that result from +from clicks on embedded messages. -trackInAppDelivery({ - messageId: '123', - deviceInfo: { appPackageName: 'my-website' } -}) - .then() - .catch(); +```ts +interface IterableUrlHandler { + handleIterableURL(uri: string, actionContext: IterableActionContext): boolean; +} ``` -## trackInAppOpen +See also: -API [(see required API payload here)](https://api.iterable.com/api/docs#events_trackInAppOpen): +- [`IterableActionContext`](#iterableactioncontext) +- [`IterableConfig`](#iterableconfig) +- [`IterableEmbeddedManager`](#iterableembeddedmanager) -```ts -trackInAppOpen: (payload: InAppEventRequestParams) => Promise; -``` +## `OOTB` -Example: +A type that defines the parameters to provide when calling +`IterableEmbeddedCard`, `IterableEmbeddedBanner`, and +`IterableEmbeddedNotification`. ```ts -import { trackInAppOpen } from '@iterable/web-sdk'; - -trackInAppOpen({ - messageId: '123', - deviceInfo: { appPackageName: 'my-website' } -}) - .then() - .catch(); +type OOTB = { + appPackageName: string; + message: IterableEmbeddedMessage; + htmlElements?: Elements; + // Callback method to handle button or element click errors + errorCallback?: ErrorHandler; +}; ``` -## trackPurchase +See also: -API [(see required API payload here)](https://api.iterable.com/api/docs#commerce_trackPurchase): +- [`Elements`](#elements) +- [`IterableEmbeddedBanner`](#iterableembeddedcard) +- [`IterableEmbeddedCard`](#iterableembeddedbanner) +- [`IterableEmbeddedNotification`](#iterableembeddednotification) +- [`IterableEmbeddedMessage`](#iterableembeddedmessage) +- [`ErrorHandler`](#errorhandler) -```ts -trackPurchase: (payload: TrackPurchaseRequestParams) => - Promise; -``` +## `Options` -Example: +Configuration options to pass to [`initializeWithConfig`](#initializewithconfig). ```ts -import { trackPurchase } from '@iterable/web-sdk'; - -trackPurchase({ - items: [{ id: '123', name: 'keyboard', price: 100, quantity: 2 }], - total: 200 -}) - .then() - .catch(); +type Options = { + logLevel: 'none' | 'verbose'; + baseURL: string; + isEuIterableService: boolean; + dangerouslyAllowJsPopups: boolean; +}; ``` -## updateCart +## `OutOfTheBoxButton` -API [(see required API payload here)](https://api.iterable.com/api/docs#commerce_updateCart): +Custom styles to apply to buttons in an embedded message. The same as +`OutOfTheBoxElement`, but with an extra `disabledStyles` string. ```ts -updateCart: (payload: UpdateCartRequestParams) => Promise; +type OutOfTheBoxButton = OutOfTheBoxElement & { + // Stringified CSS to be passed to element "style" tag. The presence of this + // value determines whether or not the button is in disabled. + disabledStyles?: string; +}; ``` -Example: +## `OutOfTheBoxElement` -```ts -import { updateCart } from '@iterable/web-sdk'; +The custom styles to apply to a single element of an embedded message. -updateCart({ - items: [{ id: '123', price: 100, name: 'keyboard', quantity: 1 }] -}) - .then() - .catch(); +```ts +type OutOfTheBoxElement = { + // id of the element + id?: string; + // Stringified CSS to be passed to element "style" tag + styles?: string; +}; ``` -## updateSubscriptions +## `SDKInAppMessagesParams` -API [(see required API payload here)](https://api.iterable.com/api/docs#users_updateSubscriptions): +Parent interface for [`InAppMessagesRequestParams`](#inappmessagesrequestparams). ```ts -updateSubscriptions: (payload?: UpdateSubscriptionParams) => - Promise; +interface SDKInAppMessagesParams { + displayInterval?: number; + onOpenScreenReaderMessage?: string; + onOpenNodeToTakeFocus?: string; + topOffset?: string; + bottomOffset?: string; + rightOffset?: string; + animationDuration?: number; + handleLinks?: HandleLinks; + closeButton?: CloseButton; + // messageId of the latest (i.e., most recent) message in the device's + // local cache + latestCachedMessageId?: string; +} ``` -Example: +See also: -```ts -import { updateSubscriptions } from '@iterable/web-sdk'; +- [`InAppMessaagesRequestParams`](#inappmessagesrequestparams) -updateSubscriptions({ emailListIds: [1, 2, 3] }) - .then() - .catch(); -``` +See also: + +- [`HandleLinks`](#handlelinks) +- [`CloseButton`](#closebutton) -## updateUser +## `TrackPurchaseRequestParams` -API [(see required API payload here)](https://api.iterable.com/api/docs#users_updateUser): +Parameters to pass to [`trackPurchase`](#trackpurchase). ```ts -updateUser: (payload?: UpdateUserParams) => Promise; +interface TrackPurchaseRequestParams { + id?: string; + user?: CommerceUser; + items: CommerceItem[]; + campaignId?: string; + templateId?: string; + total: number; + createdAt?: number; + dataFields?: Record; +} ``` -Example: - -```ts -import { updateUser } from '@iterable/web-sdk'; +See also: -updateUser({ dataFields: {} }).then().catch(); -``` +- [`CommerceUser`](#commerceuser) +- [`CommerceItem`](#commerceitem) -## updateUserEmail +## `UpdateCartRequestParams` -API [(see required API payload here)](https://api.iterable.com/api/docs#users_updateEmail): +Data to pass to [`updateCart`](#updatecart). ```ts -updateUserEmail: (newEmail: string) => Promise; +interface UpdateCartRequestParams { + user?: CommerceUser; + items: CommerceItem[]; +} ``` -Example: +See also: -```ts -import { updateUserEmail } from '@iterable/web-sdk'; +- [`CommerceUser`](#commerceuser) +- [`CommerceItem`](#commerceitem) -updateUserEmail('user@example.com').then().catch(); +## `UpdateSubscriptionParams` + +Data to pass to [`updateSubscriptions`](#updatesubscriptions). + +```ts +interface UpdateSubscriptionParams { + emailListIds: number[]; + unsubscribedChannelIds: number[]; + unsubscribedMessageTypeIds: number[]; + subscribedMessageTypeIds: number[]; + campaignId: number; + templateId: number; +} ``` -# FAQ +## `UpdateUserParams` -## How do I make API requests with the SDK? +Data to pass to `updateUser`. -First thing you need to do is generate an API key on [the Iterable -app](https://app.iterable.com). Make sure this key is JWT-enabled and is of the -_Web_ key type. This will ensure the SDK has access to all the necessary -endpoints when communicating with the Iterable API. After you generate your key, -save both the API Key and JWT Secret somewhere handy. You'll need both of them. +```ts +interface UpdateUserParams { + dataFields?: Record; + preferUserId?: boolean; + mergeNestedObjects?: boolean; +} +``` -First, you'll deal with the JWT Secret. Typically, you need some backend service -that is going to use that JWT Secret to sign a JWT and return it to your client -app. For the purposes of this explanation, this can be demonstrated this with a -site like [jwt.io](https://jwt.io). See the [documentation on the Iterable -website](https://support.iterable.com/hc/en-us/articles/360050801231-JWT-Enabled-API-Keys-) -for instructions on how to generate a JWT from your JWT secret. +## `WebInAppDisplaySettings` -Once you have a JWT or a service that can generate a JWT automatically, you're -ready to start making requests in the SDK. The syntax for that looks like this: +An object that contains information about how to display the associated in-app +message. ```ts -import { initialize } from '@iterable/web-sdk'; - -(() => { - initialize('YOUR_API_KEY_HERE', ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) - ); -})(); +interface WebInAppDisplaySettings { + position: DisplayPosition; +} ``` -Now that we've set our authorization logic within our app, it's time to set the -user. You can identify a user by either the email or user ID. User ID is -preferred because the SDK will automatically create a user in your Iterable -instance. If you identify by email, the user will remain "anonymous" with no -user ID attached to it. See [Iterable's updateUser -endpoint](https://api.iterable.com/api/docs#users_updateUser) for more -information about how users are created. +See also: -The syntax for identifying a user by user ID looks like this: +- [`DisplayPosition`](#displayposition) + +## `WithJWT` + +Return value from [`initialize`](#initialize) and [`initializeWithConfig`](#initializeWithConfig). ```ts -import { initialize } from '@iterable/web-sdk'; +interface WithJWT { + clearRefresh: () => void; + setEmail: (email: string) => Promise; + setUserID: (userId: string) => Promise; + logout: () => void; + refreshJwtToken: (authTypes: string) => Promise; +} +``` -(() => { - const { setUserID, logout } = initialize( - 'YOUR_API_KEY_HERE', - ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) - ); +Definitions: - yourAsyncLoginMethod().then((response) => { - /* this code assumes you have some backend endpoint that will return a user's ID */ - setUserID(response.user_id).then(() => { - /* now your user is set and you can begin hitting the Iterable API */ - }); - }); +- `clearRefresh` – Clears the JWT refresh timer. +- `setEmail` – Identifies the current user by `email`, and fetches a valid JWT + token by calling the `generateJWT` function passed to [`initialize`](#initialize) + or [`initializeWithConfig`](#initializeWithConfig). +- `setUserID` - Identifies the current user by `userId`, and fetches a valid JWT + token by calling the `generateJWT` function passed to [`initialize`](#initialize) + or [`initializeWithConfig`](#initializeWithConfig). +- `refreshJwtToken` – Manually refreshes the JWT token for the signed-in user. +- `logout` – Signs the current user out of the SDK. - /* optionally logout the user when you don't need to hit the Iterable API anymore */ - logout(); -})(); -``` +## `WithJWTParams` -Doing this with an email is similar: +Parameters to pass to [`initializeWithConfig`](#initializewithconfig). ```ts -import { initialize } from '@iterable/web-sdk'; +interface WithJWTParams { + authToken: string; + configOptions: Partial; + generateJWT: (payload: GenerateJWTPayload) => Promise; +} +``` -(() => { - const { setEmail, logout } = initialize( - 'YOUR_API_KEY_HERE', - ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) - ); +`generateJWT` should be a function that takes a `userId` or `email` and uses +it to fetch, from your server, a valid JWT token for that user. The function +should return the token as a string. - yourAsyncLoginMethod().then((response) => { - /* - this code assumes you have some backend - endpoint that will return a user's email address - */ - setEmail(response.email).then(() => { - /* now your user is set and you can begin hitting the Iterable API */ - }); - }); +See also: - /* optionally logout the user when you don't need to hit the Iterable API anymore */ - logout(); -})(); -``` +- [`Options`](#options) +- [`GenerateJWTPayload`](#generatejwtpayload) -Now let's put it altogether with an Iterable API method: +# FAQ -```ts -import { initialize, track } from '@iterable/web-sdk'; +## How do I use Iterable's Web SDK to fetch and display embedded messages? -(() => { - const { setUserID, logout } = initialize( - 'YOUR_API_KEY_HERE', - ({ email, userID }) => - yourAsyncJWTGeneratorMethod({ email, userID }).then( - ({ jwt_token }) => jwt_token - ) - ); +For detailed instructions about how to use Iterable's Web SDK SDK to fetch and +display embedded messages, see [Embedded Messages with Iterable's Web SDK](https://support.iterable.com/hc/articles/27537816889108). - yourAsyncLoginMethod().then((response) => { - /* this code assumes you have some backend endpoint that will return a user's ID */ - setUserID(response.user_id).then(() => { - document.getElementById('my-button').addEventListener('click', () => { - /* - no need to pass a user ID to this endpoint. - _setUserID_ takes care of this for you - */ - track({ eventName: 'button-clicked' }); - }); - }); - }); -})(); -``` +For more information about Embedded Messaging, read the [Embedded Messaging Oveview](https://support.iterable.com/hc/articles/23060529977364). -## How does the SDK pass up my email / user ID? +## How does SDK add the user's `email` or `userId` to the requests it makes to Iterable? -This SDK relies on a library called [Axios](https://github.com/axios/axios). For -all outgoing XHR requests, the SDK utilizes [Axios interceptors](https://github.com/axios/axios#interceptors) -to add your user information to the requests. +The SDK uses a library called [Axios](https://github.com/axios/axios). To add +user information to outgoing requests, the SDK uses [Axios interceptors](https://github.com/axios/axios#interceptors). -## What if I want to handle this intercepting logic myself instead? +## How can I manipulate the API requests the SDK makes to Iterable? -You can do that! This SDK exposes the base Axios request instance so you can do -whatever you like with it and build upon that. You can import the Axios request -like so and anything in the Axios documentation is fair game to use: +Iterable's Web SDK SDK exposes the base Axios request instance, which you can +modify as necessary. For example: ```ts import { baseAxiosRequest } from '@iterable/web-sdk'; ``` For example, if you want to set an `email` query param on every outgoing -request, you would just implement the way Axios advises like so: +request, you could do somethign like this: ```ts import { baseAxiosRequest } from '@iterable/web-sdk'; @@ -732,22 +2094,31 @@ import { baseAxiosRequest } from '@iterable/web-sdk'; })(); ``` -:rotating_light: Please note, you won't likely need access to this Axios -instance. This is reserved for advanced use cases only. +:rotating_light: You probably won't need to do anything with the underlying +Axios request. This is only for advanced use cases. + +## How do I add a delay between the display of multiple in-app messages? + +To add a delay between the display of multiple in-app messages: + +1. In the object you pass as the first parameter to `getInAppMessages`, set + `displayInterval` to the number of milliseconds you want to wait between + messages. -## I want to automatically show my in-app messages with a delay between each +2. In the object you pass as the second parameter to `getInAppMessages`, set + `display` to `deferred`. -This SDK allows that. Simply call the `getInAppMessages` method but pass `{ -display: 'immediate' }` as the second parameter. This will expose some methods -used to make the request to show the messages and pause and resume the queue. +Then, to show messages, pause the display of messages, and resume the display of +messages, use the methods returned by `getInAppMessages`. -Normally to request a list of in-app messages, you'd make a request like this: +For example, this code fetches in-app messages from Iterable but doesn't display +them: ```ts import { initialize, getInAppMessages } from '@iterable/web-sdk'; (() => { - const { setUserID } = initialize('YOUR_API_KEY_HERE', ({ email, userID }) => + const { setUserID } = initialize('', ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token ) @@ -766,14 +2137,13 @@ import { initialize, getInAppMessages } from '@iterable/web-sdk'; })(); ``` -In order to take advantage of the SDK showing them automatically, you would -implement the same method in this way: +This code fetches in-app messages and displays them automatically: ```ts import { initialize, getInAppMessages } from '@iterable/web-sdk'; (() => { - const { setUserID } = initialize('YOUR_API_KEY_HERE', ({ email, userID }) => + const { setUserID } = initialize('', ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token ) @@ -789,22 +2159,21 @@ import { initialize, getInAppMessages } from '@iterable/web-sdk'; { display: 'immediate' } ); - /* trigger the start of message presentation */ + // Trigger the start of message presentation request().then().catch(); }); }); })(); ``` -Optionally, you can pass arguments to fine-tune how you want the messages to -appear. See the [usage section](#getInAppMessages) to see all available options -and what they do. +This code manipulates the display of in-app messages by setting more fields in +the object passed as the first parameter to [`getInAppmessages`](#getinappmessages): ```ts import { initialize, getInAppMessages } from '@iterable/web-sdk'; (() => { - const { setUserID } = initialize('YOUR_API_KEY_HERE', ({ email, userID }) => + const { setUserID } = initialize('', ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token ) @@ -829,20 +2198,20 @@ import { initialize, getInAppMessages } from '@iterable/web-sdk'; { display: 'immediate' } ); - /* trigger the start of message presentation */ + // Trigger the start of message presentation request().then().catch(); }); }); })(); ``` -You can also pause and resume the messages stream if you like +This code pauses the display of messages, and then resumes: ```ts import { initialize, getInAppMessages } from '@iterable/web-sdk'; (() => { - const { setUserID } = initialize('YOUR_API_KEY_HERE', ({ email, userID }) => + const { setUserID } = initialize('', ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token ) @@ -859,24 +2228,21 @@ import { initialize, getInAppMessages } from '@iterable/web-sdk'; { display: 'immediate' } ); - /* trigger the start of message presentation */ + // Trigger the start of message presentation request().then().catch(); - /* pause any more in-app messages from appearing for a little while */ + // Prevent any more in-app messages from appearing for a little while pauseMessageStream(); - /* - pick up where you left off and show the next message in the queue. - And start the timer again. - */ + // Pick up where you left off — show the next message in the queue, and + // start the timer again. resumeMessageStream(); }); }); })(); ``` -Finally, you can also choose to do your own manipulation to the messages before -choosing to display them: +This code manipulates the list of in-app messages before displaying them: ```ts import { @@ -887,7 +2253,7 @@ import { } from '@iterable/web-sdk'; (() => { - const { setUserID } = initialize('YOUR_API_KEY_HERE', ({ email, userID }) => + const { setUserID } = initialize('', ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token ) @@ -904,23 +2270,21 @@ import { { display: 'deferred' } ); - /* trigger the start of message presentation */ + // Trigger the start of message presentation request() .then((response) => { - /* do your own manipulation here */ + // Do your own manipulation here const filteredMessages = doStuffToMessages( response.data.inAppMessages ); - /* - also feel free to take advantage of the sorting/filtering - methods used internally - */ + // Also, feel free to take advantage of the sorting/filtering + // methods used internally const furtherManipulatedMessages = sortInAppMessages( filterHiddenInAppMessages(response.data.inAppMessages) ) as InAppMessage[]; - /* then display them whenever you want */ + // Display them whenever you want triggerDisplayMessages(furtherManipulatedMessages); }) .catch(); @@ -929,11 +2293,11 @@ import { })(); ``` -## I want my messages to look good on every device and be responsive +## How can I make sure that in-app messages are displayed responsively? -This SDK already handles that for you. The rules for the in-app message -presentation varies based on which display type you've selected. Here's a table -to explain how it works: +The SDK handles this for you. In-app message presentation varies based on +the display type (center, full, top-right, bottom-right) you select when sending +the campaign: | Message Position →

Browser Size ↓ | Center | Full | Top-Right | Bottom-Right | | ------------------------------------------------------ | ------ | ---- | --------- | ------------ | @@ -942,92 +2306,95 @@ to explain how it works: | 976px - 1300px | 50% | 100% | 33% | 33% | | 1300px+ | 50% | 100% | 25% | 25% | -Looking at this table, you can see the browser sizes on the left, and the -display positions on top. For example, if your in-app message is positioned in -the top-right of the screen and your browser window is at 1000px, then your -in-app message will take up 33% of the screen. +For example: -Another example: If your in-app is positioned in the center and your browser if -at 700px, your in-app message will grow to take up 100% of the screen. +- If your in-app message is positioned at the top-right of the screen and your + browser window is at 1000px, your in-app message will take up 33% of the + screen. +- If your in-app is positioned in the center and your browser if at 700px, your + in-app message will grow to take up 100% of the screen. -This chart also implies that your in-app message is taking 100% of its -container. Your results may vary if you add, for example, a `max-width: 200px` -CSS rule to your message HTML. Regardless of how you write your CSS, these rules -will take effect, **so it is recommended that you stick to percentage-based CSS -widths when possible when creating your message** +This chart also implies that yout in-app message is taking 100% of its container. +Your results may vary if you add, for example, a `max-width: 200px` CSS rule to +your message HTML. -## Clicking links breaks the experience of my single-page app (or how you add a custom callback to link clicks) +Regardless of how you write your CSS, these rules take effect. So, when creating +an in-app message, it is best to stick with percentage-based CSS widths. -No problem! Please see [the link handling section](#about-links) for more -information on how to create callback methods on link clicks. There, you'll find -information on how to create a seamless link-clicking experience if you're using -a library such as React Router. +## How do I add custom callbacks to handle link clicks on in-app and embedded messages? -## What if my JWT expires? +See [Link handling](#link-handling). -JWT expiration is handled for you automatically by the SDK. There are 3 points -where the SDK will generate a new JWT token for you, apart from the initial call -when invoking `setEmail` or `setUserID`: +## What if the user's JWT expires? -1. The JWT is within 1 minute of expiration -2. An Iterable API request has failed with a 401 response -3. Your code invoked the `updateUserEmail` method +The SDK automatically handles JWT expiration and refresh. It fetches a new JWT +token for the signed-in user at four different times: -As previously explained, when initializing the SDK you need to pass a function -that returns a Promise with the JWT, which looks something like this: +- When you sign a user in by calling `setEmail` or `setUserID`. +- When the JWT is within 1 minute of expiration. +- When a request to Iterable's API request fails with a `401` response. +- When your application code calls `updateUserEmail`. -```ts -import { initialize } from '@iterable/web-sdk'; +To fetch a new JWT, the SDK calls the `generateJWT` function passed to +[`initialize`](#initialize) or [`initializeWithConfig`](#initializeWithConfig). -initialize('API_KEY_HERE', ({ email, userID }) => - yourAsyncJWTGenerationMethod({ email, userID }).then( - (response) => response.jwt_token - ) -); -``` +If there's a failure when requesting a new JWT, the SDK does not try again. +At that point, further requests to Iterable's API will fail. -When the previous three listed events occur, the SDK will invoke the method passed -as the second argument, and when the Promise resolves, attach the new JWT to any -future Iterable API requests. +To perform a manual JWT token refresh, call [`refreshJwtToken`](#refreshjwttoken). -Finally, if the request to regenerate the JWT fails however, the SDK will not -attempt to generate the JWT again so requests will start failing at that point. +# Iterable's European data center (EUDC) -To perform a manual JWT token refresh, call [`refreshJwtToken`](#refreshjwttoken). +If your Iterable project is hosted on Iterable's [European data center (EUDC)](https://support.iterable.com/hc/articles/17572750887444), +you'll need to configure Iterable's Web SDK to interact with Iterable's EU-based +API endpoints. -# A note about imports +To do this, you have two options: -This library exposes UMD modules and a single-file build for you to import from. -In other words, this means that you'll be able to import methods in these ways: +- On the web server that hosts your site, set the `IS_EU_ITERABLE_SERVICE` + environment variable to `true`. -```ts -import { getInAppMessages, initialize, updateUser } from '@iterable/web-sdk'; -``` +- Or, when use [`initializeWithConfig`](#initializeWithConfig) to initialize + the SDK (rather then [`initialize`](#initialize)), and set set the + `isEuIterableService` configuration option to `true`. For example: -```ts -import { initialize, getInAppMessages, updateUser } from '@iterable/web-sdk'; -``` + ```ts + import { initializeWithConfig } from '@iterable/web-sdk'; + + const { clearRefresh, setEmail, logout } = initializeWithConfig({ + authToken: 'my-API-key', + configOptions: { + isEuIterableService: true, + }, + generateJWT: ({ email }) => + yourAsyncJWTGeneratorMethod({ email }).then( + ({ jwt_token }) => jwt_token + ) + }); + ``` + +# Link handling + +The SDK allows you to write your own callbacks to implement custom link-handling +behavior. However, you'll do this in different ways for embedded messages and +in-app messages. -For those using Webpack/Rollup/Some Other Build Tool, it is recommended to -import methods with the later approach for smaller final bundles. Importing with -the second method ensures your bundle will only include the code you're using -and not the code you're not. +## Embedded messaging -# About links +To learn how to handle clicks on links found in embedded messages, read +[Embedded Messages with Iterable's Web SDK](https://support.iterable.com/hc/articles/27537816889108#step-8-2-handle-urls-and-custom-actions). -Since the Web SDK renders in-app messages in an iframe element on your website -if you choose to render the messages automatically, the event handler that is -responsible for clicking links is highjacked by the SDK code internally. To the -user, this doesn't really change the experience. As expected, `` tags will -open the link in the same browser tab unless given the `target="_blank"` -property. +## In-app messages -But there are few features which the SDK adds so that you can customize how -you'd like links to behave: +In-app messages render in an `iframe` element. If you choose to have the SDK +render messages automatically, the event handler responsible for handling link +clicks gets hijacked by internal SDK code. To the user, this doesn't change the +experience — links open the link in the same browser tab unless given the +`target="_blank"` property. -First, the `handleLinks` option provided by [`getInAppMessages`](#getInAppMessages) -allows you to specify how the SDK opens links: in the current tab, in a new tab, -or a combination (external links in a new tab, internal links in the current tab). +However, the `handleLinks` option that you can provide to [`getInAppMessages`](#getInAppMessages) +allows you to specify how the SDK opens in-app message links: in the current tab, +in a new tab, or a combination (external links in a new tab, internal links in the current tab). For example, consider this code: ```ts @@ -1040,8 +2407,8 @@ getInAppMessages({ }); ``` -This code ensures the following links open in the same tab if your domain is -`mydomain.com`, for example: +This example code ensures the following links open in the same tab if your +domain is `mydomain.com`: ``` /about @@ -1056,16 +2423,16 @@ https://google.com https://hello.com ``` -## Reserved keyword links +### Reserved URL schemes -Iterable reserves the `iterable://` and `action://` URL schemas to define custom -link click actions: +For in-app messages, the SDK reserves the `iterable://` and `action://` URL +schemes for custom purposes. -1. `iterable://dismiss` - Removes the in-app message from the screen, grabs the +1. `iterable://dismiss` - Removes an in-app message from the screen, grabs the next one to display, and invokes both [trackInAppClose](#trackInAppClose) and - [trackInAppClick](#trackInAppClick). + [trackInAppClick](#trackInAppClick). Not applicable to embedded messages. -2. `action://{anything}` - Makes a [`Window.prototype.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) +2. `action://` - Makes a [`Window.prototype.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) call with payload `{ type: 'iterable-action-link', data: '{anything}' }`, to be consumed by the parent website as needed. These links also dismiss the message and invoke [trackInAppClose](#trackInAppClose) and [trackInAppClick](#trackInAppClick). @@ -1076,30 +2443,26 @@ The SDK may reserve more keywords in the future. WebKit (which affects iOS web browsers, Safari included). In these browsers, users can close an in-app message by clicking away from the message. -## Routing in single-page apps +### Routing in single-page apps -Knowing now the custom link schemas available, let's explain how you can -leverage them to add custom routing or callback functions. If for example you -want to hook into a link click and send the user to your `/about` page with a -client-side routing solution, you'd do something like this if you're using React -Router: +You can add custom routing or callback functions for link clicks on in-app +messages. -```ts -/* - assuming you're clicking this link in your in-app message: - - go to about page -*/ +For example, if you want to intercept a link click and use a client-side routing +solution to send the user to your `/about` page, you could so something like this +(this example assumes that you're using React Router): +```ts +// This example assumes a click on this link: +// Go to the about page import { useHistory } from 'react-router-dom'; const SomeComponent = () => { const history = useHistory(); - React.useEffect(() => { global.addEventListener('message', (event) => { if (event.data.type && event.data.type === 'iterable-action-link') { - /* route us to the content that comes after "action://" */ + // Route us to the content that comes after "action://" history.push(`/${event.data.data}`); } }); @@ -1109,32 +2472,29 @@ const SomeComponent = () => { }; ``` -## Safari: Allowing JavaScript execution in tabs opened by in-app message link clicks +### Safari: Allowing JavaScript execution in tabs opened by in-app message link clicks To display an in-app message, Iterable's Web SDK uses an `iframe` on which the `sandbox` attribute is set to `allow-same-origin allow-popups allow-top-navigation`. On Safari, this configuration blocks JavaScript execution in tabs that open because of link clicks in the `iframe`. -To allow JavaScript to run in these new tabs: +To allow JavaScript to run in these new tabs, use [`initializeWithConfig`](#initializeWithConfig) , +pass in the configuration options, and set `dangerouslyAllowJsPopups` to `true`. -- You will need to migrate to the new - [`initializeWithConfig`](#initializeWithConfig) method, pass in the - configuration options, and set `dangerouslyAllowJsPopups` to `true` +For example: ```ts import { initializeWithConfig } from '@iterable/web-sdk'; const { clearRefresh, setEmail, setUserID, logout } = initializeWithConfig({ - authToken: 'my-API-key', + authToken: '<>', configOptions: { isEuIterableService: false, dangerouslyAllowJsPopups: true, }, - /* - _email_ will be defined if you call _setEmail_ - _userID_ will be defined if you call _setUserID_ - */ + // email will be defined if you call setEmail + // userID will be defined if you call setUserID generateJWT: ({ email, userID }) => yourAsyncJWTGeneratorMethod({ email, userID }).then( ({ jwt_token }) => jwt_token @@ -1143,8 +2503,8 @@ const { clearRefresh, setEmail, setUserID, logout } = initializeWithConfig({ ); ``` -- However, use caution. Allowing JavaScript to run in new tabs opens the door to - the possibility of malicious code execution. +However, use caution. Allowing JavaScript to run in new tabs opens the door to +the possibility of malicious code execution. SDK version support: @@ -1159,13 +2519,12 @@ For more information, see: # TypeScript -The Iterable Web SDK includes TypeScript definitions out of the box. All SDK -methods should be typed for you already but if you need to import specific -typings, you can parse through each `types.d.ts` file inside of the `./dist` -directory to find what you need. Request and response payloads should all be -available. +Iterable's Web SDK includes TypeScript definitions. All SDK methods should be +typed for you, but if you need to import specific typings, you can parse through +each `types.d.ts` file inside of the `./dist` directory to find what you need. +Request and response payloads should all be available. -If you feel something is missing, feel free to open an issue! +If something is missing, please let us know. # Contributing