Build in-app messages

 This feature is in beta

We’re confident in the core feature and don’t expect to introduce any breaking changes before we formally release it—but we still have a bit more work to do and a few more questions to answer. Start using it today and Share your feedback to help us build the best possible feature for you!

How it works

An in-app message provides all of your message content, including the text areas you can customize when you create a message in Customer.io.

When you set up an in-app message, you’ll add basic components like text and images. You’ll wrap these items in actions to make them tappable. You’ll wrap items in blocks, lists, and grids to organize the layout of your message. You can wrap items in multiple containers, for example: a button in your message that takes a person to a deep link is an action (deep link), containing a block (defining the shape of the button), containing a text component (button text).

 Have you already set up in-app branding?

If you haven’t configured your in-app Branding settings, you’ll need to do that first. Branding determines the colors, padding, and font-sizes that you can use in messages.

Create a message...and use it in a campaign
Set up an in-app message
Set up an in-app message
use the message in a campaign
use the message in a campaign

In-App message code

You can use the Show Code option to expose the JSON representation of your message.

Your message is an array of objects, where each object represents a part of your message. Some items, like actions and blocks, contain nested components. You might use the code editor to rearrange your message by moving components in and out of blocks, or moving them up or down in the array.

Each component has a type and a gist object, both are required and set automatically by the editor.

  • type determines the type of widget you’re using in the editor—textWidget, imageWidget, actionWidget, etc.
  • gist is an object containing a unique id for the widget.
See the JSON representation of your message in the code editor
See the JSON representation of your message in the code editor

Set up an in-app message

Before you can create your first message, you must have set up your brand styles. When you create a message, you can choose from a template, which has components already laid out for you, or start with a Blank message.

  1. Go to the Messages tab under Settings > Workspace Settings > In-App Settings and click New Message.
  2. Choose a message template or click Blank to start fresh.
  3. Give the message a Name and click Create Message. The name is how you’ll select your in-app message in Customer.io. You might want to make the name descriptive and unique, so it’s easy to select your messages in Customer.io later.
  4. Add components to your messages. By default, a component only shows required fields.
    • Use $properties.<var> to add variables to your message that you can supply in Customer.io. For example, $properties.name creates a field called Name in Customer.io
    • Click to reveal additional properties for the component.
    • Click Actions in the upper-right of any component to change the order of components, wrap them in blocks, actions, etc.

As you create and update your message, we’ll show how it will appear in your app or on your website.

the message designer
the message designer

Customizing messages with variables

You can customize text in your message by adding $properties.<variableName> a text component’s text field. You can include as many variables as you like, and even simply set a variable name for an entire block if you want to give message creators control over the text that they send in messages. You can use the same variable multiple times if you want to duplicate variable text in your message.

When you create and populate your messages, you can use liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable {{customer.first_name}}. to use your audience’s attributes or event data—like a person’s name or the items they left in their cart. In the example below, we use a variable in an in-app message called $properties.name to add a field called name when you use the message in a campaign or broadcast.

add variables to your messages so that you can personalize them in your campaigns
add variables to your messages so that you can personalize them in your campaigns

Organizing your message

While Text and Image components make up your message content, you’ll organize these granular items into containers to adjust the layout of your message. You can also wrap components in actions to determine what happens when someone taps a part of your message.

in-app messages are flexible: you can nest some containers inside each other. In this section, we’ll show a few common arrangements that you’ll use to create buttons, carousels, and so on.

A link is an action containing text. The action determines what happens when someone taps the text—whether the link goes to a website, somewhere in your app, a mail application, etc.

set up a link in your message
set up a link in your message

Buttons

A button consists of three items, nested in this order—action, block, and text:

  1. Action: this determines what happens when someone taps the button.
  2. Block: this provides the button shape, defining the tappable area.
  3. Text: the text for the button. You could substitute an icon or markdown for button text.

Click to style your block and text. You’ll probably want to add a background to the button and center your button text.

Remember, if you want to personalize the text for your buttons when you create your message, use the syntax $properties.fieldname. When you create your message in Customer.io, you’ll see a fieldname that you can personalize with liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable {{customer.first_name}}. or otherwise change so that it’s relevant to your message!

 Place actions outside of tappable blocks

You can create a button with a block outside the action, but that will reduce the tappable area of your button based on the padding you set! In general, you want to wrap any item that you want to make tappable in an action container.

add a button in your message
add a button in your message

Arrange items horizontally

You can place buttons next to each other on the same row using a grid or a horizontal list. Here, we’ve wrapped two buttons in a horizontal list that’s centered with Main Alignment set to Space Evenly. This center-aligns buttons for you.

You might do this to create an action button and a button that dismisses your message.

 Click Show Code to move components in and out of lists or grids

You might want to try different list and grid layouts as you create your message. Rather than re-creating components in different list and grid containers, you can use the Show Code option and copy the components array into different containers to play with different layouts!

set buttons next to each other with a horizontal list
set buttons next to each other with a horizontal list

A carousel is content that users can swipe without dismissing your message. You might use a carousel to showcase new features, provide a tutorial, etc.

You’ll use a Fixed horizontal scroll widget containing at least two components. You can even wrap items in the carousel in actions, so that each item in your carousel performs a different action.

Message component reference

When you add a component or container, we show required settings by default. Click to show additional options. You can also click Show Code to add or edit components in JSON.

Component properties are largely CSS-based. If you’re familiar with CSS, you should be able to manipulate message components.

Text

A text component represents any text in your message—headings, body, footers, etc. Use $properties.<variableName> to add a customizable variable to your message. when someone uses your message in a campaign or broadcast workflow, they’ll see a field called <variableName> that they can personalize for your audience.

Press to expose options to style your text.

{
	"type": "textWidget",
	"text": "$properties.name",
	"style": "bodyText",
	"color": "black",
	"textAlign": "left",
	"maxLines": 1,
	"overflow": "ellipsis"
}
  • color string
    The color you want to use for this content. You can only set values here that are defined under Settings > Workspace Settings > In-App Settings.
  • maxLines integer
    The maximum lines of text you want to display. Text over this limit is controlled by the overflow property. If unset, the message displays an unlimited number of lines.
  • overflow string
    Determines how to handle text that overflows the maxLines limit (if set). By default, we cut off overflowing text with ellipsis (...).

    Accepted values:ellipsis,fade,clip

  • style string
    The style of text you want to display. You can only set values here that are defined under Settings > Workspace Settings > In-App Settings.
  • text string
    Required The text you want to display.
  • textAlign string
    How you want to align this text.

    Accepted values:center,right,left,start,end,justify

  • type string
    Required Defines the widget type.

    Accepted values:textWidget

Image

Upload an image for your message. Click the downarrow to reveal additional properties determining the width of your image, how it should fit the bounds of the message, whether it should fade in, etc.

Press to expose options helping you style your image and fit it to your message.

{
	"type": "imageWidget",
	"image": "$properties.imageUrl",
	"fit": "cover",
	"height": 50,
	"width": 50,
	"cornerRadius": 25,
	"fadeInDuration": 200
}
  • cornerRadius integer
    Sets the radius of corners for an item in pixels, similar to the border-radius CSS property.
  • fadeInDuration integer
    The durration for the image to fade in, in milliseconds, similar to the fadeIn CSS transition property.
  • fit string
    Determines how the image fits your message. Defaults to cover.

    Accepted values:none,fitWidth,cover,contain,scaleDown,fill,fitHeight

  • height integer
    The height of the component in pixels, if you want to constrain it. If you don’t set a height or width, we’ll scale your content to fit your message or container.
  • type string
    Required Defines the widget type.

    Accepted values:imageWidget

  • width integer
    The width of the component in pixels, if you want to constrain it. If you don’t set a height or width, we’ll scale your content to fit your message or container.

Action

An Action determines what happens when someone taps one or more components in your message. You might use an action to send someone to a link in your app, an external link, etc. When you add an action, you’ll determine the action and then add components inside the action.

example of a link action
example of a link action

We support the following actions:

ActionDescription
Navigate to web pageSends the message recipient to a web page in their default browser.
Navigate to web page (new tab)Because you’re sending a message to a mobile app, this action does the same as the Navigate to web page action. All web page links open in a new tab in the user’s default browser.
iOS/Android deep linkSends a person to a deep link in your app. You’ll need to know the deep link format and screen you want to send a person to.
Change messageChange the content of your message when someone interacts with it.
Close messageDismisses the in-app message.
ApplicationSet up an action handled directly by your app. In general, this option is for developers.

If you use the Show Code option, the action is the link. You can set a behavior key determining how to handle the action. See the schema below for available values.

{
	"type": "actionWidget",
	"action": "myApp://homepage",
	"behaviour": "push",
	"component": {}
}
  • action string
    Required The link or place you want to send a person. This is either a deep link in your app, a web address, a mailto link, or a way to close the message (gist://close).
  • behaviour string
    • push: pushes a new route into the navigation stack.
    • system: offloads the action onto the operating system. Actions like mailto:support@bourbon.sh will open the default email client.
    • back: pops the navigation stack one step back.
    • retain: retain replaces the current view with a new route.

    Accepted values:push,system,back,retain

  • type string
    Required Defines the widget type.

    Accepted values:actionWidget

Block

A block is a group of components that you apply a design to. You might group components to set a background image, apply rounded corners, etc. The only required property is the list of components you want to nest inside the block. You’ll need to style the block using the Show code option.

{
	"type": "blockWidget",
	"safeInsets": false,
	"padding": ["m","m","m",""],
	"backgroundColor": "white",
	"borderColor": "black",
	"borderWidth": 1,
	"borderRadius": 10,
	"height": 150,
	"backgroundImage": "$properties.backgroundImage",
	"flex": 1,
	"components": []
}
  • backgroundColor string
    The background color for your block. You must set a value defined under Branding > Colors.
  • backgroundImage string
    Set a background image for the block
  • borderColor string
    The border color for your block, if you set a border width greater than 0. You must set a value defined under Branding > Colors.
  • borderRadius integer
    Sets the radius of corners for an item in pixels, similar to the border-radius CSS property.
  • borderWidth integer
    The width of the border for this block in pixels.
  • components array of [objects]
    An array of child components that you want to make available inside this widget.
  • flex integer
    The single digit syntax for the CSS flex property. The value you use here determines the propotional amount of space the block consumes in a parent container.
  • height integer
    The height of the component in pixels, if you want to constrain it. If you don’t set a height or width, we’ll scale your content to fit your message or container.
  • padding array of [strings]
    Defines padding for the block, based on the values set under Branding > Padding. As with the CSS padding property, values in the array represent top, right, bottom, and left padding.
  • safeInsets boolean
    Based on the env safe-area-inset-* CSS properties. Set to true to ensure that the block can’t overflow the defined screen or the defined area of your message. Defaults to false.
  • type string
    Defines the widget type.

    Accepted values:blockWidget

Vertical List

While elements in your message are typically displayed top-to-bottom, a vertical list helps you align these items. You can set up vertical lists to control the vertical layout of your message.

{
	"type": "conditionalWidget",
	"condition": "$properties.items > 2",
	"true": {},
	"false": {}
}
  • components array of [objects]
    An array of child components that you want to make available inside this widget.
  • crossAxisAlignment string
    The crossAxisAlignment property supports the following options

    Accepted values:center,start,end,center,stretch,baseline

  • mainAxisAlignment string
    The mainAxisAlignment property supports the following options.

    Accepted values:start,end,spaceBetween,spaceAround,spaceEvenly

Horizontal List

A horizontal list lays out components horizontally, letting you set the alignment of the items in the list.

{
	"type": "fixedHorizontalListWidget",
	"mainAxisAlignment": "start",
	"crossAxisAlignment": "center",
	"components": [{},{}]
}
  • components array of [objects]
    An array of child components that you want to make available inside this widget.
  • crossAxisAlignment string
    The crossAxisAlignment property supports the following options

    Accepted values:center,start,end,center,stretch,baseline

  • mainAxisAlignment string
    The mainAxisAlignment property supports the following options.

    Accepted values:start,end,spaceBetween,spaceAround,spaceEvenly

  • type string
    Defines the widget type.

    Accepted values:fixedHorizontalListWidget

Horizontal Scroll List (Carousel)

A horizontal scroll list is essentially a carousel. It displays one component at a time, and users can swipe items in the horizontal list to see different components. The horizontal scroll list takes up the entire width of the parent list, block, or grid.

{
	"type": "fixedHorizontalListScrollWidget",
	"height": 150,
	"components": [{},{}]
}
  • components array of [objects]
    An array of child components that you want to make available inside this widget.
  • height integer
    The height of the widget in pixels.
  • type string
    Defines the widget type

    Accepted values:fixedHorizontalListScrollWidget

Horizontal Grid

A grid is like a horizontal list, except that you can control the padding between elements and the aspect ratio of items in the grid. This allows you to customize your layout with tall, skinny grids or short, long grids. By default, A grid’s aspect ratio is 1.0 making it similar to a horizontal list, though you can control the padding between elements.

{
	"type": "conditionalWidget",
	"condition": "$properties.items > 2",
	"true": {},
	"false": {}
}
  • childAspectRatio number
    The aspect ratio for items in the grid. Defaults to 1.0
  • columns integer
    Required The number of columns in your grid.
  • components array of [objects]
    Required An array of child components that you want to make available inside this widget.
  • itemPadding string
    The padding between items in your grid.
  • type string
    Required Defines the widget type.

    Accepted values:fixedGridWidget

Copied to clipboard!