Personalized Messaging

Appboy 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)

Appboy can automatically substitute values from a given user into your messages. Put your expression inside of two sets of curly brackets to notify Appboy 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 Appboy’s Connected Content feature.

The full range of personalizable attributes are available from the campaign message composing screen by clicking the link titled “View list of supported attributes.”


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!

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 Appboy’s device identifier. On iOS, this is the Apple Identifier for Vendor (IDFV). For Android and other platforms, it is Appboy’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 Appboy’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.


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.


  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 Appboy!
{% elsif ${language} == 'es' %}
Este es un mensaje en español de Appboy !
{% elsif ${language} == 'zh' %}
{% else %}
This is a message from Appboy! 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 Appboy!

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 Appboy !
{% elsif ${language} == 'zh' %}

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 Appboy! 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 Appboy will be unable to parse your message.


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 Appboy’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 %}


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') %}


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.


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


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

Note: 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 Appboy’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.


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


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==

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}} 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 Appboy’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 :save connected %}
{% if connected.__http_status_code__ != 200 %}
{% abort_message('Connected Content returned a non-200 status code') %}
{% endif %}

Note: 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!
{% 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 Appboy 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 Appboy

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 Appboy 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 Appboy 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:


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 the emoji 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.

Windows Emoji


Many of the available emojis are currently unviewable in the Chrome browser. This issue will not affect the sending of emojis across Appboy 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.

Conversion Events

Appboy allows you to track how often users perform specific actions (Conversion Events) after receiving a campaign. Conversion Events allow you to go beyond tracking engagement with notifications and see exactly how your messaging drives your KPIs.

Primary Conversion Event

The Primary Conversion Event is the first event added during campaign creation. It is used to:

  • Compute the winning message variation in multivariate campaigns.
  • Determine the window in which revenue is calculated for the campaign.
  • Adjust message distributions for campaigns using Intelligent Selection.

Step 1: Create a Campaign

Navigate to the Appboy Campaigns page in your company dashboard and click “Create Campaign,” then select the type of campaign you’d like to create.

After setting up your campaign’s messages and, for non-API campaigns, schedule, you’ll have the option to add up to four conversion events for tracking.

Step 2: Add Conversion Events

For each conversion event you wish to track, select the event and conversion deadline:

  1. Select the general type of event you’d like to use.

    Conversion Event Selection

    • Opens App: A user is counted as having converted when they open any one of the apps that you specify (defaults to all apps in the app group).
    • Makes Purchase: A user is counted as having converted when they purchase the product you specify (defaults to any product).
    • Performs Custom Event: A user is counted as having converted when they perform one of your existing custom events (no default, you must specify the event).
    • Upgrade App: A user is counted as having converted when they upgrade the app version on any one of the apps that you specify (defaults to all apps in the app group). Appboy will perform a best-efforts numerical comparison to determine if the version change was in fact an upgrade. For example, a user would convert if they upgrade from version 1.2.3 to 1.3.0 of the application, while Appboy will not register a conversion if a user downgrades from 1.2.3 to 1.2.2. However, if the app’s version names contain strings, such as “1.2.3-beta2”, then Appboy will not be able to determine if a version change was in fact an upgrade. In that situation, Appboy will count it as a conversion when the user’s most recent app version changes.
  2. Set a “conversion deadline.” You have the option of allowing up to a 30 day window during which a conversion will be counted if the user takes the specified action.

Once you’ve selected your conversion events, continue the campaign creation process and begin sending your campaign.

Step 3: View Results

Navigate to the “Details” page to view details for each conversion event associated with the campaign you just created. Regardless of your selected conversion events, you can also see the total revenue that can be attributed to this specific campaign — as well as specific variants — during the window of the Primary Conversion Event (please note, if no conversion events were selected during campaign creation, the time period defaults to 3 days). Additionally, for multivariate messages, you can see the number of conversions and conversion percentage for your control group and each variant.

View Results

Conversion Tracking Rules

  • A user can only convert once on each conversion event for a campaign. For instance, assume a campaign has only one conversion event which is “makes any purchase.” If a user who receives this campaign makes 2 separate purchases within the conversion deadline, only one conversion will be counted.
  • If a user performs one conversion event within the conversion deadlines of two separate campaigns they received, the conversion will register on both campaigns.
  • A user will count as converted if they performed the specific conversion event in the window even if they did not open/click the message


Appboy allows you to control marketing pressure by implementing two different types of rate-limiting for your campaigns. The first focuses on providing the best experience for the end user, while the second takes into consideration the bandwidth of your servers.

User Centric Rate-Limiting

As you create more segments, there are going to be cases where the membership of those segments overlaps. If you’re sending out campaigns to those segments, you want to be sure that you are not messaging your users too often. If a user receives too many messages within a short time period, they will feel over-encumbered and either turn off push notifications or uninstall your app.

Relevant Segment Filters

Appboy provides the following filters in order to help you limit the rate at which your users receive messages:

  • Last Engaged With Message
  • Last Received Any Campaign
  • Last Received Push Campaign
  • Last Received Email Campaign
  • Last Viewed News Feed

Implementing Filters

Consider the following example segment:


This is a standard re-engagement segment. If you have other more targeted segments receiving notifications recently, you may not want your users to be targeted by more generic campaigns directed at this segment. Appending the “Last Received Push Campaign” filter to this campaign, the user has ensured that if they’ve received another notification in the past 24 hours, they will slide out of this campaign for the next 24 hours. If they still meet the other criteria of the segment 24 hours later and haven’t received any more notifications they will slide back into the segment.

Appending this filter to all segments targeted by campaigns would cause your users to receive a maximum of one push every 24 hours. You could then prioritize your messaging by ensuring that your most important messages are delivered before less important messages.

Setting A Max User Cap

Additionally, in the ‘Target Users’ section of your campaign composition, you can limit the total number of users that will receive your message. This feature serves as a check that is independent of your campaign filters, allowing you to freely segment users without needing to worry about over-spamming.

Total Limit Example

Using the filters in this way, you’ll be able to limit the rate at which your users receive notifications on a per channel basis or globally across all message types.

Setting a Max Impression Cap

For in-app messages, you can control marketing pressure by setting a maximum number of impressions that will be displayed to your user base, after which Appboy will not send down more messages to your users. However, it is important to note that this cap is not exact. New in-app message rules are sent down to an app on session start, meaning that it is possible for Appboy to send an in-app message down to the user before the cap is hit, but by the time the user triggers the message, the cap has now been hit. In this situation, the device will still display the message.

For example, let’s say you have a game with an in-app message that triggers when a user beats a level, and you cap it at 100 impressions. There have been 99 impressions so far. Alice and Bob both open the game and Appboy tells their devices that they are eligible to receive the message when they beat a level. Alice beats a level first and gets the message. Bob beats the level next, but since his device has not communicated with Appboy’s servers since his session start, his device is unaware that the message has met its cap and he will also receive the message. However, once an impression cap has been hit, the next time any device requests the list of eligible in-app messages, that message will not be sent down and will be removed from that device.

Delivery Speed Rate-Limiting

If you anticipate large campaigns driving a spike in user activity and overloading your servers, you can specify a per minute rate limit for sending messages. While targeting users during campaign creation, you can click into Advanced Options and select a rate limit (in various increments from 10K to 500K messages per minute).

Per Minute Rate Limit Example

For instance, if you are trying to send out 75K messages with a 10K per minute rate limit, the delivery will be spread out over 8 minutes. Your campaign will deliver 10k for each of the first 7 minutes, and 5K over the last minute. Be wary of delaying time sensitive messages, however, with this form of rate-limiting. If the segment contains 30M users but we set the rate limit to 10K per minute, a large portion of the user base won’t receive the message until the following day.

It is important to note that when sending a multi channel campaign with a speed rate limit, each channel is sent independently of the others. The effect is that users could receive the different channels at different times, and it is not predictable which channel they will get first. For example, if you send a campaign that contains an email and a push notification, you may have 10,000 users with valid push tokens but 50,000 users with valid email addresses. If you set the campaign to send 100 messages per minute, a user could receive the push notification in the first batch of sends and the email in the last batch of sends, almost 9 hours later.

Multi-Channel Campaigns

Keep in mind that the per minute rate limit is adjusted on a per campaign basis. If multiple channels are utilized within a campaign, the rate limit will apply to each of those channels. If your campaign utilizes email and in-app banners with a rate limit of 10K per minute, we will send 20K total messages each minute (10K email, 10K push).

Multi-Platform Push Campaigns

For push campaigns delivering on multiple platforms, the rate limit selected will be equally distributed across platforms. A push campaign leveraging Android, iOS and Windows with a 10K rate limit per minute will equally distribute the 10K messages across the 3 platforms.

Frequency Capping

As your user base continues to grow and your messaging scales to include life cycle, triggered, transactional and conversion campaigns, it’s important to prevent your notifications from appearing spammy or disruptive. By granting greater control over your users’ experience, Frequency Capping enables you to create the campaigns you desire without overwhelming your audience.

Feature Overview

Frequency Capping can be set up for each app group by selecting Global Campaign Settings found underneath the Campaigns tab. From here, you can choose:

  • What message channel you’d like to cap - push, email, in-app or any of those three
  • How many times each user should receive that channel within a certain time frame, which can be measured in minutes, days, weeks (7 days) and months

Each line of frequency caps will be connected using an “AND,” and you’re able to add as many as you wish. In addition, you may include multiple caps for the same message types. For instance, you can cap users to no more than 1 push per day and no more than 3 pushes per week.

Frequency Capping

Delivery Rules

There may be some campaigns - transactional messages, in particular - that you wish to always reach the user, even if she has already reached her frequency cap. For example, a delivery app may wish to send an email or push when an item is delivered regardless of how many campaigns the user has received. If you want a particular campaign to override Frequency Capping rules, you can set this up when scheduling that campaign’s delivery by checking the box next to “Ignore frequency capping settings for this campaign”. When sending API campaigns, which are often transactional, you’ll have the ability to specify that a campaign should ignore Frequency Capping rules within the API request by setting “override_messaging_limits” to “true.”

By default new Campaigns/Canvases that do not obey Frequency Caps will also not count towards them. This is configurable for each Campaign/Canvas. Please note that this behavior changes the default behavior when you turn off Frequency Capping for a Campaign/Canvas; the changes are backwards compatible and do not impact messages that are currently live right now.

Frequency Capping Update

  • Different channels within a multi-channel campaign will individually count towards the frequency cap. For instance, if you create a multi-channel campaign with, say, both push and email, and have Frequency Capping set up for both of those channels, then the push will count toward 1 push campaign and the in-app message will count toward 1 in-app message campaign. The campaign will also count toward 1 “campaign of any type.” If users are capped to 1 push and 1 in-app campaign per day and someone receives this multi-channel campaign, then she will no longer be eligible for push or in-app campaigns for the rest of the day (unless a campaign ignores Frequency Capping rules).

  • Triggered in-app messages will count towards global frequency cap, however they cannot be frequency capped. For instance, an in-app message confirming a purchase will appear after every purchase regardless of frequency capping.

  • Keep in mind that Frequency Capping applies to the campaigns a user receives, and not to individual messages. That is, if you have a recurring campaign that users are re-eligible to receive, each recurring message of each channel will be counted as just one campaign. For instance, if a user receives a recurring push campaign that delivers every day, and she is capped to 2 push campaigns per week, the recurring push messages will collectively count towards 1 push campaign for frequency capping purposes, and for that week, this user will still be eligible to receive a different campaign that contains push.

Multivariate Testing

Introduction to Multivariate Testing

What is Multivariate Testing?

A multivariate test is an experiment that compares users’ responses to multiple versions of the same marketing campaign. These versions share similar marketing goals, but differ in wording and style. The objective is to identify the version of the campaign that best accomplishes your marketing goals. This section walks through how to use multivariate testing to test out differences in content. If you’d like to evaluate differences in message scheduling or timing (for instance, sending an abandoned cart message after 1 hour of inactivity versus 1 day of inactivity), please refer to our section on setting up a Canvas.

As an example of a multivariate test, suppose you have two options for a push notification:

  • This deal expires tomorrow!
  • This deal expires in 24 hours!

Using a multivariate test, you can see which wording results in a higher conversion rate. The next time you send a push notification about a deal, you’ll know which type of wording is more effective.

The Benefits of Multivariate Testing

Multivariate testing gives you an easy, clear way to learn about your audience. You no longer have to guess what users will respond to - every campaign becomes an opportunity to try different variants of a message and gauge audience response.

Specific scenarios in which multivariate testing could come in handy include:

  • The first time you’re trying out a messaging type. Worried about getting in-app messaging right the first time? Multivariate testing allows you to experiment and learn what resonates with your users.
  • The creation of onboarding campaigns and other campaigns that are constantly being sent out. Since most of your users will encounter this campaign, why not ensure that it’s as effective as possible?
  • Cases in which you have multiple ideas for messages to send. If you are unsure of which to choose, run a multivariate test and then make a data-driven decision.
  • Investigating whether your users respond to “tried and true” marketing techniques. Marketers often stick to conventional tactics to engage with users, but every product’s user base is different. Sometimes, repeating your call to action and using social proof won’t get you the results you desired. Multivariate testing lets you step outside the box and discover unconventional tactics that work for your specific audience.

Five Rules for Multivariate Testing

Multivariate testing can unveil powerful insights regarding your users. To ensure that your test results are truly reflective of your users’ behaviors, you need to:

  1. Run the test on a large number of users. Large samples ensure that your results reflect the preferences of your average user and are less likely to be swayed by outliers. Larger sample sizes also allow you to identify winning variants that have smaller margins of victory.

  2. Randomly sort users into different test groups. Appboy’s multivariate testing feature allows you to create up to eight randomly selected test groups. Randomizing is designed to remove bias in the test set and increase the odds of the test groups being similar in composition. This ensures that differing response rates are due to differences in your messages rather than your samples.

  3. Know what elements you are trying to test. Multivariate testing allows you to test differences between several versions of a message. In some cases, a simple test may be most effective, since isolating changes allows you to identify which elements had the greatest impact on response. Other times, presenting more differences between variants will let you examine outliers and compare different sets of elements. Neither method is necessarily wrong, provided you are clear from the beginning what you are trying to test for.

  4. Decide how long your test will run for before beginning the test, and don’t end your test early. Marketers are often tempted to stop tests after they see results that they like, biasing their findings. Resist the temptation to peek and never end your test early!

  5. Include a control group if possible. Including a control group lets you know whether your messages have a greater impact on user conversion than sending no message at all. Learn more about control groups here.

Creating Multivariate Tests with Appboy

How To Create a Multivariate Test

Step 1: Create your campaign

On the Campaigns section of Appboy’s dashboard, click “Create Campaign” and select a channel for the campaign.


Step 2: Compose your variants

Create up to 8 variants of your message. For some ideas on how to get started differentiating your variants, see here.


Step 3: Schedule your campaign

Test scheduling works the same as scheduling any other Appboy campaign. All of Appboy’s standard campaign scheduling options are available.

Step 4: Choose a segment to run your campaign on

Select a segment to send the campaign to. For best practices around choosing a segment to test with, see here.


Optional Step: Limit the number of users to test with

Sometimes, you’ll want to limit the number of users you send a test to, so that later, once you know which of your variants performs best, you will have users who haven’t received the campaign and can be sent the winner. This typically most useful if your test isn’t scheduled to recur and you won’t be using Intelligent Selection.

Limit Users

Step 5: Distribute users among your variants

Decide what percentage of your target segment should receive each of your variants. Or have Intelligent Selection handle the distribution for you.


Step 6: Designate a Conversion Event

Setting a conversion event for a campaign allows you to see how many of the recipients of that campaign performed a particular action after receiving it. Unlike other campaigns, multivariate tests must define a conversion event. You can read more about our Conversion Events feature here.

Step 7: Review and launch

On the confirmation page, review the details of your multivariate campaign and launch the test!

Step 8: View results

Once your campaign has launched, you can check how each variant is performing by selecting clicking on your campaign from the Campaigns section of the dashboard.


You will see a summary of the campaign and statistics on how the different variants are performing. If one variant is outperforming the others with better than 95% confidence, Appboy will mark that variant with a banner indicating that it is best performing.

Messaging type Projected winner is selected based on…
Push conversion rate (if unavailable, open rate)
Email conversion rate (if unavailable, click rate)
In-app message conversion rate (if unavailable, click rate)

Step 9: Select a winner and continue sending

Once you are satisfied that one of your variants is the best performing, you can edit the campaign and adjust the distribution of users so that 100% of users receive the best performing variant. All users in the segment who have not yet received the campaign (including users who enter the segment at a future date) will then get the best performing variant, provided your campaign is scheduled to send again in the future. If you configured your campaign to only send to a limited number of users initially, this is typically when you would also remove that restriction, so that the best variant can reach as many of your segment users as possible.

Keep in mind that Appboy recommends that you wait to select a winner like this until you have 95% confidence in a particular variant. If no variant did better than the others with 95% confidence, it’s possible that multiple variants received similar response rates, or your sample size of users was not large enough to yield 95% confidence. While you can still select a winner, the chances that your selection will not reflect users’ true preferences will be greater than 5%. Follow-up tests may yield more informative results.


Tips For Different Channels

Depending on which channel you select, you’ll be able to test different components of your message. Try to compose variants with an idea of what you want to test and what you hope to prove. What levers do you have to pull and what are the desired effects? While there are millions of possibilities that you can investigate using a multivariate test, we have some suggestions to get you started:

Channel Aspects of Message You Can Change Results To Look For
Push Wording, punctuation, use of images and emojis, deep links, presentation of numbers (e.g. “triple” vs. “increase by 200%”), presentation of time (e.g. “ends at midnight” vs. “ends in 6 hours”) Open and conversion rate
Email Subject, display name, salutation Open and conversion rate
- Use of images, organization of text (e.g. bulleted vs. numbered lists) Click and conversion rate
- Reply-to field, sign-off Unsubscribe and conversion rate
In-app Notification Aspects listed for “push,” message format Click and conversion rate

In addition, the ideal length of your test may also vary depending on channel. Keep in mind the average amount of time most users may need to engage with each channel. For instance, if you’re testing a push, you may achieve significant results faster than when testing email, since users see pushes immediately, but it may be days before they see or open an email. If you’re testing in-app messages, keep in mind that users must open the app in order to see the campaign, so you should wait longer in order to collect results from both your most active app openers as well as your more typical users.

If you’re unsure how long your test should run for, the Intelligent Selection feature can be useful for finding a winning variant efficiently.

Choosing a Segment

Since different segments of your users may respond differently to messaging, the success of a particular message says something about both the message itself and its target segment. Therefore, try to design a test with your target segment in mind. For instance, while active users may have equal response rates to “This deal expires tomorrow!” and “This deal expires in 24 hours!”, users who haven’t opened the app for a week may be more responsive toward the latter wording since it creates a greater sense of urgency.

Additionally, when choosing which segment to run your test on, be sure to consider whether the size of that segment will be large enough for your test. In general, multivariate tests with more variants require a larger test group to achieve statistically significant results. This is because more variants will result in fewer users seeing each individual variant. As a crude guide, you will likely need around 15,000 users per variant (including the control) to achieve 95% confidence in your test results. However, the exact number of users you need could be higher or lower than that depending on your particular case. For more exact guidance on variant sample sizes, consider referring to Optimizely’s Sample Size Calculator.

Intelligent Selection

Intelligent Selection is a feature that analyzes the performance of your campaign twice a day and automatically adjusts the percentage of users that receive each message variant. A variant that appears to be performing better than others will go to more users, while variants that are underperforming will be targeted at fewer users. Each adjustment is made using a statistical algorithm that makes sure we are adjusting for real performance differences and not just random chance.

By looking at performance data in real-time and shifting campaign traffic toward winning variants gradually, Intelligent Selection ensures that more users receive your best performing variant, without any sacrifice in statistical confidence. Intelligent Selection will also rule out underperforming variants and identify high performing variants faster than a traditional A/B test. Basically, with Intelligent Selection, you can test more frequently and with greater confidence that your users will see your best message.

One thing to note is that this only works well for campaigns that are scheduled to send multiple times. Since Intelligent Selection needs initial results to begin adjusting your campaign, a campaign that sends only once won’t benefit. On the other hand, this make Intelligent Selection ideal for campaigns that are scheduled to recur frequently.


Including a Control Group

When you create a multivariate test, you can reserve a percentage of your target audience for a randomized control group. Users in the control group will not receive the test, but Appboy will monitor their conversion rate for the duration of the campaign. When viewing your results, you’ll be able to compare the conversion rates of your variants against a baseline conversion rate provided by your control group. This lets you compare not only the effects of your variants, but also compare the effects of your variants against the conversion rate that would result if you didn’t send a message at all.

The size of the control group for a campaign with Intelligent Selection will be based on the number of variants. If each variant is being sent to more than 20% of users, then the control group will be 20% and the variants will be split evenly across the remaining 80%. However, if you have multiple variants such that each variant is being sent to less than 20% of users, then the control group will have to become smaller. Once Intelligent Selection starts analyzing the performance of your test, the control group will grow or shrink based on the results.

Understanding Your Multivariate Test Results

Congratulations on getting to this stage! Receiving your multivariate test results is, however, not the last step of the testing process. Now you need to understand what your results mean and apply these insights to your engagement strategy.

Understanding Confidence

An important part of your results is the confidence of your test. The confidence shows the reliability of your test results - the greater the confidence, the more reliable your findings. For instance, your results may show that “A” had a 20% click rate and “B” had a 25% click rate. This seems to indicate that “B” is the more effective message. Having a confidence of 95% means that the difference between the two click rates is likely due to an actual difference in users’ responses, and that there is only a 5% likelihood that the difference is due to chance.

In general, a confidence of at least 95% is necessary to show that your results are reflective of users’ actual preferences, and not due to chance. In rigorous scientific tests, 95% confidence is the common benchmark used to determine statistical significance. If you continually fail to achieve 95% confidence, try increasing your sample size or decreasing the number of variants.

Appboy will mark any variants that have 95% confidence with a banner indicating that they are projected as best performing. Winner Banner

Statistically Insignificant Results — Now What?

A test that doesn’t have a confidence of 95% can still hold important insights. Here are a few things you can learn from a test with statistically insignificant results:

  • It’s possible that all of your variants had roughly the same effect. Knowing this saves you the time you would’ve spent making these changes. Sometimes, you may find that conventional marketing tactics, such as repeating your call to action, don’t necessarily work for your audience.
  • While your results may have been due to chance, they can inform the hypothesis for your next test. If multiple variants appear to have roughly the same results, run some of them again alongside new variants to see if you can find a more effective alternative. If one variant does better, but not by a significant amount, you can perform another test in which this variant’s difference is more exaggerated.
  • Keep testing! A test with insignificant results should lead to certain questions. Was there truly no difference between your variants? Should you have structured your test differently? You can answer these questions by running follow-up tests.

While multivariate testing is useful for discovering which type of messaging generates the most response from your audience, it’s also important to understand which alterations in messaging have only a negligible effect. This allows you to either continue testing for another more effective alternative, or save the time that may have been spent deciding between two alternate messages.

Whether or not your multivariate test has a clear winner, it can be helpful to run follow-up test to confirm your results or apply your findings to a slightly different scenario.

One multivariate test can (and should!) inspire ideas for future multivariate tests, as well as guide you toward changes in your messaging strategy. Possible follow-up actions include:

  • Changing your messaging strategy based on test results. Your multivariate results may lead you to change the way you word or format your messaging.

  • Changing the way you understand your users. Each multivariate test will shed light on your users’ behaviors, how users respond to different messaging channels, and the differences (and similarities) among your segments.

  • Improving the way you structure future multivariate tests. Was your sample size too small? Were the differences between your variants too subtle? Each multivariate test provides an opportunity to learn how to improve future tests. If your confidence is low, your sample size is too small and should be enlarged for future tests. If you find no clear difference between how your variants performed, it’s possible that their differences were too subtle to have a discernible effect on users’ responses.

  • Running a follow-up test with a larger sample size. Larger samples will increase the chances of detecting small differences between variants.

  • Running a follow-up test using a different messaging channel. If you find that a particular strategy is very effective in one channel, you may want to test that strategy in other channels. If one type of message is effective in one channel but not effective in another, you may be able to conclude that certain channels are more conducive to certain types of messages. Or, perhaps there is a difference between users who are more likely to enable push notifications and those who are more likely to pay attention to in-app messages. Ultimately, running this sort of test will help you learn about how your audience interacts with your different communication channels.

  • Running a follow-up test on a different segment of users. To do this, create another test with the same messaging channel and variants, but choose a different segment of users. For instance, if one type of messaging was extremely effective for engaged users, it may be useful to investigate its effect on lapsed users. It’s possible that the lapsed users will respond similarly, or they may prefer another one of the other variants. This sort of test will help you learn more about your different segments and how they respond to different sorts of messages. Why make assumptions about your segments when you can base your strategy on data?

  • Running a follow-up test based on insights from a previous test. Use the intuitions you gather from past tests to guide your future ones. Does a previous test hint at one messaging technique being more effective? Are you unsure about what specific aspect of a variant made it better? Running follow-up tests based on these questions will help you generate insightful findings about your users.

A Quick Recap of Multivariate Testing

There’s a lot that can be said on multivariate testing. Looking for a quick summary of this page or a way to easily share this information with your team? Check out this slideshow, which contains our main tips on multivariate testing.

Perfect Your Multivariate Tests from Appboy

This slideshow was originally presented at a NYC Meetup on Optimizing Mobile Apps and is hosted by Slideshare. For more presentations by Appboy, check out our Slideshare page.

Creating a Webhook

Feature Overview

Creating a webhook campaign or including a webhook in a multichannel campaign allows you to trigger non-app actions. More specifically, webhooks can be used to provide other systems and applications with real-time information. You can use webhooks to send information to systems such as Salesforce or Marketo. You can also use webhooks to send information to your backend systems. For example, you might want to credit your customers account with a promotion once they’ve performed a custom event a certain number of times.

Creating a Webhook

Step 1: Set Up a Webhook

Add a new webhook message to a Campaign or Canvas. You can then choose to build a webhook from scratch or use one of our existing templates.

Step 2: Enter the URL for Your Webhook


Enter the HTTP URL. This HTTP URL specifies your endpoint. The endpoint is the place where you’ll be sending the information that you’re capturing in the webhook. If you’d like to send information to a vendor, the vendor should provide this URL in their API documentation. If you’re sending information to your own systems, check with your development or engineering team to ensure that you’re using the correct URL. Appboy only allows URLs that communicate over port 80 (HTTP) and 443 (HTTPS).


Personalization is supported in our HTTP URLs. At times, certain endpoints may require you to identify a user or provide user-specific information as part of your URL. You’ll want to be sure to include a default value for each piece of user specific information that you use in your URL.


Internationalization is supported in the URL and the request body. To internationalize your message, click ‘add languages’ and fill out the flyout.

Step 3: Create the Request Body

Create the body of your webhook request. This is the information that will be sent to the URL that you specified. There are two ways to create the body of your web hook request:

JSON Key/Value Pairs

JSON Key/Value Pairs allow you to easily write a request for an endpoint that expects a JSON format. Do note that you can only use this feature with an endpoint that expects a JSON request. For example, if your key is “message_body,” the corresponding value might be “Your order just arrived.” Once you’ve entered your key value pair, the composer will configure your request in JSON syntax and a preview of your JSON request will automatically populate.


Raw Text

The raw text option gives you the flexibility to write a request for an endpoint that expects a body of any format. For example, you might use this feature to write a request for an endpoint that expects your request to be in XML format.



Personalization is supported in both the JSON Key/Value Pairs option and the raw text option. You can include any user attribute, custom attribute or event property in your request. For example, you can include a customer’s first name and email in your request. Don’t forget to include a default value for each attribute.


Internationalization is supported in raw text.

Step 4: Request Headers and HTTP Method

Certain endpoints may require that you include headers in your request. In the settings section of the composer, you can add as many headers as you’d like. Common use cases for request headers include a content type specification (e.g XML or JSON) and authorization headers that contain your credentials with your vendor or system. Content type specifications have the key “Content-Type” and common values are “application/json” or “application/x-www-form-urlencoded”.

The HTTP Method that you should use will vary depending on the endpoint to which you are sending information. The majority of the time, you’ll be using POST.


Step 5: Test Send Your Message

Before making your campaign go live, you may wish to test send the webhook to make sure the request is formatted properly. To do so, navigate to the preview tab and send the test webhook. You can test the webhook for a random user, a specific user (by entering their email address of external user ID), or a customized user of with attributes of your choosing. If the request is successful a small message will appear at the top of your screen. If the webhook request is unsuccessful a modal will appear with the error response message. The screenshot below is an example of the response of a webhook with an invalid webhook URL.

Webhook Test Feature

Step 6: Continue Campaign Creation

Continuing creating your campaign the way that you normally would. As with all of our message types, you can preview what your request will look like for a particular user, random user or user with specific attributes in the preview section of the webhook composer.

Errors and retry logic

Webhooks rely on Appboy’s servers making requests to an external endpoint, and syntax and other errors may arise. The first step to avoiding webhook errors is to test your webhook campaign for syntax errors and making sure that personalized variables have a default value. However, webhooks may still fail due to issues like expired API keys, rate limits or unexpected server errors. If your webhook fails to send, an error message gets logged to the Developer Console, under “Message Activity Log.” This description contains the time the error occurred, the app name and the error message:

Webhook error

If the message body is not clear enough regarding the source of the error, you should check the documentation of the API endpoint you’re using. These typically provide an explanation of the error codes the endpoint uses as well as what they’re typically caused by.

Like other campaigns, Appboy tracks the delivery of your webhook campaigns and conversions resulting from them. When the webhook request is sent, the receiving server will return a response code indicating what happened with the request. The below table summarizes the different responses the server may send, how they impact campaign analytics and whether, in the case of errors, Appboy will try to redeliver the campaign:

Response code Marked as received? Retried?
20x (success) Yes N/A
30x (redirection) No No
4xx (client error) No No
5xx (server error) No Once (after 120 seconds)


For this example, we’ll configure the Appboy webhook channel to send SMS to your users, via Twilio’s message sending API. For your convenience, a Twilio webhook template is included on the dashboard.


The Webhook URL is provided by Twilio in your dashboard. This URL is unique to your Twilio account, since it contains your Twilio account ID (TWILIO_ACCOUNT_SID).

In our Twilio example, the webhook URL is You can find this URL in the Getting Started section of the Twilio console.


Request Body

The Twilio API expects the request body to be URL-encoded, so we have to start by changing the request type in the Appboy webhook composer to Raw Text. The required parameters for the body of the request are To, From and Body.

The screenshot below is an example of what your request might look like if you are sending an SMS to each user’s phone number, with the body “Hello from Appboy!”.

  • You’ll need to have valid phone numbers on each user profile in your target audience.
  • In order to meet Twilio’s request format, use the url_param_escape Liquid filter on your message contents. This filter encodes a string so all the characters are allowed in an HTML request; for example, the plus character (+) in the phone number +12125551212 is forbidden in URL-encoded data, and will be converted to %2B12125551212.

Webhook Body

Request Headers and Method

Twilio requires two request headers, the request Content-Type and an HTTP Basic Authentication header. Add them to your webhook by clicking the gear icon on the right side of the webhook composer, then clicking Add New Pair twice.

Header Name Header Value
Content-Type application/x-www-form-urlencoded
Authentication Basic {{ 'TWILIO_ACCOUNT_SID:TWILIO_AUTH_TOKEN' | base64_encode }}

Be sure to replace TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN with values from your Twilio dashboard. Lastly, Twilio’s API endpoint is expecting an HTTP POST request, so choose that option in the dropdown for HTTP Method.

Webhook Method

Preview Your Request

Use the webhook composer to preview the request for a random user, or for a user with particular credentials, to ensure that the request is rendering properly.

Webhook Preview

Lob is an online service which one can interact with through their API to send letters, postcards, and checks through the mail. You can access Lob’s services through Appboy’s webhook feature and send mail to your users. To get started, sign up for an account on and locate your API key in the settings section under your name in the dashboard.

Lob API Key


The HTTP URL to request in the webhook is different for each action you can make to Lob. In this example we will be sending a postcard so the url is, however the list of all the HTTP URL endpoints can be found in the Lob documentation.

Lob Endpoints

Request Body

To specify an address in the webhook body requires nested objects, and as such it must be entered as “Raw Text” in JSON format. If you are unfamiliar with the JSON format, an easy way to generate a sample request body is to copy the example CURL requests given on the documentation and run it in your terminal (replacing their test API key with yours). Once you run the code in terminal, go to the dashboard and check the “Logs” tab found under the “Requests” title. If the API request worked, you will be able to click on the request and copy the request body into the dashboard. You can then replace the data in the file to fit your desires.

Lob Success Response

Request Headers and Method

Lob’s documentation states that you must include your API key in the header to authorize the request. To do so, simply navigate to the setting section and add a new pair. For an authentication header, set the key to “Authorization”. Lob expects your API key to be base64 encoded, so use the Base64 filter in the header value: Basic APIkey:. You will need to add a “:” to the end of your API key when encoding as Lob expects the password to be left blank. Because the body of the request is in JSON format, you will also need to add a “Content-Type” key with the value “application/json”. The request method for this webhook is POST as specified on Lob’s documentation.

Lob Preview

Preview Your Request

At this point your campaign should be ready to send. If you run into errors, check the Lob dashboard and the developer console error message logs found in the Appboy dashboard. Using these two resources you should be able to troubleshoot and debug your request. For example, the error below is caused by an incorrectly formatted authentication header.

Error Log Message

Facebook Messenger

Facebook Messenger is one of the world’s most popular instant messaging platforms, used by nearly one billion monthly active users. Our Webhook interface helps you message your users on Facebook Messenger using the Messenger Platform APIs while taking full advantage of Appboy’s advanced segmentation, personalization and triggering features. For your convenience, a Facebook Messenger webhook template is included on the dashboard.

In order to send messages, you’ll need a Facebook Messenger Page and App. We’ll assume you already have the requisites set up. If you need to do this, please see Facebook’s Messenger Platform Product Overview for help getting started. Appboy also offers a full tutorial for creating a Messenger bot with example code in a GitHub repository!

Before starting, please note that Facebook does not allow usage of the Messenger Platform to send marketing messages. The platform is intended for “non-promotional messages that facilitate a pre-existing transaction, provide other customer support actions, or deliver content requested by a person.” To read more, see Facebook’s Platform Guidelines and Examples of Acceptable Use Cases. In addition, to send messages to users who are not test users of your Facebook App, your App will need to pass Facebook’s App Review.

Messenger IDs

In order to send messages on Facebook Messenger, you need to collect your users’ page-specific IDs (PSIDs). PSIDs are not the same as the user’s Facebook ID, and you’ll need the user’s explicit permission for messages from your page. To use PSIDs to send messages, embed a Send to Messenger or Message Us button in your web page or app and send the user’s PSID to Appboy as a string custom attribute. You will also gain access to the user’s PSID in the back end if the user messages your page.

Facebook also supports the use of phone numbers to send messages on Messenger. Note that you’ll need to request the pages_messaging_phone_number permission separately in your App Review to use this feature. Additionally, all phone numbers need to be verified with Facebook by the user in order to receive messages on Messenger.

Setting up the Messenger Webhook

Every HTTP POST request to the Messenger Platform Send API needs to be accompanied by a page access token. If you don’t yet have one, please see Facebook’s documentation on obtaining one. Below is an example of the webhook settings, make sure to replace <ACCESS_TOKEN> with your access token. Also change the Request Body from key/value pairs to raw text to support multi-level JSON.

FBM webhook

You also need to set the Content-Type header to application/json in the webhook settings within Appboy. To do this, click on the gear icon in the webhook configuration and add a key/value pair like this:

FBM Webhook headers

Formatting the Message

All requests to the Send API are sent in JSON according to a pre-specified format. The below examples are not exhaustive of all formats Facebook supports. Please see the Send API reference and its subsections for JSON definitions of all available message types and templates.

You can also use personalization and Connected Content in your webhook campaigns.

Text Messages

In order to send a text message to a user, use the following template, replacing the text with whatever message you wish to send:

    "text":"Hi {{${first_name} | default: 'there'}}! This is an example Facebook Messenger message."

This message appears in Messenger as follows:

Example FBM text message

Media Messages

You can also use Facebook Messenger to send media such as images (including GIFs), videos, audio and files. You’ll need to host this media in a publicly accessible location where it can be accessed by URL, typically your web site. Just replace <YOUR_URL> in the template with the URL to your file and set type as image, audio, video or file depending on the content type you want to send:


This is a sample image message in Messenger:

Example FBM image message

Structured Messages and Templates

In addition to text and files, Facebook Messenger can be used to send structured messages containing buttons or content previews as well as templates like receipts. See the Send API reference for thorough descriptions of the JSON for all available templates as well as character limits and other limitations for copy.

The below webhook body will send a scrollable preview of a few articles in the Appboy blog:

          "payload": {
              "elements": [
                      "title": "The Rise and Rise of Emoji Marketing",
                      "subtitle":"Brands sent 800 million messages with emojis in June",
                            "title":"Read More"
                      "title": "What Emojis Really Mean to a Mobile Marketer",
                      "subtitle":"An infoposter to remember World Emoji Day",
                            "title":"Read More"

This is the sample message in Messenger:

Example FBM structured message

Previewing and Testing Your Webhook

Before you send your message, test your webhook. Make sure your Messenger ID is saved in Appboy (or find it and test as a Customized User), and use the preview to send the test message:

Sending a message to yourself

If you receive the message successfully, you can continue on to configure its delivery settings.

Targeting Facebook Messenger Users

If you are not sending messages using users’ phone numbers and plan on sending Messenger messages repeatedly, you should create a segment for all users for whom the Messenger ID exists as a custom attribute and turn on Analytics Tracking to track your Messenger subscription rates over time. If you choose not to create a specific segment for Messenger subscribers, make sure to include a filter for Messenger ID existing to avoid errors:

Segment filter for Messenger IDs

You may also use other segmentation to target your Messenger campaigns, and the rest of the campaign creation process is as with any other campaign.

Connected Content

Appboy’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 Appboy can hit a web server to pull content to be included in a message using the {% connected_content %} tag. The connected_content tag simply gets the content at that web address and directly inserts it. For example, this message body will hit the url and include a fun trivia fact in your message:

Hi there, here is fun some trivia for you!: {% connected_content %}

You can also include attribute variables in the URL string to allow Appboy to hit your web service with the right parameters. As an example, you may have a web service that returns content based on a user’s attributes. 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. See an example of this in the e-mail address attribute below.

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

{% connected_content{{${email_address} | url_param_escape}}&user_id={{${user_id}}} %}

If the URL cannot be reached, Appboy will render an empty string in its place. Because Appboy 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. If you are using a public API, be sure that your usage will not violate any rate-limiting that the API provider may employ. Appboy 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. Appboy only allows URLs that communicate over port 80 (HTTP) and 443 (HTTPS).

Note: Attribute values must be surrounded by ${} in order to operate properly within Appboy’s version of Liquid Syntax. Note: Connected Content calls do not follow redirects.

Using Basic Authentication

If the URL requires basic authentication, Appboy 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 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 in your API calls by referencing the token’s name:

Hi there, here is fun some trivia for you!: {% connected_content :basic_auth credential_name %}

Local Connected Content Variables

Appboy 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.

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:

{% connected_content :save localweather %}

Note: 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. Rest assured however, that if the request is identical, Appboy will use a cached value rather than making a second request to the server.

JSON Parsing

Connected Content also allows you to parse through any JSON object you save as a local variable. For example, let’s imagine you save the following JSON object as a local variable called localweather.

"weather":[{"id":804,"main":"rain","description":"overcast clouds","icon":"04n"}],

You could see whether or not it was raining by referencing {{[0].main}} which if used on the above object would return rain. 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!

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, Appboy will set both the Content-Type and Accept header to the type you specify.

{% connected_content :content_type application/json %}

Connected Content Syntax Example

If the API responded as before with {{[0].main}} returning ‘rain’, the user would then receive this push.

Connected Content Push Example

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 :save connected %}
{% if connected.__http_status_code__ != 200 %}
  {% abort_message('Connected Content returned a non-200 status code') %}
{% endif %}

Note: 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 a given endpoint 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 :cache 900 %}

Aborting Messages

Using Liquid templating, you have the option of aborting messages within conditionals. For example:

{% connected_content :save connected %}
   {% if connected.recommendations.size < 5 or == nil %}
     {% abort_message() %}
   {% endif %}

You can also have the abort_message log something to your Developer’s Console log:

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

Transifex Integration

If you have a Transifex account, you can use Appboy’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<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.


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


Standard Transifex Integration Code

If you do not set the context on your translations, you can use code that’s similar to the below code in your message composer. This example supports translations for French, German and Italian:

{% assign source_string = "<Put translation key here>" %}

{% assign resource = "<resource_name>" %}
{% assign project = "<project_name>" %}

{% capture key %}
{% endcapture %}
{% assign md5_hash = key | md5 %}

{% if {{${language}}} == "fr" or {{${language}}} == "it" or {{${language}}} == "de"  %}
  {% connected_content{{project}}/resource/{{resource}}/translation/{{${language}}}/string/{{md5_hash}}/ :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}
{% else %}
  {% connected_content{{project}}/resource/{{resource}}/translation/<default_language>/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringsone %}
  {% if {{stringsone}} != null and {{stringsone.translation}} != "" %}
  {% else %}
    {% abort_message('null or blank english') %}
  {% endif %}
{% endif %}  

Transifex Integration Code Explanation

Variable Assignment

This portion of the code assigns your key, resource name, and project name as variables to be used in the Connected Content call:

{% assign source_string = "<Put translation key here>" %}

{% assign resource = "<resource_name>" %}
{% assign project = "<project_name>" %}

{% capture key %}
{% endcapture %}
{% assign md5_hash = key | md5 %}

Integration When Setting Both Key and Context

If you are setting both the key and the context you should add the following line of code after

{% assign project = "<project_name>" %}:

{% assign context = "<context_name>" %}

You should also replace {{source_string}}: with {{source_string}}:{{context}}.

Defining Your Translation Languages

In the next portion of the code you should list of all the languages that have translations in your Transifex account. This example is for an account with French, Italian and German translations.

Additionally, in this example the default language is English:

{% if {{${language}}} == "fr" or {{${language}}} == "it" or {{${language}}} == "de"  %}
  {% connected_content{{project}}/resource/{{resource}}/translation/{{${language}}}/string/{{md5_hash}}/ :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}

Abort Message Clause

This portion of the code provides the Connected Content call that will be made when the user’s language either does not exist or does not match any of the translations that you have in your Transifex account:

{% else %}
  {% connected_content{{project}}/resource/{{resource}}/translation/<default_language>/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringsone %}
  {% if {{stringsone}} != null and {{stringsone.translation}} != "" %}
  {% else %}
    {% abort_message('null or blank english') %}
  {% endif %}
{% endif %}

Using Most Recent Locale

If you have language translations based on most recent locale, you should use code that is similar to the following code. This example supports translations for traditional Chinese, Simplified Chinese and Brazilian Portuguese:

{% if {{${language}}} == "zh" and {{${most_recent_locale}}} != "zh_CN" %}
  {% connected_content{{project}}/resource/{{resource}}/translation/zh_TW/string/{{md5_hash}}/  :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}
{% elsif {{${most_recent_locale}}} == "zh_CN" and {{${language}}} == "zh" %}
    {% connected_content{{project}}/resource/{{resource}}/translation/{{${most_recent_locale}}}/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringslocal %}
    {% if {{stringslocal}} != null and {{stringlocal.translation}} != "" %}
    {% else %}
      {% abort_message('null or blank') %}
    {% endif %}
{% elsif {{${most_recent_locale}}} == "pt_BR" and {{${language}}} == "pt" %}
    {% connected_content{{project}}/resource/{{resource}}/translation/{{${most_recent_locale}}}/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringslocal %}
    {% if {{stringslocal}} != null and {{stringlocal.translation}} != "" %}
    {% else %}
      {% abort_message('null or blank') %}
    {% endif %}
{% elsif {{${language}}} == "fr" or {{${language}}} == "it" or {{${language}}} == "de" or {{${language}}} == "es" or {{${language}}} == "tr" or {{${language}}} == "ru" or {{${language}}} == "ja" or {{${language}}} == "ko" or {{${language}}} == "ms" or {{${language}}} == "vi" or {{${language}}} == "tl" or {{${language}}} == "id" or {{${language}}} == "en" %}
  {% connected_content{{project}}/resource/{{resource}}/translation/{{${language}}}/string/{{md5_hash}}/ :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}
{% else %}
  {% connected_content{{project}}/resource/{{resource}}/translation/en/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringsone %}
  {% if {{stringsone}} != null and {{stringsone.translation}} != "" %}
  {% else %}
    {% abort_message('null or blank english') %}
  {% endif %}
{% endif %}

Most Recent Locale Explanation

Assigning variables

{% assign source_string = "Put translation key here" %}

{% assign resource = "resource_name" %}
{% assign project = "project_name" %}

{% capture key %}
{% endcapture %}
{% assign md5_hash = key | md5 %}

Checking for Most Recent Locales

In this line we check to see if a user’s language is Chinese. If a user’s language is Chinese and their most recent locale is not zh_CN we send them a message in Traditional Chinese:

{% if {{${language}}} == "zh" and {{${most_recent_locale}}} != "zh_CN" %}
  {% connected_content{{project}}/resource/{{resource}}/translation/zh_TW/string/{{md5_hash}}/  :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}

In this line, we check to see if the user’s language is Chinese and if their most recent locale is zh_CN. If these conditions are met, we send the Simplified Chinese translation:

{% elsif {{${most_recent_locale}}} == "zh_CN" and {{${language}}} == "zh" %}
    {% connected_content{{project}}/resource/{{resource}}/translation/{{${most_recent_locale}}}/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringslocal %}
    {% if {{stringslocal}} != null and {{stringlocal.translation}} != "" %}
    {% else %}
      {% abort_message('null or blank') %}
    {% endif %}

In this line, we check to see if the user’s language is Portuguese and if their most recent locale is pt_BR. If these conditions are met, we send the Brazilian Portuguese translation:

{% elsif {{${most_recent_locale}}} == "pt_BR" and {{${language}}} == "pt" %}
    {% connected_content{{project}}/resource/{{resource}}/translation/{{${most_recent_locale}}}/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringslocal %}
    {% if {{stringslocal}} != null and {{stringlocal.translation}} != "" %}
    {% else %}
      {% abort_message('null or blank') %}
    {% endif %}

Defining your Translation Languages

If none of the above conditions are met, we check to see if the user’s language matches one of the translations in your transifex account:

{% elsif {{${language}}} == "fr" or {{${language}}} == "it" or {{${language}}} == "de" or {{${language}}} == "es" or {{${language}}} == "tr" or {{${language}}} == "ru" or {{${language}}} == "ja" or {{${language}}} == "ko" or {{${language}}} == "ms" or {{${language}}} == "vi" or {{${language}}} == "tl" or {{${language}}} == "id" or {{${language}}} == "en" %}
  {% connected_content{{project}}/resource/{{resource}}/translation/{{${language}}}/string/{{md5_hash}}/ :basic_auth <credential_name> :save strings %}
  {% if {{strings}} != null and {{strings.translation}} != "" and {{${language}}} != null %}
  {% else %}
    {% abort_message('null or blank') %}
  {% endif %}
{% endif %}  

Abort Message Clause

This portion of the code provides the Connected Content call that will be made when the user’s language either does not exist or does not match any of the translations that you have in your transifex account.

{% else %}
  {% connected_content{{project}}/resource/{{resource}}/translation/en/string/{{md5_hash}}/  :basic_auth <credential_name> :save stringsone %}
  {% if {{stringsone}} != null and {{stringsone.translation}} != "" %}
  {% else %}
    {% abort_message('null or blank english') %}
  {% endif %}
{% endif %}

Appboy or third parties may make available certain third party products or services to our customers that interoperate with the Appboy 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. Appboy 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 Appboy in connection with the interoperation of the Appboy Services with such third party services. Appboy is not responsible for any disclosure, modification or deletion of any customer data by such third party providers, and Appboy 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 Appboy Services, customers shall not be entitled to any refund, credit or other compensation from Appboy.

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!

Note: 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


API Description 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.
Bands in Town 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.


API Description
Yahoo Finance Provides a variety of stock data.
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.

Utilizing Badge Count

The iOS badge count displays the number of unread notifications within your application, taking the form of a red circle in the upper-right hand corner of the app icon. In recent years, badging has come to be one of the most effective means for re-engaging app users.

The badge count can be used to re-engage your users who either forgot to check or did not receive push notifications. Similarly, it can be used to notify your users about unviewed messages such as news feed changes or in-app updates.

Best Practices

In order to optimize the re-engagement power of badging, it is crucial that you configure your badge settings in a way that most simplifies the user’s experience.

Keep the Badge Count Low

Research shows that once the badge count increases past double digits, users generally lose interest in the updates and often stop using the app altogether.

Note: There can be exceptions to this rule depending on the nature of your app (e.g. email and group messaging apps).

Limit the Things a Badge Count Can Represent

When badging, you want to make the notifications as clear and direct as possible. By limiting the number of things that a badge notification can represent, you can provide your users with a sense of familiarity with your app’s features and updates.

News Feed and In-app Badging

One of the most powerful features of badging is that it allows you to engage with your users without the immediacy of a push notification through the news feed and in-app updates. To ensure that your users stay interested in the in-app badging notifications, you should try to focus such badge updates on personalized or urgent messages.

Badge Count with Appboy

After integrating the Appboy SDK, you will need to manually configure your badge settings. It is common practice to update the badge count at the end of the session’s lifecycle so that it is accurately reflected when the user closes the app.

Removing the Badge Count

You can disable the badge count for push notifications on your app altogether by manually configuring your App Settings page on the Manage App Group tab as shown below.

Disabling Count

Note: This is not recommended.

News Feed Categories

News Feed “Categories” make it possible to integrate multiple instances of the news feed into your application. It’s possible to integrate feeds within different windows that only display news feed cards of a certain “category.”

News Feed Categories Image

Marking a News Feed as being from a specific “category” is not visible to the end user. By default, the Appboy News Feed will display cards of all categories, unless a feed is specifically configured in the app code to display specific categories. For more information on the app code configuration, please see our technical documentation on the matter.

Responding to Feedback

Listening to User Feedback is important. It can alert you of a technical issue in your app or design flaws that you might not have considered. Most importantly though, it gives your users a way to reach out easily and directly to your app. If they have a criticism or face a technical issue, you need to make sure they come to you with that issue rather than dragging your name through the mud in the App Store, Google Play etc.

Step 1: Managing Feedback

Feedback is organized within the dashboard by “Issues” and “Feedback.” The latter are generic requests that may be critical or contain praise, while the former denote technical issues that require your immediate attention. You also may notice that you can keep multiple feedback tabs open at a time in order to efficiently manage your tickets.


Step 2: Responding to Feedback

First, notice that you get the entire user card to the right of the feedback ticket. This enables you to see if this user has had frequent technical problems by clicking on the Feedback section while quickly gathering technical information from the user to promptly diagnose and fix bugs.

Responding to Feedback is as simple as typing a response in the text field, selecting one or two message types, and sending it off to the user.

In most cases, we recommend that you respond to the user via email, although reacting to positive Feedback via Twitter is often a great way to get free publicity. They might re-tweet you!


Additionally, you have the ability to create canned responses. Simply navigate to a piece of feedback and select the “Canned Responses” button. From there, you can create a new canned response, or choose from existing ones.


Step 3: Following Up with All Users

In many cases, you might notice that a certain action or user behavior is causing a bug. Going back and segmenting users who might be experiencing similar issues can ensure that more than the small subset of users who actually take the time to complain feel truly supported.

Step 4: Setting Notifications

To help you stay abreast of feedback as it comes in, Appboy can send notifications via email when new feedback arrives. To receive email notifications for new feedback, navigate to the Manage App Group page under App Settings in the dashboard. In the tab [Email Settings][email settings], you can enter an address for notifications to be sent for new feedback and replies from users. You can also change your outbound email settings for feedback responses sent through Appboy.

Email Settings

Managing User Subscriptions

Subscription States

Appboy has three subscription tiers for e-mail users:

State Definition
Opted-in User has explicitly confirmed he/she wants to receive e-mail. We recommend an explicit opt-in process to acquire consent from users to send e-mail.
Subscribed User has neither unsubscribed, nor explicitly opted-in to receive e-mails. A user automatically gets set as Subscribed when a valid e-mail address is added to their user profile.
Unsubscribed User has either explicitly unsubscribed from your e-mails or been automatically unsubscribed after marked one of your e-mails as spam.

Changing Subscriptions

Changing Email Subscriptions

In most cases, your users will manage their email subscription through subscription links that are included in the emails they receive.

Appboy automatically inserts a footer with an unsubscribe link at the bottom of every email you send, in accordance with the CAN-SPAM Act of 2003. When users click on the unsubscribe url in this footer, they are unsubscribed and taken to a landing page that confirms the change to their subscription.

Appboy provides the ability to set an app group wide custom email footer which you can template into every email using the {{${email_footer}}} attribute. In this way, you do not have to create a new footer for every email template or email campaign you use. Changes you make to your custom footer will be reflected in every email campaign that starts after the changes are saved. Remember that compliance with the CAN-SPAM Act of 2003 requires you to include a physical address for your company and an unsubscribe link in your emails. It is your responsibility to make sure that your custom footer meets those requirements.

To create or edit your custom footer, go to the Manage App Group page under App Settings, and select the Email Settings tab.

Email Settings In the Custom Footer section, you can choose to turn on Custom Footers. Once turned on, you will see a window to edit your footer and send a test message.

Custom Footer You will see the default footer which uses the {{${set_user_to_unsubscribed_url}}} attribute and Appboy’s physical mailing address. To comply with CAN-SPAM regulations, your custom footer must include {{${set_user_to_unsubscribed_url}}}; you will not be able to save a custom footer without {{${set_user_to_unsubscribed_url}}}.

If using the default footer which uses the {{${set_user_to_unsubscribed_url}}} attribute, be sure to select “other” for the Protocol as indicated below.

Default Unsub URL Protocol

No Footer-Email Settings Note: be very careful to use a template with the custom footer {{${email_footer}}} or {{${set_user_to_unsubscribed_url}}}when composing an email campaign. A warning will pop-up, however the ultimate decision of whether to send an email without an unsubscribe link lies with you.

No Footer-Campaign Composition When creating a custom footer, Appboy suggests you use attributes for personalization. Here are a few you may find useful:

Attribute Tag
User’s Email Address {{${email_address}}}
User’s Custom Unsubscribe URL {{${set_user_to_unsubscribed_url}}}
User’s Custom Opt-In URL {{${set_user_to_opted_in_url}}}
User’s Custom Subscribe URL {{${set_user_to_subscribed_url}}}

Of course, the full set of default and custom attributes are available to you. As a best practice, Appboy recommends including both an unsubscribe link (i.e. {{${set_user_to_unsubscribed_url}}}) and an opt-in link (i.e. {{${set_user_to_opted_in_url}}}) in your custom footer. This way users will be able to both unsubscribe or opt-in and you can passively collect opt-in data for a portion of your users.

You can also choose to set a custom footer for plaintext emails, which follows the same rules as the custom footer for HTML emails. If you choose not to write a plaintext footer, Appboy will automatically build one from the HTML footer. When your custom footers are to your liking, press Save at the bottom of the page.

Save Custom Footer

Custom Unsubscribe Landing Page

When a user clicks on an unsubscribe url in an email, they are taken to a default landing page that confirms the change to their subscription.

Optionally, you may provide HTML for your own custom landing page, which users will be directed to (instead of the default page) upon unsubscribing. This feature is available on the “App Settings - Email” page. We recommend including a resubscribe link (i.e. {{${set_user_to_subscribed_url}}} ) on this page so that users have the option to resubscribe in case they unsubscribed by accident.

Custom ReSubscribe

Changing Push Subscriptions

Appboy’s Mobile SDKs provide methods for changing a user’s push message subscription. Please refer to Appboy’s technical documentation for your mobile platform for information on configuring these methods:

Manually Changing User Subscriptions

You can manually change the subscription status for any user in his/her individual user profile. You can find individual user profiles by searching for a user’s ID or email address on the “User Search” page. Under the user profile’s “Engagement” tab, you’ll find a user’s current push and email subscription status. Clicking on the “Unsubscribed”, “Subscribed”, or “Opted In” buttons will allow you to change that user’s subscription status. If available, the user profile also displays a timestamp for when the user’s subscription was last changed.

User Profile Subscription UI

Subscriptions and Campaign Targeting

Campaigns with push or email messages are targeted at users who are subscribed or opted-in by default. You can change this targeting preference when editing a campaign by going to the “Target Users” step and clicking “Advanced Options.”

Appboy supports three targeting states:

  • Users who are subscribed or opted-in (default).
  • Only users who are opted-in.
  • All users, including those who have unsubscribed.

Please note that it is your responsibility to comply with any applicable spam laws when using these targeting settings.

Campaign Targeting Subscription UI

Segmenting by User Subscriptions

The “Email Subscription Status” and “Push Subscription Status” filters allow you to segment your users by their subscription status.

This can be useful - for example, if you want to target users who have neither opted in nor out and encourage them to explicitly opt-in to email or push. In that case, you would create a segment with a filter for “Email/Push Subscription Status is Subscribed” and campaigns to this segment will go to users who are subscribed but not opted in.

Subscription Filter

Sending Test Messages

Before sending out a messaging campaign to your users, you may want to test it to make sure it looks right and operates in the intended manner. Creating and sending test messages to select devices or members of your team is very simple using the tools in the dashboard.

Sending a Test Mobile Push Notification or Email Message

After drafting your Push or Email, you have the ability to send the message to your own device to see what it looks like in real time. In the settings bar, click the “eye” icon, input your email address or userID, and click “Send Test.” This will send the message that you drafted to your device.

This is what the testing process will look like for a push message.

Test Push

And here is what the process will look like for an email message.

Test Email

Keep in mind that you will either need your users’ email address or Appboy UserID to send test messages to your device.

Sending a Test Web Push Notification

After drafting your web push, you have the ability to send the message to your computer to see what it looks like in real time. In the settings bar, click the “eye” icon, and click “Send Test to Myself.”

Test Web Push

If you have already accepted push messages from the Appboy Dashboard, you will see the push come through in the corner of your screen. Otherwise, please click “Allow” when prompted, and the message will then appear.

Accept Web Push

Sending a Test In-App Message

If you have push notifications set up within your app and on your test device, you have the ability to send test in-app messages to your app to see what it looks like in real time. In the settings bar, click the “eye” icon, input your email address or userID, and click “Send Test:”

Test In App

This will send a push message to your device like the following:

Test Push for In App

Directly clicking and opening the push message will send you to your app where you’ll be able to view your in-app message test.

Sending a Test News Feed Card

Sending a test newsfeed card requires you to set up a test segment and subsequently send a test campaign out.

Creating a Designated Test Segment

Once you set up a test segment, you can utilize it these messaging channels. The process is very simple and if configured properly will only need to be done once.

Navigate to the “Segments” page in the dashboard and create a new segment. In the dropdown menu under “Add Filter”, you’ll find our testing filters at the bottom of the list.

Testing Filters

Our testing filters allow you to select users with specific email addresses or external user IDs.

Testing Filter Options

These filters have three options:

  1. “Equals” - This will look for an exact match of the email or user ID that you provide. Use this if you only want to send the test campaigns to devices associated with a single email or user ID.
  2. “Does Not Equal” - Use this if you want to exclude a particular email or user ID from test campaigns.
  3. “Matches” - This will find users that have email addresses or user IDs that match part of the search term you provide. You could use this to find only the users that have an “” address, allowing you to send messages to everyone on your team.

These filters can also be used in conjunction with each other to narrow down your list of test users. For example, the test segment could include an email address filter that matches “” and another filter that does not equal “”. You can also select multiple specific emails by using the matches option and separating the email addresses with a “|” character (e.g. matches “|”).

After adding the testing filters to your test segment, you can verify that you’ve selected only the users you intended by clicking “Preview” at the top of the segment editor or by exporting that segment’s user data to CSV by clicking on the gear icon in the right hand corner of the editor and selecting “CSV Export All User Data” from the dropdown menu.

Verify Test Segment

Note: Exporting the segment’s User Data to CSV will give you the most accurate picture of who falls under that segment. The “Preview” tab is only a sample of the users in the segment - see more details about this in our FAQ - and therefore may appear to have not selected all intended members.

Once you’ve confirmed that you’re only targeting the users that you want to receive the test message, you can either select this segment in an existing campaign that you want to test or click the “Start Campaign” button in the segment menu.

Sending the Test Campaign

In order to send test newsfeed cards, you need to target your previously created test segment. Begin by creating a Multichannel campaign and following the usual steps. When you reach the ‘Target Users’ section, select your test segment as shown below.

Test Segment

Finish confirming your campaign and launch it to test your newsfeed cards.

Note: Be sure to check the box titled “Allow users to become re-eligible to receive campaign” under the Schedule portion of the campaign wizard if you intend to use a single campaign to send a test message to yourself more than once.

Sending a Test Campaign Personalized with User Attributes

If you are using personalization in your message, you’ll need to take some additional steps to properly preview your campaign and check that user data is properly populating the content.

When sending a test message, make sure to choose either the option to “select a user” or preview as a “customized user.”

Testing a personlized message

If selecting a user, you’ll be able to enter the user ID or email of a specific app user into a search field. Then you’ll be able to use the dashboard preview to see how that user’s message would appear, and send a test message to your device that reflects that that user would see.

Select a user

If previewing as a customized user, you’ll be able to enter in text for various fields available for personalization, such as first name and any custom attributes. Once again, you can enter your own email address to send a test to your device.

Custom user

Sending a Test Campaign Personalized with Custom Event Properties

Testing campaigns personalized with Custom Event Properties differs slightly from testing other types of campaigns outlined above. The most robust way to test campaigns personalized using Custom Event Properties is to trigger the campaign yourself. Begin by writing up the copy involving the event property:

Composing Test Message with Properties

Then use Action Based Delivery to deliver the campaign when the event occurs. Note that if you’re testing an iOS Push campaign, you must set the delay to 1 minute to allow yourself time to exit the app, since iOS doesn’t deliver push notifications for the currently open app. Other types of campaigns can be set to deliver immediately.

Test Message Delivery

As described above, target the users as you would for testing using either a testing filter or simply targeting your own e-mail address and finish creating the campaign.

Test Message Targeting

Go into your app and complete the custom event, and the campaign will trigger, and you should see the message customized with the event property:

Test Message Example

Alternatively, if you are saving custom user IDs, you can also test the campaign by sending a customized test message to yourself. After writing the copy for your campaign, click the eye icon on the upper right corner of the preview, then select “Customized User”. Add the custom event property on the bottom of the page, add your user ID or e-mail address to the top box and click “Send Test”. You should receive a message personalized with the property.

Testing Using Customized User

User Import

Appboy’s User Import feature allows users to upload and update user profiles via CSV files. This feature supports updating default and custom user profile attributes.


Appboy accepts user data in the standard CSV format from files up to 100MB in size. The particulars of how to construct your file are described below.

Column Headers

Appboy expects that the first row in your CSV file will contain the headers for each column in the file. The number of columns in each row must match the number of headers.

Users imported to Appboy via CSV must be identified – Appboy does not support creating entirely anonymous users via User Import. You must specify either an ‘appboy_id’ or an ‘external_id’, but not both, allowing Appboy to match an existing user.

  • If you provide an external_id, we will update any existing user with the same external_id or create a new identified user with that external_id set if one is not found.

  • If you provide an appboy_id, we will update any existing user with the same appboy_id but will not create a new identified user with that appboy_id if one is not found since we do not allow entirely anonymous users via User Import.

All headers will be interpreted as custom attributes unless they match these fields used with the user data REST API:

  • appboy_id
  • external_id
  • first_name
  • last_name
  • email
  • dob
  • country
  • language
  • home_city
  • bio
  • gender
  • phone
  • email_subscribe
  • push_subscribe
  • image_url

Note: all of these fields are of type String except for dob (date of birth). Take care to use the exact spelling and proper case for pre-existing user data fields.


These data types are accepted in User Import:

  • Datetime (Must be stored in the ISO 8601 format)
  • Boolean (TRUE/FALSE)
  • Number (Integer or Float with no spaces or commas, floats must use ‘.’ as the decimal separator)
  • String (no commas)
  • Blank

Note that the following data types are not supported in User Import:

  • Arrays
  • Push Tokens
  • Custom Events

For uploading these kinds of values, please use our User Data API.


Any value which is not formatted to match the Datetime, Boolean, Integer, or Float specifications will be read as a String. Each comma in the input will be interpreted as a column separator, therefore any commas in values will cause errors in parsing the file. In addition, all leading and trailing whitespace will be trimmed from each value. Otherwise, values will be stored exactly as stored in the input CSV file. Blank values will not overwrite existing values on the user profile, and you do not need to include all existing user attributes in your CSV file.

For segmentation, it is important that each column contains a consistent data type. Values which do not match the attribute’s data type will not match the filters used to segment the attribute. In addition, for custom attributes whose data type is set as “Detect Automatically” on the dashboard, the most recently added value is used to set the data type of the attribute, so an error in your last row can interfere with proper segmentation.

During import, Appboy determines the data type of each column by scanning a sample from the top rows of the file. Mixed data types in a column will not prevent you from importing your file, so we recommend exercising caution and ensuring the values in each column are consistent and match the data type you expect.


Import Navigation

To import your CSV file, navigate to the User Import page under the Users section on the left hand toolbar. In the lower text box, “Recent Imports”, there will be a table which lists up to twenty of your most recent imports, their file names, number of lines in the file, number of lines successfully imported, total lines in each file, and the status of each import. User Import

The upper box, “Import CSV”, will contain importing directions and a button to begin your import. Press the “Select CSV File” button and select your file of interest, then press “Start Upload.” Appboy will upload your file and check the column headers as well as the data types of each column. Once the upload is complete, you will see a modal window with a table previewing the contents of your file. All the information in this table is based off of the values in top few rows of your CSV file. For column headers, default attributes will be written in normal text, while custom attributes will be italicized and have their type noted in parentheses. There will also be a short summary of your file at the top of the pop-up. Errorless Import

If Appboy notices something malformed in your file during the upload, errors will be shown above the summary. A file can be imported with errors, but once started, an import cannot be cancelled or rolled-back. Review the preview, and if errors are found cancel the import and modify your file. It is important to examine the full file before upload as well. Appboy does not scan every row of the input file at this stage; errors can exist which Appboy does not catch while generating this preview. Malformed rows and rows lacking an external ID (A) will not be imported, all other errors can be imported (B) but may interfere with filtering when creating a segment. Note that errors are based solely off of data type and file structure - for example, a poorly formatted email address (C) would still be imported as it can still be parsed as a string.

Import Errors

When you are satisfied with the upload, start the import. The pop-up will close and the import will begin in the background. You can track its progress on the User Import page, which will refresh every 5 seconds, or at the press of the refresh button in the Recent Imports box. Under Lines Processed, you will see the progress of the import; the status will change to Complete when finished. You can continue to navigate around other parts of the dashboard during the import, you will receive modal notifications when the import begins and ends.

Import Begins

Import Ends

When the import process runs into an error, a yellow warning icon will be displayed next to the total number of lines in the file. You can mouse over the icon to see details into why certain lines failed. Once the import is Complete, all data will have been added to existing profiles or all new profiles will have been created.

Error Tooltip


User Import creates and updates user profiles, and can also be used to create segments. To create a segment, check the ‘Create a segment from this CSV’ box.

Create a Segment

You can set the name of the segment or accept the default, which is the name of your file. Files which were used to create a segment will have a link to view the segment once the import has completed.

View the Segment

The filter used to create the segment selects users who were created or updated in a selected import, and is available with all other filters in the edit segment page. Note that for each user, only the last 10 CSVs the user was imported/updated in are cached. So if you attempt to create a segment by filtering for members who were in an older import, the segment will not include users who have been in 10 or more imports since.

Edit the Segment

Common Errors

  • No external_id: To connect data from User Import to user profiles, Appboy requires an external_id in each row. Rows without a value in the external_id column will be excluded from the import. User profiles that lack an external_id cannot be created or updated via the User Import.
  • Malformed Row: There must be a header row in order to properly import data. Each row must have the same number of cells as the header row. Rows whose length that have more or fewer values than the header row will be excluded from the import. Commas in a value will be interpreted as a separator and can lead to this error being thrown. Additionally, all data must be UTF-8 encoded.
  • Multiple Data Types: Appboy expects each value in a column to be of the same data type. Values which do not match their atttribute’s data type will cause errors in segmenting.
    • Incorrectly Formatted Dates: Dates not in the ISO 8601 format will not be read as datetimes on import.
    • String Quotation: Values encapsulated in single (‘’) or double (“”) quotation marks will be read as strings on import.

Exporting to Facebook Audiences

Appboy provides Facebook marketing integration, allowing you to export segments as Facebook marketing audiences and target those users for ad campaigns. Here are instructions on setting up this feature.

Setting Up

Configuring Facebook App Settings

In order to export custom audiences from the dashboard, your Facebook app must be configured to allow Appboy to make requests to Facebook on behalf of the members of your team.

  • You need to have a Facebook app that Appboy can use to access the Facebook Marketing API on your behalf. If you already have a Facebook app that you’re using for Facebook sign-in in your app, you can use that or you can create a new one by following the instructions in the Facebook marketing API documentation. You will need to add each of your team members who should be able to export Facebook audiences as developers on whichever app you want to use.
  • Head to the Facebook app dashboard, and make sure to select the app you want Appboy to use for marketing API access.

Facebook Settings 1

  • Before proceeding, make sure to note the app ID and the app secret, as you will need to enter these in the Appboy dashboard.
  • Make sure you have proper permissions to export Facebook audiences. Click “Roles.”
  • Within the roles tab, you should have either administrator or developer permissions. If not, please ask your administrator to give you the proper permissions.

Facebook Settings 2

  • Next, click “Facebook Login” under “Products” in the left hand menu.
    • If you don’t see “Facebook Login” in the menu, add the Facebook Login product by clicking on “Add Product”.

Facebook Settings 3

  • You should see “Valid OAuth redirect URIs” at the bottom of the “Client OAuth Settings” section.
  • Add in this field.
  • Save your changes.
  • Make sure that each of the members of your team who will be exporting audiences to Facebook has accepted the Facebook custom audience terms of service.

Configuring Appboy 3rd Party Integration

  • Once your Facebook app has been correctly configured, you’ll need to add your credentials to the appropriate app group in Appboy. Within the Appboy dashboard, head to the 3rd Party Integrations section, and click on the Facebook tab. Make sure you’ve selected the correct app group.
  • Enter your app ID and app secret in the “Facebook Marketing App ID” and “Facebook Marketing App Secret” fields.
  • The “Facebook App ID” field is optional. If users authenticate with Facebook in your app and you are providing Facebook data to the Appboy SDK, you will have the option to export those users to Facebook using their Facebook User ID. If you’d like to do this, save the Facebook app ID that you use to authenticate your users in the “Facebook App ID” field.

Facebook Settings 4

  • Save your changes.

Exporting Your Users

  • The Facebook audience export link will be in the settings menu of each segment in an app group that has Facebook credentials.
    • While this link will be present for all members of your app group, only users with permissions in your Facebook marketing app will be able to successfully export a segment.

Facebook Export 1

  • When you click on this link, a modal will appear to ask which type of user data to export. Unfortunately, Facebook only allows exporting by 1 data type per custom audience. If you choose more than 1 type, Appboy will create a separate custom audience for each.
    • There are 4 possible user data types we can use for the export: email, device IDFA, Facebook UID, and phone number. If you haven’t entered a Facebook app ID in your 3rd Party Integration settings, you won’t be able to select Facebook UID.

Facebook Export 2

  • Click on export. As with CSV exports, you will receive an email when the segment has finished exporting.
  • You can view the custom audience on the Facebook Ad Manager.
    • Due to Facebook privacy restrictions, you cannot see the users or the exact size of the audience. Facebook provides an estimate of your custom audience size.

Facebook Export 3

Lookalike Audiences

Once you’ve successfully exported a segment as a Facebook Audience, you can create additional groups using Facebook’s Lookalike Audiences. This feature looks at demographics, interests, and other attributes of your chosen audience and creates a new audience of people with similar attributes.


Appboy tracks some author, editor, date, and status information about segments, campaigns, and news feed cards, and gives you the ability to create tags to further organize and sort your engagement.

Campaign, Segment, and News Feed Card Tags

You can add tags when creating or editing a campaign, segment, or news feed card. Click the Add Tag button below the engagement name and add an existing tag or write in a new tag.

Campaign Creation

Segment Creation

The tags set on a campaign, segment, or news feed card are visible on the detail page below the engagement name.

Campaign Details

Segment Details

They are also visible in the list of campaigns, segments, and news feed cards, as bubbles above the engagement name, along with status labels such as Archived and Draft.


To filter by a tag, select the tag name in the left-hand toolbar or search for the tag in the search pane using the tag selector

Tag Search for Campaigns and Segments

Best Practices

Tags can be a useful organizational tool for keeping track of engagement tactics. You can link segments, campaigns, and news feed cards to business objectives, funnel stages, and the like.

Below is an example of tags an eCommerce app might find useful:

Potential Tags

You can use the same tags across segments, campaigns, and news feed cards. To efficiently rename or remove tags across your dashboard, use the Tags tab in the Manage App Group page.

Tag Management

Advanced Search Functionality

Our dashboard allows you to search through your segments, campaigns, and news feed cards using various advanced search filters. This feature is intended to help you locate your specific campaign or segment even faster and is useful to help parse through dozens of campaigns and segments that you may have.

To access this feature, you simply click on the dropdown arrow to the right of the search box on the campaign, segments, or news feed page:

Search Dropdown

Segment Search Filters

For segments, you will be able to search by the below filters:

  • Last Edited By
  • Search by Date of when a segment was created or last edited

Segments Search

Campaign Search Filters

For campaigns, you will be able to search by the below filters:

  • Last Edited By
  • Target Segment
  • Messaging Channel
  • Search by Date of when a campaign was created, last edited, or last sent

Campaigns Search

News Feed Search Filters

For news feed cards, you will be able to search by the below filters:

  • Last Edited By
  • Target Segment
  • Search by Date of when a card was created or last edited

News Feed Card Search


The Appboy Canvas is a powerful solution for visualizing how campaigns connect to shape a customer’s journey. Canvas provides a single unified interface where marketers can set up multiple multiple messaging paths, compare and optimize those experiences, and view comprehensive analytics for the full user experience.

Canvas is only available to customers on annual contracts. If you are not on contract, please [link 02][reach out] to learn how to get Canvas.

Getting Started With Canvas

Marketing is a science—but one that needs an artist’s touch and specialized tools. Within Canvas, you can mix rigor and artistry to create meaningful, relevant, and personal experiences for each customer. Canvas is a single unified interface where marketers can set up campaigns with multiple messages and steps to form a cohesive journey and then compare and optimize those experiences using comprehensive analytics for the full user experience.

This guide will walk you through setting up a Canvas and give you important questions and thought starters as you build and consider your customer experiences.

Canvas: The Basics

Find your strategy with the Five W’s of visualization

Fill in the form here to get started:

  • What am I trying to help the customer do or understand?_________ (Canvas Name)

  • When will a user start this experience? Pick one.

    • Enter users at a designated time: Scheduled

      • Immediately
      • Regularly (daily, weekly, monthly)
      • Later, at a defined date.
    • Enter user when they perform actions: Action-Based

      • Make purchase
      • Start a session
      • Perform a custom event # Enter a location # Interact with or leave another campaign or Canvas
  • Who are we trying to reach? _________ (Segment Name) with [optional] additional filters:

    • Custom Data
    • User Activity
    • Retargeting
    • Marketing Activity
    • User Attributes
    • Install Attribution
    • Social Activity
  • Why am I creating this canvas?

    • Start Session: I want them coming back and engaging with the app.
    • Make Purchase: I want them to buy.
    • Perform Custom Event: I want them to perform a specific action that I’m tracking as a custom event.
  • Where will we reach them?

    • Push (Android, iOS, Windows, web)
    • Email
    • Webhook
  • How will we reach them? (Great place to test different messaging configurations)

    • Timing: Schedule or trigger messages using tools like Intelligent Delivery and delays after trigger events
    • Cadence & Channel: Use one channel and then another or sent messages on multiple channels simultaneously
    • Content: Build creative with strong appeals, value propositions, and CTAs
    • Targeting: Add additional segments and/or filters
    • Triggers: Use customer actions to trigger messages

Anatomy of Canvas

Journey Canvas refers to the workspace and overall visualization.

Journey_2 A journey or customer journey is an individual user’s experience within the Canvas.

Journey_3 Variants are the variant flows marketers build that create personalized journeys.

Journey_4 Steps are individual decision points (like messages) within a variant.

Building The Customer Journey In Canvas

Name Your Canvas: the “what”

Never underestimate the power of the name. Appboy is built for collaboration so this is a good time to get grounded in how you’ll communicate goals with your team. You can add Tags (including Teams Tags) and name both steps and variants within the Canvas.

Create Starting Conditions: the “when”

When will a customer run into this Canvas? Users can enter your Canvas in two ways: scheduled or action-based triggers.


You can use scheduled delivery when you want to send a Canvas out immediately to your target audience, have it regularly sent, or schedule it for a specific time in the future.


These Canvas respond to specific customer behaviors as they happen. These action-based triggers can include opening your app, making a purchase, interacting with another campaign, or triggering any custom event.

Select an Entry Audience for Entry: the “who”

Who are you trying to reach? Here you can use a pre-defined segment and add further filters. Filters include:

  • Custom Data: Custom data filters allow you to segment users based on events and attributes you define. With them, you can use features specific to your product.
  • User Activity: User activity filters allow you to segment customers based on their actions and purchases.
  • Retargeting: Retargeting filters allow you to segment customers who have been sent, received, or interacted with previous Campaigns or Canvases.
  • Marketing Activity: Marketing filters segment customers based on universal behaviors like last engagement or received campaigns.
  • User Attributes: User attribute filters segment customers by their constant attributes and characteristics.
  • Install Attribution: Install attribution filters segment customers by their first source, adgroup, campaign, or ad.
  • Social Activity: Social activity filters segment customers by their social media activity namely through connection to Facebook and Twitter.

Only the users who match these target audience criteria can enter the journey.

Identify Conversion Events: the “why” Why are you building this Canvas? It’s always important to have a defined goal in mind and Canvas helps you understand how you are performing against KPIs like session engagement, purchases, and custom events.

Selecting at least one conversion event will give you the ability to understand your campaign performance and also to help you optimize performance within the Canvas as if your Canvas has multiple variants and/or a control group Appboy will use the conversion event to determine the best variation for achieving this goal.

Build the experience: the “how” and “where”

  1. Setting up variants: A variant is the trail each customer follows on their journey. Canvas supports up to four variants with a control group. While not required, you can name each variant, as well as control the distribution of the target audience following each variant.

  2. Building steps: A step is a marketing decision point—what is the experience you’re creating? Within a step you can set triggers or schedule delivery, refine targeting by adding filters or marking exception events, and add channels from email to push to webhooks.

  3. Determining when and how to use steps & variants: Each Canvas must have at least one variant and at least one step. The sky’s the limit from there—so how do you decide on the shape of your Canvas? That’s where your goals, data, and hypothesis come into play. The “how” and “where” brainstorm from above will help you map out the right shape and structure of your Canvas. There are a couple approaches you can use:

    a. Work backward: Some goals have smaller sub-goals. There is a great lecture on growth from Alex Schlutz that explains how finding your North Star and that Magic Moment where customers understand your value proposition are powerful stimulants. This can be applied on the Canvas level by finding the intermediate step to your goal. For instance, if you’re aiming for converting a free user into a subscription, you may need a page with your subscription services outlined. A visitor may need to see the options before they purchase. You may focus your messaging efforts on showing them this page before a checkout page. Working backward to understand the journey a customer must go through to get to your goal is key to guiding them through to conversion.

    b. Start with the status quo and add more: Have you ran a similar campaign in the past? Or is one currently running? Use that one message and add to it. Try a new filter or add a followup message. Look at your performance and keep optimizing by making incremental changes.

    c. Look to others: Imitation is the highest form of flattery. Don’t reinvent in the wheel. Don’t worry, we have you covered. At the end of this guide, you’ll find some outlines that can help you get started.

Moving the needle: Measuring and testing with Canvas Analytics

You need to know if what you’re building is moving the needle. Canvas makes it easy to understand how the experiences you’re building are impacting your goals. Once you build your Canvas and set it live, you can review performance on the Canvas Details page.

Canvas Overview


At the top of the Canvas Details page, there are topline Canvas stats. These include the number of messages sent within the Canvas, the total number of times customers have entered the Canvas, how many have converted and your total rate, the revenue generated by the Canvas, and the estimated total audience. This is a great way to level set in general how you’re doing against your goal.

Performance Visualization


As you move down the Canvas details page, you’ll see the performance for each step. These metrics include sends, unique recipients, conversion count, and revenue generated. You can click to breakdown further and see channel specific performance.

Performance Breakdown (by Variant)


At the bottom of the Canvas Details page, you can see a breakdown (by variant and Control Group if you have more than one) of performance. This is a clear table showing you by variant the number of steps, total sends, total entries, conversions, and total revenue. You can quickly infer effective variants and identify the right cadences, content, triggers, timing, and more!

Four Canvas Outlines

Journey_8 Onboarding - Restaurant Reservation Example

  • What: Onboarding users to their first reservation
  • When: Triggered at session start
  • Who: All New Customers
  • Why: Perform custom event “completed reservation”
  • Where: Push, Email
  • How: Channel, Content (test)

Journey_9 Upsell - Music Streaming Example

  • What: Upgrading active freeloaders to basic premium subscription
  • When: Triggered after custom event of “milestone - 3 hours music streamed”
  • Who: All Active, but free customers
  • Why: Perform custom event: visit pricing page
  • Where: Push, Email, Webhook
  • How: Content, Discount

Journey_10 Cart Abandonment - Clothing Retail Example

  • What: Reminding customers of incomplete purchases
  • When: Triggered after custom event of “abandoned cart”
  • Who: All registered customers
  • Why: Make purchase
  • Where: Push, Email
  • How: Channel, Trigger (test)

Journey_11 Holiday Travel - Airline

  • What: Educate customers on resources and prime them for good flight and airport experiences.
  • When: Scheduled daily until January 1st
  • Who: Customers booked for travel in two days with the app
  • Why: Session Start
  • Where: Push
  • How: Channel, Cadence (test)

Creating A Canvas

Step 1: Navigating to the Canvas page

Click on the “Canvas” link on the Dashboard’s side navigation located underneath the “Campaigns” link:

Canvas Dropdown

Step 2: Create a New Canvas

Click the “Create New Canvas” button:

Create New Canvas Button

Step 3: Name Your Canvas

Click on the name of your Canvas to edit it:

Name Your Canvas

Step 4: Set Your Starting Condition

Click on the “Starting Condition” link to control how users will be enrolled in a particular Canvas.

Canvas Starting Condition

There are two ways in which users can enter your Canvas. With scheduled delivery, users will enter on a time schedule, similarly to how you would schedule a Campaign. You can enroll users in a Canvas as soon as it is launched, or enter them into your journey at some point in the future, or on a recurring basis.

Canvas Scheduled Delivery

Additionally, you can choose to enter users into a Canvas when they perform certain triggers using Action-Based Delivery. Users will enter your Canvas and begin receiving messages when they take particular actions, such as opening your app, making a purchase, or triggering a custom event.

Canvas Action-Based Delivery

You can control other aspects of your Canvas’ behavior from the Entry Audience window, including rules for re-eligibility and frequency capping settings.

Step 5: Set Your Target Audience

Click on the “Target Audience” link to control the eligible audience for your Canvas:

Canvas Target Audience

You can set the target audience for your Canvas from this screen. Only the users who match these criteria can enter the journey. For example, you might want to limit a particular journey to users who first used your app less than 3 weeks ago. You can also control settings such as whether messages should be sent to users who are subscribed or opted-in to your notifications.

Canvas Opted-In

Step 6: Choose a Conversion Event

Click on the “Conversion Event” link to choose a conversion event goal for your Canvas:

Canvas Conversion Event

We will use the Conversion Event that you set from this screen to measure the efficiency of your Canvas. If your Canvas has multiple variants or a Control Group, Appboy will use this Conversion Event to determine the best variation for achieving this Conversion goal. Using the same logic, you can create multiple Conversion Events:

Canvas Conversion Start

Step 7: Add a Variant

Click the “Add Variant” button and select the option to add a new variant to your Canvas. variants represent a journey that your users will take:

Canvas Add Variant

You can add additional variants by pressing the + button. When you add new variants, you’ll be able to adjust how your users will be distributed between them so that you can cross-compare and analyze the efficacy of different engagement strategies:

Canvas Multiple Variants

Step 8: Editing a Step

Click anywhere on a Step, and Appboy will open the Step editing interface. Steps can be configured to send messages after either a fixed delay, or when a user performs a particular action. For example, you can use Canvas to configure a Day 1, Day 3, Day 7 onboarding Campaign with time delays between messages:

Canvas One Day

Or you can set a group of messages to be sent after your users take a particular action, with a configurable window, delay, and exception events:

Canvas Exception Events

You can also apply Filters to each Step of a Canvas. Use this to add additional control flow logic, such as dropping users out of a journey when they’re not likely to need additional engagement encouragement:

Canvas Additional Engagement

Edit the Messages in a Step to control messages that a particular Step will send. Canvas can send Email, Mobile & Web Push messages, and Webhooks to integrate with other systems.

Canvas Message Edit

Press the “Done” button once you’ve finished configuring your Step.

Step 9: Add More Steps

Add more Steps by pressing the blue plus icon:

Canvas More Step

Step 10: Multivariate Testing Using Canvas

You can add a Control Group to your Canvas by clicking on the Plus icon to add a new variant. Appboy will track the Conversions for users who are placed into the Control Group, although they will not receive any messages. In order to preserve an accurate test, we will track the number of Conversions for your variants and the Control Group for exactly the same amount of time, as shown on the Conversion Event selection screen. Adjust the distribution between your messages by double clicking the variant Name headers.

Canvas Multivariate

Step 11: Saving & Launching Your Canvas

Once you’re done, press the “Launch Canvas” button at the bottom right to save and launch your Canvas. You can also save your Canvas as a Draft if you need to come back to it.

Once you’ve launched your Canvas, you’ll be able to view analytics for your journey as they come in:

Canvas Analytics


Create a Branch

You can harness the power of Appboy’s action based delivery and powerful realtime segmentation to deliver personalized experiences for your users.

To create a branch, click on the blue circle at the bottom of a Step. Then click on one of the shadowed icons to create a new step.

Canvas Create Branch 1

Create another step, branching from the first:

Canvas Create Branch 2

You can setup filters to determine how users should flow to subsequent steps.

Canvas Create Branch 3

Or you can have users flow between branches based upon actions that they take.

Canvas Create Branch 4


Overlapping Filters

When setting up your Canvas, you should ensure that the Filters that you use to split users down different branches do not overlap. If a user can match multiple steps, Appboy will pick a branch to send them down. For example:

Canvas Create Branch 5

If a user first made a purchase 7 days ago, they will be randomly slotted into one of the branches above.

Key Value Pairs

Appboy 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


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
category string Performs custom actions for values you have instantiated as identifier properties of the UIMutableUserNotificationCategory object
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

Appboy’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 Appboy 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 Value Input

Use-cases for custom key value pairs include but are not limited to internal metrics keeping and setting the context for the user interface. Appboy 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 include customer information or any senstive 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.


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

Appboy’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 Value Input

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 Appboy Documention.

Appboy 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" : ""
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 Appboy Documentation for further instructions on how to set these options in the Appboy 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 Appboy’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.

Testing Filter 1 Testing Filter 2

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


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

Key Value Input

In-App Messages

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

Key Value Input


For Appboy 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 Value Input

News Feed

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

Key Value Input

In-App Message Color Templates

You can save in-app message and in-browser message templates on the dashboard to swiftly build new campaigns and messages using your style.

Adding a Color Profile

Color Profiles

You can customize the color scheme of your message template by either entering HEX color code or by clicking the colored box and selecting a color with the color picker. Click the “Save Color Profile” button on the bottom right when you’re finished.

Template options

Template Options

From the template options page, you can add a new color profile and edit or delete existing color profiles. You can also set a default color file by selecting “Set as Default” from the dropdown menu.

Rich Notifications

Rich Notifications allow for more customization in your push notifications by adding additional content beyond just copy. Android notifications have included images in push notifications for some time now, messaged as an ‘Expanded Notification Image’. Starting with iOS 10, your customers will be able to receive iOS push notifications that include gifs, images, videos, or audio.

Rich Not Blog

Android Rich Notifications


  • Note that expanded notification view is only available on devices using Jelly Bean (Android 4.1) or higher. If a user’s device is not running on these systems, they will not see the notification image.
  • Currently, Android rich notifications only allow for static images including jpg and png file formats.

Setting Up Your Android Rich Notification

  1. Follow the campaign steps you normally do to compose a push notification for Android. You will be using the same composer that you use for setting up push notifications that do not contain rich content.

  2. Add your Summary Text/ Image Caption that you’d like to display above the image in the notification.

    Add Android Summary Text

  3. Add your image in the ‘Expanded Notification Image’ field in the composer of the message. Images can be uploaded directly through the dashboard or by specifying a content URL that is hosted elsewhere.

    Add Android Image

  4. Once your rich notification content is uploaded to the dashboard, you can simply continue scheduling your campaign the way you always do.

iOS 10 Rich Notifications


  • To ensure your app is able to send rich notifications, please follow these instructions here, as your developer will need to add a service extension to your app.
  • You should also reference Apple’s documentation for media limitations and specs. We recommend using as small of a file size as possible. In practice, sending large files can cause both unnecessary network stress and make download timeouts more common.
  • File types that we currently support for direct uploading within our dashboard include jpg, png, or gif. These files can also be entered into the templatable URL field along with these additional file types: aif, m4a, mp3, mp4, or wav.

Setting Up Your iOS Rich Notification

  1. Follow the campaign steps you normally do to compose a push notification for iOS. You will be using the same composer that you use for setting up push notifications that do not contain rich content.

  2. Add your image, gif, audio, or video file in the ‘Rich Notification Asset’ field in the composer of the message. Please reference the above requirements on how to add your content files.

    Add Image

    You can also limit this message to only send to users who have a device that runs on iOS 10. For users who have not upgraded to iOS 10 it will appear as a text only notifications without the rich content if you leave the below box unchecked.

    iOS 10 Checkbox

  3. Once your rich notification content is uploaded to the dashboard, you can simply continue scheduling your campaign the way you always do.

Notification IDs

A notification ID can be assigned to a push notification when you want the option to group or replace it with an updated version once it’s been issued.

To do this, navigate to the composition page of the push you’d like to add the ID to and enter an integer in the Notification ID section. To update this notification once you’ve issued it, send another notification with the same ID that you used previously.


Developer Console

The developer console section of the dashboard is useful for both important identification information for your app group and for troubleshooting.

API Settings

The API Settings page displays API identifications for your app group. The first section on Services will link you to our technical documentation for whatever you’re using the API for.


The Authentication section is your App Group Identifier, or the unique identifier that allows you access to your data for an app group. This key is required with every request to the Appboy API.

API Whitelisting

You can whitelist specific IP addresses and subnets to send requests to our API for this app group. If you don’t specify any, requests can be sent from any IP address.


These identifiers are used to reference specific Apps in requests made to the Appboy API.

Additional API Identifiers

To integrate with our API, you can search for the identifiers related to any Segment, Campaigns or Cards that you want to access from Appboy’s external API. Once you’ve selected any of them, the identifier will be displayed underneath the dropdown menu.


The message activity log displays a record of any messages or errors that are associated with the API. This offers insight on how to improve notification deliverability and for solving existing technical issues.

troubleshooting developer console

Within the logs, you can apply filters for the type of messages that you want to see by selecting them from the the Add Filter dropdown menu.

iOS Push Message Titles

To add a headline to an iOS push notification, select the gear icon in the Appboy message composer. Check the tick box next to Alert Options and enter your chosen headline in the Message Title field.


The headline will appear in bold once the message is sent.


Engagement Reports

Appboy allows dashboard users to export an aggregated report regarding their campaign performance. Previously, this data was only shown in the dashboard and required API’s to extract. However, with this feature Appboy enables marketers to utilize a simple step-by-step wizard to run an engagement report.

How To Use

A new section has been created for marketers to interact with this feature.
Navigate to Data » Engagement Reports


Note: you must have ‘Export User Data’ access to utilize Engagement Reports.

Creating A New Report


To create a new report, click ‘Create New Report’ located on the top right of the page.


Follow the 4 step process to generate a report.

  1. Setup Report
  2. Add Campaigns
  3. Add Stats
  4. Confirm

About the Report

  • The report is exported as an attachment to the email address provided in the ‘Setup Report’ section.
  • The report, when opened, will contain all the statistics selected in the ‘Add Stats’ section of the setup process. The stats available to select will change dependent on the type of campaign you select.
  • The campaign time-frame that is included in the report, is from the ‘creation time’ of that campaign till the ‘present time’ when the report is ran.
  • When selecting multiple campaigns, the report will include data from the earliest creation date out of all the selected campaigns to the present date.
  • Certain data is aggregated at the ‘campaign’ level versus at the individual message level.
  • Note: Reports are not saved, and re-running the report can result in updated statistics.

Internal Groups

The Internal Groups feature allows you to create a list of targeted users for both Content or SDK log testing. You’ll be able to create an unlimited number of Groups, and Internal Groups that are enabled for Content testing allow you to send a preview test of any Push, Email or In-App message to your group members. Groups that are enabled for SDK or Rest API logging are meant for SDK integration testing.

Creating a Group

Dashboard users can create multiple Internal Groups and set these groups to be utilized for Content Testing, SDK or API Logging (or a combination of all of these).

In order to Create a new group, you will need proper access rights set by your Administrator.

  • Navigate to the Developer Console Tab located under App Settings on the navigation menu.
  • Once you are in the Developer Console click the ‘Internal Groups’ Tab located on the top.
  • Click ‘Create Internal Group’ on the top right to create a new group.
  • Give your group a name.

Internal Group

Adding Test Users

To setup a test user, access the Internal Groups management section located within the Developer Console.

Note: admin access may be needed to access this section.

User Logs 1

Click the “Add Test User” button. You can add two types of test users: identified and anonymous.

Identified Users

You can search for the user by their External User ID or email address.

Identified user

Anonymous Users

You can search by IP address.

Anon users

Provide a name for each test user that is added. This is the name that all event logs will be associated with on the Event User Log page.

Content Test Groups

Similar to sending a preview test of a message, the Content Test group saves you time and allows you to launch tests to a pre-defined list of users simultaneously. This functionality is available for Push, IAM, and Email within Appboy.

You can select individual users or as many Internal Groups to send the message to as you want. You can preview the message as a ‘Random’, ‘Existing User’, or ‘Custom User’.

Only Groups that are tagged as Content Test will be available on the ‘preview’ section of a message.

Content test group settings

Note: The version being previewed will be sent to everyone in the Group that was selected.

Event User Logs

Navigate to the Event User Log section located within the Developer Console. Here, you can see all the events for all users that were added in the Internal Groups section. To find your logs easily, you can filter based on:

  • SDK or API
  • App Names
  • Time frame
  • User

Each log is broken up into multiple sections, which can include:

  • Device Attributes
  • User Attributes
  • Events
  • Campaign Events
  • Response Data

Click the “Raw Data” button to show the raw JSON data for that specific log. Raw logs

Event User Logs will remain in the dashboard for 7 days after they are logged.

Creating a Webhook Template

Step 1: Navigate to the Webhook Template Editor

You can access the Webhook Template by first clicking the Campaigns tab under Engagement on the navigation bar, which will reveal a drop down menu with a ‘Templates and Styles’ tab. Click on this tab to access the Webhook Template Editor.


Step 2: Create a New Template

You can now create a new template, edit an existing template or utilize one of the predesigned webhook templates that are offered. The pre-designed templates currently offered are for Twilio and Facebook messenger.

Step 3: Customize Your Template

Webhook templates can be used for many different use cases. You can start by entering a unique template name to be utilized. You can also fill in the webhook URL, the Request Body, Request Headers and select the HTTP Method to be used.

If you want to see how your webhook looks before sending it out to your users, you can send a test webhook through the Settings tab in the top right corner.


Step 4: Save Your Template

Be sure to save your template by clicking the “Save Template” button in the bottom right corner of the editor. You’re now ready to use this template in any campaign you choose.


Note: Edits made to an existing template will not be reflected in campaigns that were created using the previous versions of that template.