NOTE
To add Embedded Messaging to your Iterable account, talk to your customer success manager.
This article describes how to use Iterable's Web SDK to display embedded messages on your website.
Before getting started, note that:
- The Embedded Messaging product documentation describes how Embedded Messaging works as a whole.
- The code snippets included in this doc are examples. Do not paste them directly into your own code. Instead, use them to get a sense of how Embedded Messaging works and how to implement it on your website, and adapt them as needed for your site's architecture and your specific requirements.
TIP
For some example code that uses Iterable's Web SDK to display embedded messages using React and out-of-the-box views, see the React sample app, in the GitHub repository for the Web SDK.
In this article
- Step 1: Coordinate with your marketing and design teams
- Step 2: Create a Web API key
- Step 3: Install Iterable's Web SDK in your app
- Step 4: Initialize the SDK
- Step 5: Fetch embedded messages from Iterable
- Step 6: Set up your code to handle incoming messages
- Step 7: Track sessions and impressions
- Step 8: Handle clicks
- Step 9: Test and activate an embedded message campaign
- Out-of-the-box views
Step 1: Coordinate with your marketing and design teams
First, collaborate with your marketing and design teams to determine:
- Where you'll display embedded messages in your apps. That is, where your placements will go.
- Each placement's Iterable-assigned numeric ID, which you'll use to display the right messages in the right places.
- The fields that each placement will display in its messages, so that your website knows what data to expect.
- The message design for each of your placements.
For more information about these topics, read our Embedded Messaging Overview.
Step 2: Create a Web API key
To use Iterable's Web SDK to display embedded messages, you'll need a Web API key for Iterable. To learn how to create one, read Creating API Keys.
Step 3: Install Iterable's Web SDK in your app
Versions 1.1.0+ of Iterable's Web SDK support Embedded Messaging.
To install the SDK, use npm, Yarn, or a script
tag:
-
npm
npm install @iterable/web-sdk@1.1.0
-
Yarn
yarn add @iterable/web-sdk@1.1.0
-
script
tag<script src="https://unpkg.com/@iterable/web-sdk@1.1.0/index.js"></script>
Step 4: Initialize the SDK
To get started using the Web SDK:
- In your code, import necessary classes and methods from the SDK.
- Create an
IterableEmbeddedManager
andIterableEmbeddedSessionManager
, which you'll use to fetch embedded messages, handle clicks, and track sessions and impressions. - Call the SDK's
initialize
function, passing in your web API key and a function the SDK can call to fetch (from your own server) a JWT token for the current user.initialize
returns asetEmail
andsetUserID
methods for you to call when you determine the identity of the signed-in user. - When you know the identity of the current user, call
setEmail
orsetUserID
to identify the user to the SDK. This causes thes SDK to fetch a JWT token for the user, using the method you passed toinitialize
.
For example, here's some sample code that shows how to initialize the SDK,
identifying a user by email
:
// Import necessary SDK classes and methods. import { initialize, trackEmbeddedClick, IterableEmbeddedManager, IterableConfig, IterableEmbeddedSessionManager } from '@iterable/web-sdk'; // Create an IterableEmbeddedManager and IterableEmbeddedSessionManager, // which you'll use to fetch embedded messages, handle clicks, and track events. const embeddedManager = new IterableEmbeddedManager(packageName); const embeddedSessionManager = new IterableEmbeddedSessionManager(packageName); // Example placement ID, as assigned by Iterable. const placementId = 327; // Call initialize to get the setEmail (or setUserID) method you'll call once // you know the identity of the current user const { setEmail, logout, refreshJwtToken } = initialize( // Pass in your API key. (Don't check your API key into your source code // repository. For example, you might store it in an environment variable on // your server, and then access the environment variable in your code.) YOUR_API_KEY, // This function should fetch a JWT token for the current user (from your // server), and return it to the SDK as a string. The SDK calls this function // when you identify the user by calling setEmail or setUserID. ({ userEmailAddress }) => { // Fetch (from your authorization server) a JWT token specific to the // current user }.then((response) => { // Return the user-specific JWT token to the SDK, as a string }); ); // ... // Later, when you know the user's identity, call setEmail or setUserID. // This triggers a call to the JWT refresh function passed to initialize. // In this example, after the JWT comes back, this example immediately calls // syncMessages to fetch (from Iterable) embedded messages for the current user. setEmail(email) .then(response => { embeddedManager.syncMessages( packageName, () => { // Handle messages using embeddedMessageUpdateHandler }, [placementId] ); }) .catch(error => { console.log('Failed to set email:', error); });
NOTE
If your project is hosted on Iterable's EDC, you'll need to configure the SDK appropriately.
For related information, see the following sections of the Web SDK's GitHub README:
Also, for more detail, see the code for:
Step 5: Fetch embedded messages from Iterable
NOTE
You can only fetch embedded messages (or use the SDK to make any other calls to Iterable's API) if you've already received a JWT token for the current user and passed it back to the SDK.
When you're ready to fetch messages for the current user, call syncMessages
on
your instance of IterableEmbeddedManager
. syncMessages
has this signature:
syncMessages(packageName: string, callback: () => void, placementIds?: number[]): Promise<void>;
This method takes three parameters:
-
packageName
— ThepackageName
you use to identify your website. -
callback
— An empty handler (since, to handle incoming messages, you'll rely instead on the handler you'll define in step 6). -
placementIds
— An array of placement IDs for which the SDK should fetch messages.
ethod tells the SDK to fetch embedded messages from Iterable and store them in memory. Then, in the message handler you'll define in step 6, you can grab the already-fetched messages from the SDK and display them as needed.
For example, to display messages immediately after identifying a user by email
(as shown in the sample code above):
setEmail(email) .then(response => { embeddedManager.syncMessages( packageName, () => { // Handle messages using embeddedMessageUpdateHandler }, [placementId] ); }) .catch(error => { console.log('Failed to set email:', error); });
Some things to note:
You can fetch embedded messages when the page loads (after a JWT is fetched for the current user), or when the user completes an action (clicks a link or a button, etc.).
To fetch embedded messages from Iterable, the SDK calls
GET /api/embedded-messaging/messages
.The second argument to
syncMessages
is a callback that executes after the messages have been retrieved. However, it's generally better to leave this callback empty, and follow the instructions in step 6 to handle incoming messages.For each embedded message received from Iterable, Iterable's Web SDK automatically tracks an
embeddedReceived
event. Each of these events indicates that a message was fetched, but not necessarily that it was displayed. To trackembeddedReceived
events, the SDK callsPOST /api/embedded-messaging/events/received
.
Step 6: Set up your code to handle incoming messages
After you call syncMessages
and the SDK fetches embedded messages from Iterable
(as described in the step 5),
the SDK calls the onMessagesUpdated
method on your message update handler, so
that it can display the incoming messages as needed. In this step, you'll set up
that message update handler.
Your message update handler for incoming embedded messages must implement the
IterableEmbeddedMessageUpdateHandler
interface:
export interface IterableEmbeddedMessageUpdateHandler { onMessagesUpdated: () => void; onEmbeddedMessagingDisabled: () => void; }
onMessagesUpdated
– Called by the SDK when there are new messages to display. Use this method to grab messages for the current placement from the embedded manager, and then display them as needed.onEmbeddedMessagingDisabled
– Called by the SDK when it hits an error fetching embedded messages. Use this method to hide the embedded message display or display an empty state.
In onMessagesUpdated
, grab the messages the SDK fetched from Iterable when you
called syncMessages
(in step 5),
using one of two methods:
getMessages(): IterableEmbeddedMessage[];
- Returns all embedded messages that the SDK has in memory, for all placements.getMessagesForPlacement(placementId: number): IterableEmbeddedMessage[];
- Returns all embedded messsages that the SDK has in memory, for a specific placement.
The sample code below grabs already-fetched messages for placement 327 (an example
placement ID) from the IterableEmbeddedManager
, and displays one message to
the screen. Or, in case of an error, it hides the embedded message display
altogether.
NOTE
This code is only an example. Your implementation will depend on the structure of your code, the frameworks that you're using, etc.
// This sample code assumes that embeddedManager has already been instantiated // (for an example, see step 4, above), and that embeddedMessageImage, // embeddedMessageTitle, embeddedMessageBody, embeddedMessageButton1, // embeddedMessageButton2, and embeddedMessage are already set up to reference // elements of an embedded message UI. const embeddedMessageUpdateHandler = { onMessagesUpdated: () => { // a single placement, that has ID 327. const placementId = 327; // Grab the messages that the SDK has already fetched and now has in memory. const messages = embeddedManager.getMessagesForPlacement(placementId) // If there are any messages to display... if (messages.length > 0) { // Display the first message. const message = messages[0]; // Here, you could display the embedded messaging using an out-of-the-box // view, or using a custom message display. This examples uses a custom // message view. For information about out-of-the-box views, see // Out of the Box Views, at the bottom of this article. // Set up the message embeddedMessageImage.src = message.elements?.mediaUrl; embeddedMessageTitle.innerText = message.elements?.title; embeddedMessageBody.innerText = message.elements?.body; // Set up the first button if (message.elements?.buttons?.length > 0) { let button = message.elements?.buttons[0]; embeddedMessageButton1.innerText = button.title; // For "Open URL" buttons, the URL is in the data field. Otherwise, // the URL is in the type field. embeddedMessageButton1.href = button.action?.type === "openUrl" ? button.action?.data : button.action?.type; embeddedMessageButton1.style.display = "inline"; } // Set up the second button if (message.elements?.buttons?.length > 1) { let button = message.elements?.buttons[1]; embeddedMessageButton2.innerText = button.title; embeddedMessageButton2.href = button.action?.type === "openUrl" ? button.action?.data : button.action?.type; embeddedMessageButton2.style.display = "inline"; } // Display the message (this example assumes that the embedded message // UI was hidden, and should now be displayed). embeddedMessage.style.display = "block"; // Start a session & impression. embeddedSessionManager.startSession(); embeddedSessionManager.startImpression(message.metadata.messageId, placementId); } }, onEmbeddedMessagingDisabled: () => { // There was an error, so hide the embedded message display embeddedMessage.style.display = "none"; } };
To make sure that the SDK calls the methods implemented on the object above, add
the object that contains those methods as an update listener on your instance of
IterableEmbeddedManager
:
embeddedManager.addUpdateListener(embeddedMessageUpdateHandler);
With this done, the SDK can call the object's onMessagesUpdated
and
onEmbeddedMessagingDisabled
after it fetches embedded messages from Iterable.
TIPS
- To display embedded messages, you can either create your own custom views, or you can use the out-of-the-box views provided by Iterable's Web SDK (cards, banners and notifications). For more information about out-of-the-box views, see Out-of-the-box Views, below.
- You can set up multiple message update handlers (one for each placement on the page), or you can use a single message update handler for all placements — whatever makes the most sense for your scenario.
Some things to consider as you're setting up your message handler:
To get a sense of the JSON data Iterable returns for each embedded message, see
GET /api/embedded-messaging/messages
.getMessagesForPlacement
returnsIterableEmbeddedMessage
objects. Use the fields in these objects to build out your message display. For more details about this type and the data it contains, see Embedded Message Interfaces.-
As you're setting up the views for your embedded messages:
Make sure you have a way to associate each message view with its corresponding
IterableEmbeddedMessage
object, so you have access to the underlying message (and itsmessageId
) when tracking events.As messages appear and disappear, track sessions and impressions (for more information, see step 7).
Add click handlers where necessary, so you can handle clicks and track them in Iterable (for more information, see step 8).
Embedded message interfaces
To work with embedded messages that the SDK fetches, you'll interact with the following types of data:
IterableEmbeddedMessage
export interface IterableEmbeddedMessage { metadata: IterableEmbeddedMetadata; elements?: IterableEmbeddedElements; payload?: Record<string, any>; }
-
metadata
contains identifying information about the campaign. -
elements
contains the message's content. -
payload
contains custom JSON data included with the campaign.
IterableEmbeddedMetadata
export interface IterableEmbeddedMetadata { messageId: string; campaignId?: number; isProof?: boolean; placementId?: number; }
IterableEmbeddedElements
export interface IterableEmbeddedElements { title?: string; body?: string; mediaUrl?: string; buttons?: IterableEmbeddedButton[]; text?: IterableEmbeddedText[]; defaultAction?: IterableEmbeddedDefaultAction; }
IterableEmbeddedButton
export interface IterableEmbeddedButton { id: string; title?: string; action?: IterableEmbeddedButtonAction; }
IterableEmbeddedButtonAction
export interface IterableEmbeddedButtonAction { type: string; data?: string; }
The values for type
and data
depend on the type of Button action associated
with the button:
- If the campaign set the button's Button action to Open URL,
type
isopenUrl
anddata
contains the URL. - If the campaign set the button's Button action to Custom action,
type
is the URL, anddata
is empty.
IterableEmbeddedText
export interface IterableEmbeddedText { id: string; text?: string; }
IterableEmbeddedDefaultAction
export interface IterableEmbeddedDefaultAction { type: string; data?: string; }
The values for type
and data
depend on the type of Open action assigned
to the campaign in Iterable:
- If the campaign set Open action to Open URL,
type
isopenUrl
anddata
contains the URL. - If the campaign set Open action to Custom action,
type
is the URL, anddata
is empty.
Step 7: Track sessions and impressions
As you display messages on-screen, no matter whether you use custom views or out-of-the-box views, you'll need to track sessions and impressions.
A session is a period of time when a user is on a screen or page that can display embedded messages.
A session can have many impressions, each of which represents the on-screen appearances of a single embedded message, in context of the session. Each impression tracks:
- The total number of times its associated message appeared during the session.
- The total amount of time the message was visible, across all its appearances in the session.
To help you track message sessions and impressions, Iterable's Web SDK provides
an IterableEmbeddedSessionManager
class.
NOTE
Sessions and impressions are tracked in Iterable as embeddedSession
and embeddedImpression
events.
Step 7.1: Start sessions
When a user comes to a screen or page in your app where embedded messages are displayed (in one or many placements), use the session manager to start a session.
TIP
You may want to start sessions and impressions in response to pageshow
and visibilitychange
events, since these can help you determine when a user is actively viewing a page.
To start a session, call startSession
on IterableEmbeddedSessionManager
.
startSession
has this signature:
startSession(): void;
For example:
// When the page that displays embedded messages becomes visible embeddedSessionManager.startSession();
Step 7.2: Start impressions
As messages appear or disappear during an ongoing embedded message session, use the session manager to track message impressions. The session manager tracks the total number of times each message appears during a session, and the total amount of time each message is on-screen across all those appearances.
TIP
You may want to start sessions and impressions in response to pageshow
and visibilitychange
events, since these can help you determine when a user is actively viewing a page.
To start impressions, call startImpression
on IterableEmbeddedSessionManager
.
startImpression
has this signature:
startImpression(messageId: string, placementId: number): void;
This method takes two parameters:
-
messageId
– The Iterable-assigned ID of the message being displayed. -
placementId
– The Iterable-assigned ID of the placement where the message is being displayed.
For example:
embeddedSessionManager.startImpression(message.metadata.messageId, placementId);
Step 7.3: Pause impressions
You start and end sessions, but you start and pause impressions, since an embedded message can disappear and reappear many times during the same session. When a message disappears, you pause its impression. When it reappears, you start the impression again.
TIP
To pause impressions, you may want to respond to pagehide
and visibilitychange
events. For more details, see Google's article, Deprecating the unload event.
To pause an impression, call pauseImpression
on IterableEmbeddedSessionManager
.
pauseImpression
has this signature:
pauseImpression(messageId: string): void;
This method takes a single parameter, which is the ID of the message being displayed.
For example:
embeddedSessionManager.pauseImpression(message.metadata.messageId);
Step 7.4: End sessions
When the user navigates away from a page that displays embedded messages, end the active session. When you end a session, this also ends its sessions.
TIP
To end sessions, you may want to respond to pagehide
and visibilitychange
events. For more details, see Google's article, Deprecating the unload event.
To end a session, call endSession
on IterableEmbeddedSessionManager
.
endSession
has this signature:
endSession(): Promise<void>;
For example:
embeddedSessionManager.endSession();
Step 8: Handle clicks
This step describes how to handle clicks on embedded messages, whether on buttons or elsewhere on the message.
Step 8.1: Set up click handlers
NOTE
If you're using out-of-the-box views, you can skip directly to step 8.2. For out-of-the-box views, the SDK automatically:
- Tracks
embeddedClick
events. - Passes URLs resulting from clicks to the URL and custom action handlers you'll define in step 8.2.
First, set up button click handlers and a "default" click handler, so you can handle clicks when they happen. In your click handlers:
- Grab the URL associated with the click.
- Track an
embeddedClick
event. - Call
click
on your instance of theIterableEmbeddedManager
. This method passes the URL associated with the click through to the URL handler or custom action handler you'll define in step 8.2, so you can respond to the URL as necessary (by navigating to a new page or handling a custom action).
For example, here's a click handler for an embedded message button:
// This example code assumes that embeddedMessageButton1 is a reference // to the first button of an embedded message that's being displayed, and that // embeddedManager is a reference to an instance of IterableEmbeddedMessageManager. embeddedMessageButton1.addEventListener("click", handleButton1Click); function handleButton1Click(event) { // Prevent default click behavior for the button event.preventDefault(); event.stopPropagation(); // Get the button data from the message payload returned by Iterable let button = message.elements?.buttons[0]; // For buttons where type is "openUrl", the URL is in the action.data field. // Otherwise, the button represents a custom action, and the URL is in the // action.type field. let buttonUrl = button.action?.type === "openUrl" ? button.action?.data : button.action?.type; // Track an embeddedClick event trackEmbeddedClick({ messageId: message.metadata.messageId, buttonIdentifier: button.id, clickedUrl: buttonUrl, appPackageName: packageName }).then((response) => { if (response.status != 200) { console.log("Failure tracking embedded click") } }).catch((error) => { console.log("Error tracking embedded click: ", error); }) // Pass the click through to the URL or custom action handlers. For more // information, see step 8.2, below. embeddedManager.click(buttonUrl); }
Iterable's Web SDK defines trackEmbeddedClick
as:
export declare const trackEmbeddedClick: (payload: IterableEmbeddedClickRequestPayload) => import("../../types").IterablePromise<IterableResponse>;
IterableEmbeddedClickRequestPayload
is defined as:
export interface IterableEmbeddedClickRequestPayload { messageId: string; buttonIdentifier: string; targetUrl: string; appPackageName: string; }
To track embeddedClick
events, the SDK calls POST /api/embedded-messaging/events/click
.
Define similar handlers for each of the embedded message's buttons, as well as a "default" handler that all other clicks on the message.
TIP
The data for a default click, as specified in an embedded message template in
Iterable, is stored on the IterablembeddedMessage
, in elements.defaultAction
.
Step 8.2: Handle URLs and custom actions
NOTE
Complete this step no matter whether you use custom views or out-of-the-box views. For out-of-the-box views, the SDK automatically tracks click events, but it then passes the URLs associated with those clicks to the handlers you'll define in this step.
Embedded message campaigns can include one or two buttons, and an open action to execute when the user clicks anywhere else on the message. When setting up a button or open action in Iterable, you can choose:
Open URL – Associate the button or open action with a standard URL (for example,
https://example.com/products/1
) or a URL with a custom URL scheme (for example,mycompany://profile
).Custom action - Associate the button or open action with an
action://
URL (for example,action://joinClass/1
). Action URLs represent custom functionality for an app to exeucte — a style update, a profile update, a sign-up action, or anything else relevant to your app.
To handle URLs and custom actions, define a URL handler and a custom action
handler. These are both static properties on IterableConfig
(see below),
and the SDK invokes them, as necessary, when click
is called on the
IterableEmbeddedManager
. Out-of-the-box views call click
automatically,
but for custom views your application code will need to do this manually
(as shown in step 8.1).
NOTES
- Currently, the Web SDK uses the URL and custom action handlers defined in this step to handle URLs and custom actions coming only from embedded messages. In the future, the SDK may also use these handlers for URLs and custom actions coming from in-browser (in-app) messages.
- In-app messages support
iterable://dismiss
anditerable://delete
custom actions. Embedded messages do not yet support these actions, but theiterable://
URL scheme is reserved for Iterable-specific actions pre-defined by the SDK.
Here's an example URL handler:
IterableConfig.urlHandler = { handleIterableURL: (uri, actionContext) => { iterableEmbeddedSessionManager.endSession(); window.location.href = uri; return true; } };
In this example, the URL handler ends the session and opens the URL in the current browser tab.
A URL handler should return true
for URLs that it can handle, and false
for URLs it cannot handle. When it returns false
, or when you don't provide a
URL handler, the SDK attempts to open the URL in a new tab or browser window.
Here's an example custom action handler:
IterableConfig.customActionHandler = { handleIterableCustomAction: (action, actionContext) => { if (uri === "action://joinClass/") { // Get the class ID from the URL and join the class // ... return true; } return false; } };
This example method looks for joinClass
URLs, and then uses the data they
contain to sign the current user up for a class.
A custom action handler should return true
for custom actions it can handle,
and false
for custom actions it cannot handle. When it returns false
, or when
you don't provide a custom action handler, the custom action is dropped.
IterableConfig
export class IterableConfig { public static urlHandler: IterableUrlHandler | null = null; public static customActionHandler: IterableCustomActionHandler | null = null; }
IterableUrlHandler
export interface IterableUrlHandler { handleIterableURL(uri: string, actionContext: IterableActionContext): boolean; }
IterableCustomActionHandler
export interface IterableCustomActionHandler { handleIterableCustomAction( action: IterableAction, actionContext: IterableActionContext ): boolean; }
IterableAction
export interface IterableAction { type: string; data: string; }
IterableActionContext
export interface IterableActionContext { action: IterableAction; source: IterableActionSource; }
IterableActionSource
export enum IterableActionSource { EMBEDDED = 'EMBEDDED' }
Step 9: Test and activate an embedded message campaign
After setting up your apps and websites to handle incoming embedded messages, you can create, test, and activate embedded message campaigns in Iterable, and then make sure they appear as expected on your website.
To learn more, read these docs:
- Creating Embedded Message Templates
- Defining Eligibility Lists for Embedded Messages
- Creating Embedded Message Campaigns
Out-of-the-box views
Iterable's Web SDK provides out-of-the-box views for displaying embedded messages on your website. These views include cards, banners, and notifications.
TIP
For some example code that uses Iterable's Web SDK to display embedded messages, using out-of-the-box views and React, see React sample app.
Out-of-the-box views do not automatically track embeddedSession
or
embeddedImpression
events — your application code must do so, as described in step 7.
However, out-of-the-box views do automatically track embeddedClick
events,
and pass URLs to the URL and custom action handlers you defined in
step 8.2.
Cards, Notifications, and Banners
Iterable's Web SDK provides three types of out-of-the-box views: cards, notifications, and banners.
Cards
Cards display a header image, title text, body text, and up to two buttons. For example:
For default card styles, see the src/components/card/styles.ts
in the Web SDK GitHub repository. To learn how to apply custom styles, see
Custom Styles.
Banners
Banners display a corner image, title text, body text, and up to two buttons. For example:
For default banner styles, see the src/components/banner/styles.ts
in the Web SDK GitHub repository. To learn how to apply custom styles, see
Custom Styles.
Notifications
Notifications display title text, body text, and up to two buttons, but no image. For example:
For default notification styles, see the src/components/notification/styles.ts
in the Web SDK GitHub repository. To learn how to apply custom styles, see
Custom Styles.
Creating an out-of-the-box view
To create a card, banner, or notification:
-
First, import
IterableEmbeddedCard
,IterableEmbeddedBanner
, andIterableEmbeededNotification
from the SDK, as necessary:import { IterableEmbeddedCard, IterableEmbeddedBanner, IterableEmbeddedNotification } from '@iterable/web-sdk';
-
Then, call
IterableEmbeddedCard
,IterableEmbeddedBanner
, orIterableEmbeddedNotification
, each of which returns a string representation of the out-of-the-box view:export declare function IterableEmbeddedCard( { appPackageName, message, htmlElements, errorCallback }: OOTB ): string; export declare function IterableEmbeddedBanner( { appPackageName, message, htmlElements, errorCallback }: OOTB ): string; export declare function IterableEmbeddedNotification( { appPackageName, message, htmlElements, errorCallback }: OOTB ): string;
Each of these methods takes the following parameters:
-
appPackageName
– The package name you use to identify your website to Iterable's Web SDK. -
message
– TheIterableEmbeddedMessage
object that represents the message you want to display. -
htmlElements
– Custom styles you'd like to use when displaying your message. For details, see Custom Styles. -
errorCallback
– A callback that the SDK calls if it encounters an error when trackingembeddedClick
events.
For example, here's a call to
IterableEmbeddedCard
:const card = IterableEmbeddedCard({ packageName, message, htmlElements, errorCallback: (error) => console.log('handleError: ', error) });
-
-
Assign the string returned by embedded message function to the
innerText
property of an HTML element. For example:document.getElementById('cardView').innerText = card;
Custom styles
When you create an out-of-the-box view by calling one of the IterableEmbeddedCard
,
IterableEmbeddedBanner
, or IterableEmbeddedNotification
functions, you can
pass in an htmlElements
object (of type Elements
) to customize
the message's appearance. For example:
const card = IterableEmbeddedCard({ packageName, message, htmlElements, errorCallback: (error) => console.log('handleError: ', error) });
Here's an example htmlElements
object:
const htmlElements = { // Styles to apply to the HTML element that contains the out-of-the-box view. // Not the element whose innerText you set to the out-of-the-box view, but // its first child. parent: { // id to assign id: 'parent-id', // Styles must be strings styles: ` background: white; border-color: purple; border-radius: 30px; padding: 10px; ` }, // Image styles img: { id: 'img-id', styles: '' }, // Title text styles title: { id: 'title-id', styles: ` color: green; ` }, // Primary button styles primaryButton: { id: 'primary-button-id', styles: ` color: #8B0000; background: #FFFFFF; ` }, // Secondary button styles secondaryButton: { id: 'secondary-button-id', styles: '', // If you give disabledStyles to a button, the button will be disabled. To // enable the button, re-render the HTML component without the disabledStyles. disabledStyles: ` opacity: .6; cursor: not-allowed; background: grey; color: grey; ` }, // Body text styles body: { id: 'body-id', styles: ` color: green; ` }, // Div containing the buttons buttonsDiv: { id: 'buttons-div-id', styles: '' } };
This example shows an htmlElements
constant. However, if you're re-using
custom styles across multiple embedded messages, you'll want to use a different
id
value for each message. To accomplish this, but still use shared custom styles,
create a function that returns an htmlElements
that's based on pre-defined
styles and passed-in id
values.
You can pass in any custom styles that you like, but out-of-the-box components explicitly support the following CSS properties:
- Background color (
background-color
) - Border color (
border-color
) - Border width (
border-width
) - Border corner radius (
border-radius
) - Primary button background color (
background-color
) - Primary button text color (
color
) - Secondary button background color (
background-color
) - Secondary button text color (
color
) - Title text color (
color
) - Body text color (
color
)
TIP
Always test your out-of-the-box views on multiple devices and browsers to make sure they look good and work as expected.
Types for custom styles
Elements
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; };
OutOfTheBoxElement
export type OutOfTheBoxElement = { /** id of the element */ id?: string; /** Stringified CSS to be passed to element "style" tag */ styles?: string; };
OutOfTheBoxButton
export type OutOfTheBoxButton = OutOfTheBoxElement & { /** Stringified CSS to be passed to element "style" tag. * Presence of this value determines whether or not the button is disabled. */ disabledStyles?: string; };