Personalized Messaging

Braze allows you to personalize your campaigns by inserting user-specific information, such as the user’s name, into messages. Campaign messages support templated messaging using the Liquid templating language. Detailed documentation of Liquid syntax and usage is available here.

Liquid templating language supports the use of objects, tags and filters.

Objects allow you to insert personalizable attributes into your messages.

Tags allow you to execute programming logic in your messages. For example, you can use tags to include intelligent logic, such as “if” statements, in your campaigns.

Filters allow you to reformat personalizable attributes and dynamic content. For example, you could convert a timestamp, such as 2016-09-07 08:43:50 UTC into a date such as September 7th, 2016.

Adding Personalizable Attributes (Objects)

Braze can automatically substitute values from a given user into your messages. Put your expression inside of two sets of curly brackets to notify Braze that you’ll be using an interpolated value. Inside of these brackets, any user values that you want to substitute must be surrounded by an additional set of brackets with a dollar sign in front of them. For example, if you include the following text in your message: {{${first_name}}}, the appropriate value from the user will be interpolated when the message is sent. If you would like to use the value of a custom attribute, you must add the namespace “custom_attribute” to the variable. For example, to use a custom attribute named “zip code”, you would include {{custom_attribute.${zip code}}} in your message.

The following user values can be substituted into a message:

You can also pull content directly from a web server via Braze’s Connected Content feature.

Supported Personalization Tag Summary

As a convenience, a summary of supported personalization tags are listed below. For more detail on each kind of tag and best practices, continue reading.

Personalization Tag Type Tags
Default Attributes {{${city}}}, {{${country}}}, {{${date_of_birth}}}, {{${email_address}}}, {{${first_name}}}, {{${gender}}}, {{${language}}}, {{${last_name}}}, {{${last_used_app_date}}}, {{${most_recent_app_version}}}, {{${most_recent_locale}}}, {{${most_recent_location}}}, {{${phone_number}}}, {{${time_zone}}}, {{${twitter_handle}}}, {{${user_id}}}, {{${braze_id}}}
Device Attributes {{most_recently_used_device.${carrier}}}, {{most_recently_used_device.${id}}}, {{most_recently_used_device.${idfa}}}, {{most_recently_used_device.${model}}}, {{most_recently_used_device.${os}}}, {{most_recently_used_device.${platform}}}
Email List Attributes (learn more here) {{${set_user_to_unsubscribed_url}}}, {{${set_user_to_subscribed_url}}}, {{${set_user_to_opted_in_url}}}
Campaign Attributes* {{campaign.${api_id}}}, {{campaign.${name}}}
Canvas Attributes* {{canvas.${name}}}, {{canvas.${api_id}}}, {{canvas.${variant_name}}}, {{canvas.${variant_api_id}}}
Card Attributes* {{card.${api_id}}}, {{card.${name}}}
Event Properties These are custom to your app group and in the format {{event_properties.${your_custom_event_property}}}.
Custom Attributes These are custom to your app group and in the format {{custom_attribute.${your_custom_attribute}}}.

* Campaign, Card, and Canvas attributes are only supported in their corresponding messaging templates.

Setting Default Values

We highly recommend that you use set default fallback values for any personalization attribute that you use in your messages. Default values can be added by specifying a Liquid Filter with the name “default.” If a default value is not provided and the field is missing or not set on the user, the field will be blank in the message.

The example below shows the correct syntax for adding a default value. In this case, the words “Valued User” will replace the attribute {{${first_name}}} if a user’s first_name field is blank or unavailable.

Hi {{${first_name} | default: 'Valued User' }}, thanks for using the App!

As a convenience, you may insert preformatted variables with defaults through the “Insert Personalization Attribute” modal located on the top-right of a templatable text field.

Modal buttons

The modal will insert Liquid with your specified default value at the point that your cursor was. The insertion point is also specified via the preview box, which has the before and after text. If a block of text is highlighted, the highlighted text will be replaced.

Modal

Most Recently Used Device Information

You can template in the following attributes for the user’s most recent device across all platforms. If a user has not used your application (e.g., you imported the user via REST API), then these values will all be null.

  • {{most_recently_used_device.${id}}} - This is Braze’s device identifier. On iOS, this is the Apple Identifier for Vendor (IDFV). For Android and other platforms, it is Braze’s device identifier, a randomly generated GUID.
  • {{most_recently_used_device.${carrier}}} - The most recently used device’s telephone service carrier, if available. Examples include “Verizon” and “Orange”.
  • {{most_recently_used_device.${idfa}}} - For iOS devices, this value will be the Identifier for Advertising (IDFA) if your application is configured with Braze’s optional IDFA collection. For non-iOS devices, this value will be null.
  • {{most_recently_used_device.${model}}} - The device’s model name, if available. Examples include “iPhone 6S” and “Nexus 6P” and “Firefox”.
  • {{most_recently_used_device.${os}}} - The device’s operating system, if available. Examples include “iOS 9.2.1” and “Android (Lollipop)” and “Windows”.
  • {{most_recently_used_device.${platform}}} - The device’s platform, if available. If set, the value will be one of ios, android, windows, windows8, kindle, android_china, web, or tvos.

Because there are such a wide range of device carriers, model names, and operating systems, we advise that you thoroughly test any logic that conditionally depends on any of those values. These values will be null if they are not available on a particular device.

Targeted Device Information

For push notification and in-app message channels, you can template in the following attributes for the device to which a message is being sent. That is, a push notification or in-app message can include device attributes of the device on which the message is being read.

  • {{targeted_device.${id}}} - This is Braze’s device identifier. On iOS, this is the Apple Identifier for Vendor (IDFV). For Android and other platforms, it is Braze’s device identifier, a randomly generated GUID.
  • {{targeted_device.${carrier}}} - The most recently used device’s telephone service carrier, if available. Examples include “Verizon” and “Orange”.
  • {{targeted_device.${idfa}}} - For iOS devices, this value will be the Identifier for Advertising (IDFA) if your application is configured with Braze’s optional IDFA collection. For non-iOS devices, this value will be null.
  • {{targeted_device.${model}}} - The device’s model name, if available. Examples include “iPhone 6S” and “Nexus 6P” and “Firefox”.
  • {{targeted_device.${os}}} - The device’s operating system, if available. Examples include “iOS 9.2.1” and “Android (Lollipop)” and “Windows”.
  • {{targeted_device.${platform}}} - The device’s platform, if available. If set, the value will be one of ios, android, windows, windows8, kindle, android_china, web, or tvos.

Because there are such a wide range of device carriers, model names, and operating systems, we advise that you thoroughly test any logic that conditionally depends on any of those values. These values will be null if they are not available on a particular device. Furthermore, for push notifications, it is possible that Braze may be unable to discern the device attached to the push notification under certain circumstances such as if the push token was imported via API, resulting in values being null for those messages.

Personalization

In some circumstances, you may opt to use conditional logic instead of setting a default value. Conditional logic allows you to send messages that differ based on the value of a custom attribute.

Additionally, you can use conditional logic to abort messages to customers with null or blank attribute values.

For example, if you’re sending a rewards balance notification to customers, there isn’t a good way to account for customers with low and null balances using default values.

In this case, there are two options that may work better than setting a default value:

  1. Abort the message for customers with low, null and blank balances.

    NoBalanceAbort

  2. Send a completely different message to these customers, perhaps something along the lines of:

{% if ${first_name} != blank and ${first_name} != null %}
Hello {{${first_name} | default: 'there'}}, thanks for downloading
{% else %}
Thanks for downloading
{% endif %}

In this example, a user with a blank or null first name will get the message “Thanks for downloading”. Note that as a best practice, you should still include a default value for first name.

Conditional Messaging Logic (Tags)

Tags allow you to include programming logic in your messaging campaigns.

A tag must be wrapped in {% %}.

Tags can be used for executing conditional statements as well as for advanced use cases, like assigning variables or iterating through a block of code.

Conditional Logic

You can include many types of intelligent logic within messages – one example is a conditional statement. See the following example which uses conditionals to internationalize a campaign:

{% if ${language} == 'en' %}
This is a message in English from Braze!
{% elsif ${language} == 'es' %}
Este es un mensaje en español de Braze !
{% elsif ${language} == 'zh' %}
这是一条来自Braze的中文消息。
{% else %}
This is a message from Braze! This is going to go to anyone who did not match the other specified languages!
{% endif %}

Conditional Logic: Step By Step

In this example, we use tags with “if”, “elsif” and “else” statements to deliver internationalized content.

{% if ${language} == 'en' %}
This is a message in English from Braze!

If the customer’s language is English, the first condition is met and the customer will receive a message in English.

{% elsif ${language} == 'es' %}
Este es un mensaje en español de Braze !
{% elsif ${language} == 'zh' %}
这是一条来自Braze的中文消息。

You can specify as many conditional statements as you’d like- subsequent conditions will be checked if the previous conditions are not met. In this example, if a customer’s device is not set to English this code will check to see if the customer’s device is set to Spanish or Chinese. If the customer’s device meets one of these conditions, the customer will receive a message in the relevant language.

{% else %}
This is a message from Braze! This is going to go to anyone who did not match the other specified languages!

You have the option to include an {% else %} statement in your conditional logic. If none of the conditions that you set are met, the {% else %} statement specifies the message that should send. In this case, we default to English if a customer’s language is not English, Spanish or Chinese.

{% endif %}

The {% endif %} tag signals that you’ve finished your conditional logic. You must include the {% endif %} tag in any message with conditional logic. If you do not include an {% endif %} tag in your conditional logic, you’ll get an error as Braze will be unable to parse your message.

Operators

Liquid supports many operators that can be used in your conditional statements.

Syntax Operator Description
== equals
!= does not equal
> greater than
< less than
>= greater than or equal to
<= less than or equal to
or condition A or condition B
and condition A and condition B
contains checks to see if a string or string array contains a string

Operator Examples

Here are some examples of how these operators could be helpful for your marketing campaigns:

Total Revenue - sending messages based on an integer custom attribute for “Total Revenue”:

total revenue

In this example, if a customer’s “Total Revenue” custom attribute is greater than zero, they will get the message:

We appreciate your business! Use our coupon SAVE10 for an extra 10% off your next purchase.

If a customer’s “Total Revenue” custom attribute does not exist or is equal to 0, they will get the following message:

Make your first purchase today! Use our coupon SAVE10 for an extra 10% off

Games Attended - sending messages that differ based on an integer attribute, “Number Games Attended”:

games liquid

In this example, if you have attended one game, you get the following message:

Loved that sport game? Get 10% off your second one with code SAVE10

If you have attended more than one game, you get:

Love sports games? Get 10% your next one with code SAVE10

If you haven’t attended any games, or that custom attribute doesn’t exist on your profile, you’d get the following message:

Attend your first game! 10% off with code SAVE10

Accounting For Null Attribute Values

Conditional logic is a useful way to account for null attribute values. A null value occurs when the value of a custom attribute has not been set. For example, a user who has not yet set their first name will not have a first name in Braze’s database.

In some circumstances, you may wish to send a completely different message to users who have a first name set and users who do not have a first name set.

The following tag allows you to specify a message for users with a null “first name” attribute:

{% if ${first_name} == null %}

NullValues

Aborting Messages

Optionally, you can also now abort messages within conditionals. Here are some examples of how this feature can be used in marketing campaigns:

Aborting message if “Number Games Attended” = 0:

For example, let’s say that you did not want to send the above message to customers who had not attended a game:

liquid abort message

This message will only send to customers who are known to have attended a game.

Messaging English speaking customers only:

You can message English speaking customers only by creating an “if” statement that’ll match when a customer’s language is English and an else statement that’ll abort the message for anyone who does not speak English or does not have a language on their profile.

{% if ${language} == 'en' %}
Send this message in English!
{% else %}
{% abort_message() %}
{% endif %}

You can have the abort_message log something to your Developer Console log by including a string inside the parentheses:

{% abort_message('language was nil') %}

developer_console

Manipulating Message Content (Filters)

Filters can be used to reformat static or dynamic content. For example, you can use a filter to reformat a string from uppercase to lowercase or to perform mathematical operations.

Filters should be placed within an output tag {{ }} and should be separated from the value that you’d like to reformat with a pipe character |.

For example, the output of {{"Big Sale" | upcase}} is “BIG SALE”.

Or, let’s say that you’re running a campaign where you’re offering customers 50 rewards points if they make a purchase and you’ve stored their current rewards balance as a custom attribute.

You can use the add filter to show customers what their rewards balance would be if they made an additional purchase:

Hey Marion, make a purchase today to earn 50 pts and bring your rewards balance to {{custom_attribute.${current_rewards_balance} | plus: 50}}.

Math Filters

Math filters allow you to complete basic mathematical operations in the message composer. For example, you can add or subtract static values or variables to and from numeric personalizable attributes, other static values and or other variables. In this example, let’s assume that the value of current_rewards_balance is 50.

Input:

Hey Marion, make a purchase today to earn 50 pts and bring your rewards balance to {{custom_attribute.${current_rewards_balance} | plus: 50}}.

Output:

Hey Marion, make a purchase today to earn 50 pts and bring your rewards balance to 100.

You cannot perform mathematical operations with two custom attributes. You must first define one of the custom attributes as a variable and then perform the operation with the variable and the remaining attribute.

For example,

{{custom_attribute.${current_rewards_balance} | plus: {{custom_attribute.${giftcard_balance}}}}}

will not work. Instead, you should use a variable tag to capture the value of one of the custom attributes:

{% assign balance = {{custom_attribute.${current_rewards_balance}}} %}
{{custom_attribute.${giftcard_balance} | plus: balance}}

String Filters

String filters are used to manipulate the outputs and variables of strings. For example, you can capitalize a string.

Array Filters

Array filters can be used to manipulate the outputs of arrays. All array filters listed here are compatible with Braze’s message composer.

For example, the first filter can used to template the first value in an array into the message composer. Please note that the first value in an array custom attribute array is the most recently added value.

{{custom_attribute.${my_array} | first}} will yield the most recently added value. If “my_array” is a custom attribute array that consists of “apple, orange, banana” the output of {{custom_attribute.${my_array} | first}} will be “apple”.

Date Filters

Date filters can be used to convert a timestamp into a different date format. Let’s say that the value of “date_attribute” is the timestamp 2015-06-03 17:13:41 UTC.

{{custom_attribute.${date_attribute} | date: "%b","%d"}} will reformat this timestamp to “03 June”. There are many other date formatting options which you can find here.

In addition to these formatting options, we also support converting a timestamp to Unix time with the “%s” date filter.

For example, to get the “date_attribute” in Unix time, you’d input {{custom_attribute.${date_attribute} | date: "%s" }} and get the integer 1433351621 as an output.

In addition to the filters that you’ll find listed in Shopify’s documentation, we also support the “time_zone” filter.

The “Time_zone” filter takes a time, a time zone, and a date format and returns the time in that timezone in the specified date format. For example, let’s say that the value of {{custom_attribute.${date_attribute}}} is 2015-04-03 9:00:00 UTC.

Input:

{{custom_attribute.${date_attribute} | time_zone: 'America/Los_Angeles' | date: '%a %b %e %T' }}

Output:

Fri April 3 2:00:00

Additionally you can access the current time for manipulation by doing something like the following:

{{ 'now' | date: '%Y-%m-%d %H:%M:%S' }}

Which will return something like:

2016-08-22 18:13:13

Advanced Filters

Encoding Filters

filter name filter description example input example output
md5 returns md5 encoded string {{'hey' | md5}} 6057f13c496ecf7fd777ceb9e79ae285
sha1 returns sha1 encoded string {{'hey' | sha1}} 7f550a9f4c44173a37664d938f1355f0f92a47a7
sha2 returns sha2 encoded string {{'hey' | sha2}} fa690b82061edfd2852629aeba8a8977b57e40fcb77d1a7a28b26cba62591204
base64 encodes string into base64 {{'blah' | base64_encode}} YmxhaA==
hmac_sha1 returns hmac-sha1 encoded string {{'hey' | hmac_sha1: 'secret_key'}} 2a3969bed25bfeefb00aca4063eb9590b4df8f0e

URL Filters

filter name filter description example input example output
url_escape identifies all characters in a string that are not allowed in URLS, and replaces the characters with their escaped variants {{'hey<>hi' | url_escape}} hey%3C%3Ehi
url_param_escape replaces all characters in a string that are not allowed in URLs with their escaped variants, including the ampersand (&) {{'hey<&>hi' | url_param_escape} hey%3C%26%3Ehi
url_encode encodes a string that is url friendly {{ 'google search' | url_encode }} google+search

Property Accessor Filter

property_accessor takes a hash and hash key and returns the value in that hash at that key

Example hash : {“a” => 42, “b” => 0}

Example input: {{hash | property_accessor: 'a'}}

Example output: 42

Additionally, the property accessor filter allows you to template a custom attribute into a hash key to access a particular hash value.

Number formatting filters

filter name filter description example input example output
number_with_delimiter Formats a number with commas {{ 123456 | number_with_delimiter }} 123,456

JSON Escape / String Escape Filter

json_escape escapes any special characters in a string (i.e. double quote "" and backslash ‘').

This filter should always be used when personalizing a string in a JSON dictionary and is useful for webhooks in particular.

Advanced Use Cases

Variable Tags

You can use the assign tag to create a variable in the message composer. Once you create a variable, you can reference that variable in your messaging logic or message.

Let’s say that you allow your customers to cash in their rewards points for prizes once they accrue 100 rewards points. So, you only want to message customers who would have a points balance above or equal to 100 if they made that additional purchase:


{% assign new_points_balance = {{custom_attribute.${current_rewards_balance} | plus: 50}} %}
{% if new_points_balance >= 100 %}
Make a purchase to bring your rewards points to {{new_points_balance}} and cash in today!
{% else %}
{% abort_message('not enough points') %}
{% endif %}

This tag comes in handy when you want to reformat content that is returned from our connected content feature. You can read more about variable tags here.

Iteration Tags

Iteration tags can be used to run a block of code repeatedly. This example features the for tag.

Let’s say that you’re having a sale on Nike sneakers and want to message customers who’ve expressed interest in Nike. You have an array of product brands viewed on each customer’s profile. This array could contain up to 25 product brands, but you only want to message customers who viewed a Nike product as one of their 5 most recent product views.

{% for items in {{custom_attribute.${Brands Viewed}}} limit:5 %}
{% if {{items}} contains 'Converse' %}
{% assign converse_viewer = true %}
{% endif %}
{% endfor %}
{% if converse_viewer == true %}
Sale on Converse!
{% else %}
{% abort_message() %}
{% endif %}

In this example, we check the first five items in the sneaker brands viewed array. If one of those items is converse, we create the converse_viewer variable and set it to true.

Then, we send the sale message when converse_viewer is true. Otherwise, we abort the message.

This is a simple example of how iteration tags can be used in Braze’s message composer. You can find more information here.

HTTP Status Codes

You can utilize the HTTP status from a Connected Content call by first saving it as a local variable and then using the __http_status_code__ key. For example:

{% connected_content https://example.com/api/endpoint :save connected %}
{% if connected.__http_status_code__ != 200 %}
{% abort_message('Connected Content returned a non-200 status code') %}
{% endif %}

Be aware that this key will only be automatically added to the Connected Content object if the endpoint returns a JSON object. If the endpoint returns an array or other type, then that key cannot be set automatically in the response.

Sending Messages Based on Language, Most Recent Locale, and Time Zone

In some situations you may wish to send messages that are specific to particular locales. For example, Brazilian Portuguese is typically different than European Portuguese.

Here’s an example of how you can use most recent locale to further localize an internationalized message.

{% if ${language} == 'en' %}
Message in English
{% elsif  ${language} == 'fr' %}
Message in French
{% elsif  ${language} == 'ja' %}
Message in Japanese
{% elsif  ${language} == 'ko' %}
Message in Korean
{% elsif  ${language} == 'ru' %}
Message in Russian
{% elsif ${most_recent_locale} == 'pt_BR' %}
Message in Brazilian Portuguese
{% elsif ${most_recent_locale} == 'pt_PT' %}
Message in European Portuguese
{% elsif  ${language} == 'pt' %}
Message in default Portuguese
{% else %}
Message in default language
{% endif %}

In this example, customers with a most recent locale of ‘pt_BR’ will get a message in Brazilian Portuguese, customers with a most recent locale of ‘pt_PT’ will get a message in European Portuguese and customers who don’t meet the first two conditions but have their language set to Portuguese will get a message in whatever you’d like the default Portuguese language type to be.

You can also target users based off of their time zone. For example, send one message if they are based in EST and another if they are PST. To do this, save the current time in UTC, and compare an if/else statement with the user’s current time to ensure you’re sending the right message for the right timezone. You should set the campaign to send in the user’s local time zone, to ensure they are getting the campaign at the right time. See below for an example of how to write a message that will go out between 2PM and 3PM and will have a specific message for each time zone.

{% assign hour_in_utc = 'now' | date: '%H' | plus:0 %}
{% if hour_in_utc >= 19 && hour_in_utc < 20 %}
It is between 2:00:00pm and 2:59:59pm ET!
{% elsif hour_in_utc >= 22 && hour_in_utc < 23 %}
It is between 2:00:00pm and 2:59:59pm PT!
{else}
{% abort_message %}
{% endif %}

Deep-Linking to In-App Content

What is Deep-Linking?

Deep linking is a way of launching a native app and providing additional information telling it to do some specific action or show specific content.

There are three parts to this:

  • Identify which app to launch
  • Instruct the app which action to perform
  • Provide the action with any additional data it will need

Deep links are custom URIs that link to a specific part of the app and contain all of the above parts. The key is defining a custom scheme. “http:” is the scheme with which almost everyone is familiar but schemes can begin with any word. A scheme must start with a letter, but can then contain letters, numbers, plus-signs, minus-signs or dots. Practically speaking, there is no central registry to prevent conflicts, so it is a best practice to include your domain name in the scheme. For example, “twitter://” is the iOS URI to launch Twitter’s mobile app.

Everything after the colon within a deep link is free-form text. It is up to you to define its structure and interpretation, however, a common convention is to model it after “http:” urls, including a leading “//” and query parameters (e.g. “?foo=1&bar=2”). For the Twitter example, “twitter://user?screen_name=[id]” would be utilized to launch a specific profile in the app.

These deep links are a powerful tool when used in tandem with the Braze News Feed. Providing deep links as the URI within News Feed items allows you to utilize the News Feed as an individualized navigation tool to direct users to content inside in your app. They can also be utilized to direct users from push notifications and in-app messages to relevant app sections and content.

Keep in mind that enabling these deep links requires some additional setup within your app. Please reference our documentation on deep links for iOS and on how to deep link to the News Feed for Android to understand the requirements for implementation.

UTM Tags and Campaign Attribution

What is a UTM Tag?

UTM (Urchin Traffic Manager) tags allow you to include campaign attribution details directly within links. UTM tags are used by Google Analytics to collect campaign attribution data, and can be used to track the following properties:

  • utm_source: the identifier for the source of the traffic (e.g. my_app)
  • utm_medium: the campaign medium (e.g. newsfeed)
  • utm_campaign: the identifier for the campaign (e.g. spring_2016_campaign)
  • utm_term: identifier for a paid search term that brought the user to your app or website (e.g. pizza)
  • utm_content: an identifier for the specific link/content that the user clicked on (e.g. toplink or android_iam_button2)

UTM tags can be embedded into both regular HTTP (web) links and deep links and tracked using Google Analytics.

Using UTM Tags with Braze

If you want to use UTM tags with regular HTTP (web) links, for example to do campaign attribution for your e-mail campaigns, and your organization already uses Google Analytics, you can simply use Google’s URL builder to generate UTM links. These links can be readily embedded into Braze campaign copy just like any other link.

In order to use UTM tags in deep links to your app, your app must have the relevant Google Analytics SDK integrated and correctly configured to handle deep links. Check with your developers if you’re unsure about this.

Once the Analytics SDK is integrated and configured, UTM tags can be used with deep links in Braze campaigns. To set up UTM tags for your campaign, simply include the necessary UTM tags in the destination URL or deep links. The examples below show how to use UTM tags in push notifications, News Feed cards and in-app messages.

Attributing Push Opens with UTM Tags

To include UTM tags in your deep links for push notifications, simply set the on click behavior of the push message to be a deep link, write the deep link address and include the desired UTM tags in the following fashion:

myapp://products/20-gift-card?utm_source=my_app&utm_medium=push&utm_campaign=spring2016giftcards&utm_content=ios_deeplink

UTM Tags in Push Message

Attributing News Feed Clicks with UTM Tags

News Feed items deep linking into your app can be configured to use UTM tags as well. Note that you can use utm_content to separate between deep links on different OSes.

UTM Tags in News Feed

Attributing In-App Message Clicks with UTM Tags

Similarly to push notifications and news feed cards, you can include UTM tags in the deep links included within your in-app messages.

UTM Tags in In-App Message

Emoji Messaging

If you are using Chrome as your browser, we recommend using the EmojiOne extension to conveniently insert emojis. If not, emojis can be sent to your users via push notifications or email in a few easy steps.

Mac Users

Accessing Emojis on Your Computer

First open the dictionary application and select ‘Emoji & Symbols’ from the ‘Edit’ tab at the top of your screen.

Emoji Step One

Next, browse through and select the emoji/emojis that you would like to use in your message.

Emoji Step Two

Inserting Emojis Into Your Messages

To insert emojis into your message channels, select your desired symbol then copy and paste it directly into the body text of your message.

Push Emoji

Windows Users

Accessing Emojis on Your Computer

First follow this link to access the unicode native standards for emojis.

Inserting Emojis Into Your Messages

To insert emojis into your message channels, highlight, click and drag the native standard of your desired symbol into the body text of your message as demonstrated in the image below. You can also highlight the emoji then copy/paste it into the message composer.

Troubleshooting

Many of the available emojis are currently unviewable in the Chrome browser. This issue will not affect the sending of emojis across Braze messaging channels, and the emojis will still be successfully delivered to your users. Try using another browswer such as Safari or Firefox to accurately preview the emojis in your messages.

Connected Content

Braze’s Connected Content feature expands on marketing personalization to boost customer engagement and conversions. This feature allows you to insert any information accessible via API directly into messages you send to users. Connected Content allows for pulling content either directly from your web server or from publicly accessible APIs.

Making an API Call

Messages sent by Braze can retrieve content from a web server to be included in a message by using the {% connected_content %} tag. For example, the following message body will access the url http://numbersapi.com/random/trivia and include a fun trivia fact in your message:

Hi there, here is fun some trivia for you!: {% connected_content http://numbersapi.com/random/trivia %}

You can also include user profile attributes as variables in the URL string when making Connected Content requests. As an example, you may have a web service that returns content based on a user’s email address and ID. If you’re passing attributes containing special characters, such as @, make sure to use the Liquid filter url_param_escape to replace any characters not allowed in URLs with their URL-friendly escaped versions, as shown in the e-mail address attribute below.

Hi, here are some articles that you might find interesting:

{% connected_content http://www.yourwebsite.com/articles?email={{${email_address} | url_param_escape}}&user_id={{${user_id}}} %}

If the URL is unavailable, Braze will render an empty string in its place. Because Braze delivers messages at a very fast rate, be sure that your server can handle thousands of concurrent connections so we do not overload your server when pulling down content. When using public APIs, ensure your usage will not violate any rate-limiting that the API provider may employ. Braze requires that server response time is less than 2 seconds for performance reasons; if the server takes longer than 2 seconds to respond, the content will not be inserted.

If the endpoint returns JSON, you can detect that by checking if the connected value is null, and then conditionally abort the message. Additionally, Connected Content messages are processed with lower priority in our systems as not to roadblock other messaging campaigns due to long response times from servers. As a result, you may notice that delivery on Connected Content messages are slightly slower than other messages you send normally. Braze only allows URLs that communicate over port 80 (HTTP) and 443 (HTTPS).

Attribute values must be surrounded by ${} in order to operate properly within Braze’s version of Liquid Syntax.

Connected Content calls do not follow redirects.

Braze’s systems may make the same Connected Content API call more than once per recipient. That is because Braze may need to make a Connected Content API call to render a message payload, and message payloads can be rendered multiple times per recipient for the purposes of validation, retry logic, or other internal purposes. Your systems should be able to tolerate the same Connected Content call being made more than one time per recipient.

Using Basic Authentication

If the URL requires basic authentication, Braze can generate a basic authentication credential for you to use in your API call. In the Connected Content tab in Manage App Group, you can manage existing basic authentication credentials and add new ones.

Basic Authentication Credential Management

To add a new credential, click Add Credential. You can then name your credential and put in the username and password.

Basic Authentication Credential Creation

You can then use this basic authentication credential in your API calls by referencing the token’s name:

Hi there, here is fun some trivia for you!: {% connected_content https://yourwebsite.com/random/trivia :basic_auth credential_name %}

If you delete a credential, keep in mind that any Connected Content calls trying to use it will be aborted.

Local Connected Content Variables

Braze makes a standard GET request to the endpoint specified within the connected_content tag. If the endpoint returns JSON, it is automatically parsed and stored in a variable called connected. If the endpoint returns text, it will be directly inserted into the message in place of the connected_content tag.

If you want to save your response to a variable, it’s recommended to return JSON objects. And if you want the response of connected content to replace the tag with the text, make sure the response is not valid JSON (as defined by json.org)

You can also specify :save your_variable_name after the url in order to save the data as something else. For example, the following connected_content tag will store the response to a local variable called localweather (you can save multiple connected_content JSON variables):

{% connected_content https://www.metaweather.com/api/location/2459115/ :save localweather %}

Metaweather is a free weather API that uses a “Where-on-Earth ID” to return weather in an area. Use this code for testing / learning purposes only. For more information about this API, see here.

The stored variable can only be accessed within the field which contains the connected_content request. For example, if you wanted to use the localweather variable in both the message and title field, you should make the connected_content request within both fields. If the request is identical, Braze will use the cached results, rather than making a second request to the destination server. However, Connected Content calls made via HTTP POST do not cache and will make a second request to the destination server.

JSON Parsing

Connected Content will interpret any JSON-formatted results into a local variable, when you specify :save. For example, a weather-related Connected Content endpoint returns the following JSON object, which you store into a local variable localweather by specifying :save localweather.

{
  "consolidated_weather": [
    {
      "id": 5.8143475362693e+15,
      "weather_state_name": "Clear",
      "weather_state_abbr": "c",
      "wind_direction_compass": "WSW",
      "created": "2017-06-12T14:14:46.268110Z",
      "applicable_date": "2017-06-12",
      "min_temp": 22.511666666667,
      "max_temp": 31.963333333333,
      "the_temp": 27.803333333333,
      "wind_speed": 6.8884690250312,
      "wind_direction": 251.62921994166,
      "air_pressure": 1021.335,
      "humidity": 50,
      "visibility": 14.945530601288,
      "predictability": 68
    },
	.
	.
	.
  "title": "New York",
  "location_type": "City",
  "woeid": 2459115,
  "latt_long": "40.71455,-74.007118",
  "timezone": "US\/Eastern"
}

You can test whether or not it’s raining by referencing {{localweather.consolidated_weather[0].weather_state_name}}, which if used on the object above would return Clear. If you want to also personalize with the resulting location name, {{localweather.title}} returns New York.

The following image illustrates the type of syntax highlighting you should see in the dashboard if you’re setting things up correctly. It also demonstrates how you could leverage the connected_content request above!

Connected Content Syntax Example

If the API responded with {{localweather.consolidated_weather[0].weather_state_name}} returning Rain, the user would then receive this push.

Connected Content Push Example

By default, Connected Content does not set a Content-Type or Accept header on the HTTP GET request that it makes. By adding :content_type application/json to the tag, Braze will set both the Content-Type and Accept header to the type you specify.

{% connected_content http://numbersapi.com/random/trivia :content_type application/json %}

HTTP POST

By default, Connected Content makes an HTTP GET request to the specified URL. To make a POST request instead, specify :method post.

You can optionally provide a POST body by specifying :body followed by a query string of the format key1=value1&key2=value2&.... Content-Type defaults to application/x-www-form-urlencoded unless you specify :content_type application/json, in which case Braze will automatically JSON-encode the body before sending.

{% connected_content https://post.example.com/someEndpoint :method post :body key1=value1&key2=value2 %}

HTTP Status Codes

You can utilize the HTTP status from a Connected Content call by first saving it as a local variable and then using the __http_status_code__ key. For example:

{% connected_content https://example.com/api/endpoint :save result %}
{% if result.__http_status_code__ != 200 %}
  {% abort_message('Connected Content returned a non-200 status code') %}
{% endif %}

Be aware that this key will only be automatically added to the Connected Content object if the endpoint returns a JSON object. If the endpoint returns an array or other type, then that key cannot be set automatically in the response.

Configurable Caching

Connected Content will cache the value it returns from non POST endpoints for a minimum of 5 minutes. If a cache time is not specified, the default cache time is also 5 minutes. However, this cache time can be configured to be longer. For example:

#  Will cache for 900 seconds (15 minutes)
{% connected_content https://example.com/webservice.json :cache 900 %}

Aborting Messages

Using Liquid templating, you have the option to abort messages within conditionals. For example:

{% connected_content https://example.com/webservice.json :save connected %}
   {% if connected.recommendations.size < 5 or connected.foo.bar == nil %}
     {% abort_message() %}
   {% endif %}

You can also specify an abort reason, which will be saved to the Message Activity Log in your Developer Console:

{% abort_message('Could not get enough recommendations') %}

Braze does not count Aborted Messages towards the send count in your Dashboard or the Raw Event Stream.

Accuweather Example Use-Case

If you have an Accuweather account, you can enrich and personalize your marketing campaigns, as well as automate translations, through Connected Content. Here are all of the Accuweather APIs you can reference within your Braze campaigns:

  • Locations API: Get a location key for your desired location. Use the location key to retrieve weather data from the Forecast or Current Conditions API.
  • Forecast API: Get forecast information for a specific location.
  • Current Conditions API: Get Current Conditions data for a specific location.
  • Indices API: Get daily index values for a specific location. Index availability varies by location.
  • Weather Alarms API: Get Weather Alarms for a specific location. AccuWeather Weather Alarms are determined using the daily forecasts for a location. An alarm exists for a location if the forecast weather meets or exceeds specific thresholds.
  • Alerts API: Get severe weather alerts from official Government Meteorological Agencies and leading global weather alert providers.
  • Imagery API: Get radar and satellite images.
  • Tropical API: Get current position, past positions, and forecasts for tropical cyclones worldwide.
  • Translations API: Get a list of available languages. Get translations for specific groups of phrases.

In order to get started, you’ll need to have your app’s Accuweather API key on-hand to use within your request urls.

Accuweather_APIKey2

For example, let’s say that you wanted to run a marketing campaign that has 3 different types of messages based on the current conditions of a user’s zip code in the US.

Within the first connected_content tag you will make a GET request to the Locations API. Here’s an example of what Accuweather will return as the JSON object:

[
  {
    "Version": 1,
    "Key": "41333_PC",
    "Type": "PostalCode",
    "Rank": 35,
    "LocalizedName": "Seattle",
    "EnglishName": "Seattle",
    "PrimaryPostalCode": "98102",
    "Region": {
      "ID": "NAM",
      "LocalizedName": "North America",
      "EnglishName": "North America"
    },
    "Country": {
      "ID": "US",
      "LocalizedName": "United States",
      "EnglishName": "United States"
    },
    "AdministrativeArea": {
      "ID": "WA",
      "LocalizedName": "Washington",
      "EnglishName": "Washington",
      "Level": 1,
      "LocalizedType": "State",
      "EnglishType": "State",
      "CountryID": "US"
    },
    "TimeZone": {
      "Code": "PDT",
      "Name": "America/Los_Angeles",
      "GmtOffset": -7.0,
      "IsDaylightSaving": true,
      "NextOffsetChange": "2018-11-04T09:00:00Z"
    },
    "GeoPosition": {
      "Latitude": 47.636,
      "Longitude": -122.327,
      "Elevation": {
        "Metric": {
          "Value": 26.0,
          "Unit": "m",
          "UnitType": 5
        },
        "Imperial": {
          "Value": 85.0,
          "Unit": "ft",
          "UnitType": 0
        }
      }
    },
    "IsAlias": false,
    "ParentCity": {
      "Key": "351409",
      "LocalizedName": "Seattle",
      "EnglishName": "Seattle"
    },
    "SupplementalAdminAreas": [
      {
        "Level": 2,
        "LocalizedName": "King",
        "EnglishName": "King"
      }
    ],
    "DataSets": [
      "Alerts",
      "DailyAirQualityForecast",
      "DailyPollenForecast",
      "ForecastConfidence",
      "MinuteCast"
    ]
  }
]

Keep the “Key” ID on hand as you’ll need this for the second GET request. You can store the above JSON object into local variable location_info by specifying :save location_info after the url. Here is the example of the connected_content tag:

{% connected_content http://api.accuweather.com/locations/v1/postalcodes/{{${country}}}/search?q={{custom_attribute.${Zip Code}}}&apikey={your API key} :save location_info %}

Note: Alternatively, you could also leverage the user’s {{${city}}} if you do not have a zip code custom attribute.

For the second connected_content tag, you will make a GET request to the Current Conditions API. You’ll need to add the location key to the request url. Here is the example connected_content tag:

{% connected_content http://api.accuweather.com/currentconditions/v1/{{location_info[0].Key}}?apikey={your API key} :save local_weather %}

Here is the returning JSON object:

[
  {
    "LocalObservationDateTime": "2018-04-10T09:35:00-07:00",
    "EpochTime": 1523378100,
    "WeatherText": "Rain",
    "WeatherIcon": 18,
    "IsDayTime": true,
    "Temperature": {
      "Metric": {
        "Value": 11.0,
        "Unit": "C",
        "UnitType": 17
      },
      "Imperial": {
        "Value": 52.0,
        "Unit": "F",
        "UnitType": 18
      }
    },
    "MobileLink": "http://m.accuweather.com/en/us/seattle-wa/98104/current-weather/41333_pc?lang=en-us",
    "Link": "http://www.accuweather.com/en/us/seattle-wa/98104/current-weather/41333_pc?lang=en-us"
  }
]

As you can see from the connect_content tag above, we stored the JSON object into local variable local_weather by adding :save local_weather after the url.

You can test what the output of the WeatherText should be by referencing {{local_weather[0].WeatherText}}.

Bringing our use-case together, here is what the syntax of the campaign would look like:

{% connected_content
http://api.accuweather.com/locations/v1/postalcodes/{{${country}}}/search?q={{custom_attribute.${Zip Code}}}&apikey={your API key} :save location_info %}
{% connected_content
http://api.accuweather.com/currentconditions/v1/{{location_info[0].Key}}?apikey={your API key} :save local_weather %}
{% if {{local_weather[0].WeatherText}} == 'Cloudy' %}
No sunscreen needed :)
{% elsif {{local_weather[0].WeatherText}} == 'Rain' %}
It's raining! Grab an umbrella!
{% else %}
Enjoy the weather!
{% endif %}

If the API responded with {{local_weather[0].WeatherText}} returning Rain, the user would then receive the following push:

Connected Content Push Example

Transifex Example Use-Case

If you have a Transifex account, you can use Braze’s Connected Content feature to automate the translations in your marketing campaigns.

This integration will allow you to type in a source string instead of copying and pasting the translation for every language into the message composer.

In order to set up your Transifex integration, you’ll need to set up basic authentication for your account. In the Connected Content tab in Manage App Group, you can manage existing basic authentication credentials and add new ones.

Basic Authentication Credential Management

To add a new credential, click New Credential. You can then name your credential and put in the username and password.

Basic Authentication Credential Creation

You can then use this basic authentication credential for calls to Transifex.

The code for our Transifex integration was built using Transifex’s translation strings API.

The following CURL will allow you to see if your Transifex account has context values associated with translations:

curl -i -L --user username:password -X GET https://www.transifex.com/api/2/project/<project_name>/resource/<resource_name>/translation/en/strings

You’ll need to input the project and resource name into CURL. You can find these values in the URL of your Transifex account.

Transifex_account

An example response with a blank context field is pictured below:

terminal_response

Transifex Integration Code Example

Here is example code which utilizes the Transifex Strings API and the user’s “language” attribute

{% assign key = "<Insert Key Here>" %}
{% assign context = "<Insert Context Here>" %}
{% assign source_string = key | append: ':' | append: context %}
{% assign project = "<Insert Project Name Here>" %}
{% assign resource = "<Insert Resource Name Here" %}
{% assign source_hash = source_string | md5 %}

{% if {{${language}}} == "en" or {{${language}}} == "it" or {{${language}}} == "de" or {{${language}}} == "another_language_you_support"  %}
{% connected_content https://www.transifex.com/api/2/project/{{project}}/resource/{{resource}}/translation/{{${language}}}/string/{{source_hash}}/ :basic_auth <Insert Basic Auth Credential Name Here> :save strings %}
{% endif %}

{% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {{strings.translation}}
{% else %}
  {% abort_message('null or blank') %}
{% endif %}

Alternatively, you could also leverage the user’s {{${most_recent_locale}}} if you wanted to include a variation based upon a user’s specific version of a language such as zh_CN or pt_BR.

Braze or third parties may make available certain third party products or services to our customers that interoperate with the Braze Services. Any purchase or use of such third party services, and any exchange of data between a customer and such third parties, is solely between that customer and the third party chosen by that customer. Braze does not warrant or support any such third party services or products. Additionally, any customer who chooses to purchase or use any such third party services or products should recognize that any customer data that they submit to such third party products or services may be accessed by Braze in connection with the interoperation of the Braze Services with such third party services. Braze is not responsible for any disclosure, modification or deletion of any customer data by such third party providers, and Braze cannot guarantee the continued availability of any such third party products or services. If such third party discontinues making such services or products available for use with the Braze Services, customers shall not be entitled to any refund, credit or other compensation from Braze.

Connected Content Retries

Because Connected Content relies on receiving data from APIs, there is the possibility that an API is intermittently unavailable while Braze makes the call. In this case, Braze supports retry logic to re-attempt the request using exponential backoff. To enable retries, add :retry in the Connected Content call, as shown below:


{% connected_content https://yourwebsite.com/api/endpoint :retry %}
{% connected_content https://www.braze.com :save my_content :basic_auth auth_name :retry %}

If the API call fails and this is enabled, Braze will retry the call while respecting the rate limit you set for each resend. Braze will move any failed messages to the “back of the queue” and add additional minutes, if necessary, to the total minutes it would take to send your message.

Please note that if a retried attempt succeeds, the message is sent and no further retries are attempted for that message. If the Connected Content call errors out 5 times, the message is aborted similar to if an abort message tag was triggered.

Connected Content :retry is available in emails and push notifications.

Public APIs

There are a variety of publicly available APIs that can be used for Connected Content. As seen in the examples above, public APIs allow you to insert custom data in messages. We’ve compiled a list below of public APIs that could be used for Connected Content. However, there are many more APIs out there, providing a wide variety of potential Connected Content uses. Let us know if you have an API to share!

Public APIs can be subject to usage restrictions and rate limiting. Be sure to read through API documentations and contact API providers about your intended use.

News and Information

API Description
OpenWeatherMap Provides current weather data, 5 and 16 day forecast, and historical data.
NYT Article Search Provides NYT article data which includes headline, topic, URL, date, abstract, etc.
The Guardian API Provides Guardian article data which includes headline, topic, URL, date, abstract, etc.
Alchemy Provides data from an index of 250-300 thousand news articles and blogs.

Events and Ticketing

API Description
SeatGeek Provides ticket information for concerts, sports, and theater events.
OnConnect Provides box-office movie information and showtimes in US and Canadian theaters.
Eventbrite Provides data on a variety of public events.
Eventful Provides data on a variety of public events
Ticketmaster Provides data on public events, venues, and prices

Food & Drink

API Description
BreweryDB Provides information on breweries, beers, and beer events.
Zomato Provides a variety of restaurant information, including ratings, locations, and cuisine.

Finance

API Description
Barchart OnDemand Provides a variety of stock, futures, and foreign exchange data.
CoinDesk Provides a variety of cryptocurrency data.
Yahoo Finance Provides a variety of stock data.

Health

API Description
AirVisual Provides Air quality and weather data.
Nutritionix Worlds Provides verified nutrition data.
openFDA Provides FDA data on drugs, devices, and foods
USDA Nutrients Provides access to the National Nutrient Database.

Music

API Description
Last.fm Provides a variety of music data including artist information, recommended artists, and more.
iTunes Provides data on a variety of items in the iTunes, App Store, and iBooks stores.
Bandsintown Provides local concert information and recommends live music events.
Songkick Provides live music information with artists, venues, locations, etc.
Discogs Provides information on artists, labels, and recordings.

Product Information

API Description
Semantics3 Provides product metadata in a variety of categories.
Factual Provides various product data including nutrition and ingredients data.
eBay Provides live eBay data including item data, popular searches, and more.

Miscellaneous

API Description
Numbers API Provides random numerical trivia facts.
Clearbit Provides company logo images.
London Unified and NYC MTA Provide realtime public transit data including line statuses, arrival times, etc.
Sunrise and Sunset Provides Sunset and sunrise times for a given latitude and longitude.

Key-Value Pairs

Braze enables you to send extra data payloads to user devices via key-value pairs. This feature is available across push, in-app, and News Feed messaging channels. Extra data payloads can help you update internal metrics and app content as well as customize push notification properties, such as alert prioritization, localization, and sounds.

Push Notifications

iOS

Apple Push Notifications service (APNs) supports setting alert preferences and sending custom data using key-value pairs. APNs makes use of the Apple-reserved aps library, which includes predetermined keys and values that govern alert properties.

APS Library
Key Value Type Value Description
alert string or dictionary object For string inputs, displays an alert with the string as the message with Close and View buttons; for non-string inputs, displays an alert or banner depending on the input’s child properties
badge number Governs the number that is displayed as the badge on the app icon
sound string The name of the sound file to play as an alert; must be in the app’s bundle or Library/Sounds folder
content-available number Input values of 1 signal to the app the availabilty of new information upon launch or session resumption
Alert Properties Library
Key Value Type Value Description
title string A short string that Apple Watch displays briefly as part of a notification
body string The push notification’s content
title-loc-key string or null A key that sets the title string for the current localization from the Localizable.strings file
title-loc-args array of strings or null String values that can appear in place of the title localization format specifiers in title-loc-key
action-loc-key array of string or null If present, the specified string sets the localization for the Close and View buttons
loc-key string or null A key that sets the notification message for the current localization from the Localizable.strings file
loc-args array of strings String values that can appear in place of the localization format specifiers in loc-key
launch-image strings The name of an image file in the app bundle you wish to be used as the launch image when users tap the action button or move the action slide

Braze’s message composer automatically handles the creation of the following keys: alert and its properties, content-available, sound, and category. These values can be input directly in the Dashboard as shown below.

iOS Automatic Keys

When Braze sends a push notification to APNs, the payload will be formatted as a JSON.

Simple Payload

{
    "aps" : { "alert" : "Message received from Spencer" },
}

Complex Payload

{
    "aps" : {
        "alert" : {
            "body" : "Hi, welcome to our app!",
            "loc-key" : "France",
            "loc-args" : ["Bonjour", "bienvenue"],
            "action-loc-key" : "Button_Type_1",
            "launch-image" : "Paris"
      },
        "content-available" : 1
    },
}
Custom Key-Value Pairs

In addition to the aps library payload values, you may send custom key-value pairs to a user’s device. In the message composer, click the gear icon and specify your key-value pairs below. The values in these pairs are restricted to primitive types: dictionary (object), array, string, number, and Boolean.

key-valueInput

Use-cases for custom key-value pairs include but are not limited to internal metrics keeping and setting the context for the user interface. Braze allows you to send additional key-value pairs along with a push notification to be used however you so please via your application within the extras key. If you prefer to use another key, ensure that your app can handle this custom key. Note you should avoid handling a top-level key or dictionary called ab in your application.

Apple advises clients to avoid including customer information or any sensitive data as custom payload data. Furthermore, Apple recommends that any action associated with an alert message should not delete data on a device. Note that if you are using the HTTP/2 provider API, any individual payload you send to APNs cannot exceed a size of 4096 bytes. The legacy binary interface, which will soon be depreciated, only supports a payload size of 2048 bytes.

Android

Google Cloud Messaging (GCM) allows you to send send additional data payloads in push notifications using key-value pairs. GCM specifies two types of payloads: notification and data. The notification payload has a 2KB limit and predetermined set of keys that govern message content. The data payload enables developers to send as much as 4KB of custom key-value pairs.

Notification Payload Key-Values
Key Value Type Value Description
body string The content of the push notification
title string The title of the push notification
icon string The file name of the desired image to display

Braze’s message composer automatically handles the creation of the notifcation payload.

Data Payload

Custom key-value pairs can be input by clicking the gear icon and specifying your key-value pairs below.

key-valueInput

Use-cases for custom key-value pairs include but are not limited to internal metrics keeping and setting the context for the user interface; they may be used for whatever purpose you choose. Note that your app’s backend must be able to process custom key-value pairs for the data payload to function properly. For more information on accessing key-value pairs sent with Android push notifications, refer to the Braze Documention.

Braze automatically formats both payloads as a JSON before sending them to GCM.

Notification and Data Payloads

{
    "notification" : {
        "body" : "Message received from Spencer",
        "title" : "Hi Will!",
        "icon" : "Smiley"
    },
    "data" : {
        "volume" : "6.7",
        "contents" : "https://blog.braze.com/"
    }
}
GCM Messaging Options

Android push notifications can be further customized with GCM message options. These include notification priority, sound, delay, lifespan, and collapsibility. These values can be input directly in the Dashboard as shown below. Refer to the Braze Documentation for further instructions on how to set these options in the Braze message composer.

Android Automatic Keys

Silent Push Notifications

A silent push notification is a push notification containing no alert message or sound, used to update your app’s interface or content in the background. These notifications make use of key-value pairs to trigger these background app actions. Silent push notifications also power Braze’s uninstall tracking.

Marketers should test that silent push notifications trigger expected behavior before sending them to their app’s users. Once you compose your iOS or Android silent push notification, ensure that you only target a test user by filtering on external user ID or email address.

Upon campaign launch, you should check that you have not received any visible push notification on your test device. For instructions on how to check if your silent push notification has updated your app as intended, contact your dedicated success manager or success@braze.com.

Please note that the iOS operating system may gate notifications for some features (Uninstall Tracking, Geofences, and Push Stories). Please note that if you are experiencing difficulties with these features, the iOS’s silent notifications gate might be the cause.

Web

Key-value pairs can also be added to web push notifications. Select the gear icon in the Braze message composer to do so.

key-valueInput

In-App Messages

To add a key-value pair to an in-app message, select the gear icon in the Braze message composer.

key-valueInput

Emails

For Braze customers that use SendGrid, key-value pairs will be sent as unique arguments. SendGrid allows you to attach an unlimtied number of key-value pairs up to 10,000 bytes of data. These key-value pairs can be seen in posts from the SendGrid Event Webhook. Note that bounced emails will not deliver key-value pairs to SendGrid.

key-valueInput

News Feed

Key-value pairs can be added to a News Feed Card in the Braze message composer below the categories drop down-menu.

key-valueInput