Each campaign has a workflow. This workflow consists of one or more actions, that are executed in conjunction with the campaign being triggered. The action types available are:

The workflow can contain just one single action, several actions of the same type, or a mix of actions of different types.

Each action can be timed to happen after a certain delay from the campaign trigger. Default is “immediately”, which means that the action is executed as soon as the campaign is triggered. There can be several actions set to be executed immediately, but if you have a number of campaign actions they are more likely to be separated by a number of minutes, hours or days.

The delay starts from either the user executing the campaign trigger for an automated campaign, or from the user being targeted for campaigns with no defined trigger event.

Adding and deleting actions

adding the first action

When entering the workflow editor, it you will be asked what type of message you want to use for your initial action. This will depend on the available channels for your app.

Adding an action

Workflow editor

A workflow can consist of any number of actions (at least one). By clicking the plus button at the bottom of the workflow, you can add an additional action to the workflow:

Add action button

When adding the action, you will get to choose which type it should have.

Deleting actions

To delete an action in the workflow, click the trashcan to the right of the message title in the workflow:

Delete action

If there’s only one action in a workflow, it can’t be deleted.

Editing actions

To edit the contents of an action, click on its preview in the workflow, or click on the pen icon to the right of the message title:

Edit action

This will cause the focus to move to the selected action, indicated by its preview image being zoomed-in in the workflow. Its settings form will be opened in the right-hand column.

Message personalisation

before you start

Before you can start using custom personalisation in messages you will need to configure the events used to create them in the app settings tab. Check the documentation here for more information.

In your messages, you can use personalisation to include data such as user names, dates of birth, and purchased products in subject and text fields as well as in urls and data messages.

To personalise a message you can enclose any available attribute in two curly braces {{like.this}}. Before the message is sent to the user the macro will be replaced with the actual value for this attribute for this user.

using personalisation in messages

As soon as you type the first two curly braces we will load a list of available attributes for your app; you can either type your attribute or select it from the list.

As a personalised message won’t really make much sense if for a particular user we do not have a value to substitute before sending the message, we will not send the message to these users. For attributes where you do not have 100% coverage you can include a default value which we will use in such cases. For example, you could have an attribute for a user’s name but this might only be supplied when a user registers. In such a case, you could provide a default value for unregistered users by adding the pipe ‘|’ symbol and enclosing what you would like to use as a default in quotes, like this {{custom.user_name | default('dear user')}}.

Another way to send your message even if one or more of the personalisation attributes in your message do not exist for a user is to allow it to be empty. To do this, you just supply a default value of nothing, like this {{custom.your_attribute | default('')}}

Using personalisation attributes in URLs

When you use personalisation attributes - which may contain blank spaces or special characters - in URLs you can use the function url-encode to make sure that they are made ‘url safe’ before your message is sent to the device. Functions, are added after the pipe symbol | and separated by a comma. That means, if you are using the url-encode function as well as the default function, your final substitution variable will look like this {{custom.my_attribute | default('something not safe for urls &*$'), url-encode}} This would make sure that any value of the attribute will be made url safe and will also encode the default value for you if the attribute does not exist for a particular user. example{{custom.last_page | url-encode}}&another_attribute={{custom.city_name | default('Mülheim an der Ruhr'), url-encode}}

The encoding function should be used anywhere you think there may be spaces or special characters in an attribute and you are using them to build a URL. This includes things like os names, for example ‘iPhone OS’ or ‘Mac OS X’ would cause problems if used in a url without first having been made safe.

standard attributes

For every app we capture some standard attributes, mainly about the device. These kinds of attributes start with device. and include such things as the phone make and model, operating system and other such device-related data.

The second group of standard attributes are the environment. attributes, this includes information on the app like app version, ids and not much more.

Any custom. attributes are attributes you have set up yourself to be updated based on a certain event or set of events that your app or another backend data source provides us.

For a full list of attributes available for your app visit the app edit page and navigate to the personalisation tab where you can also set up new custom attributes for your app.

Campaign Context information

You can add key / value pairs or keys with an array of items to any workflow action. If supported by your app you can then use this contextual information to help make more intelligent decisions about when and whether to display messages to your users.

before you start

Your app developers will need to create their own logic to react to campaign context information. Make sure you discuss your strategy with them first and that the data you set here matches the rules built in to your app.

Take a simple example; if you agree with your developers that a message containing the key internal_testing and a value of true will never be displayed on your production app unless the device was also registered as being part of an internal test pool then any campaigns you create including this would be suppressed by your app instead of ever mistakenly being shown to real users. When the campaign is ready, you’d simply clone it and remove the contextual flag.

Similarly, you can agree on prioritising campaigns based on a key priority which takes numbers. If your app then has a number of inapp messages queued up for a user, they can display the most important or interesting first based on this and some simple logic.

campaign context

It is a quite flexible system so you should discuss your use cases with your team to get the most out of the least effort.

We accept numbers, normal strings and lists. When adding a new item to your message context you can select either one of these, for lists, there can be a maximum of 100 items and each string or number is limited to a maximum of 255 characters in length. This is due to the size limits of push messages imposed by both FCM and APNs. Anything above these limits will not be accepted and message sendout would fail.

Push Message

Push messages are text notifications that appear on the standby screen of the device. They are only shown if the app is closed at the time of message delivery.

customising Push Message layouts in Android

Check out our developer docs and read up on how to customise your notifications on Android to match your branding or just to add a little flair to the notification shade.

Message subject and body text

To edit the subject or body text of the push message, click on the respective area in the preview, and just start typing, you can even throw in some emojis to really catch a user’s eye:

Message subject and text

Due to screen size limitations and massive variations between devices, it’s recommended not to have push messages longer than 37 characters for Android, and 89 characters for iOS. These limits will be more strictly enforced for any messages containing image or media attachments.

That being said, if there is no image attachment, both platforms will support up to around 1,000 characters in an expandable message format. New lines can be created by using the control character /n

Android large icons

For Android push messages you can include an extra icon which will be included with your image. This can differ from your main app icon and can be a full-colour image.

To add your icon simply click the placeholder icon on the Android preview and enter the location of your image. Remember, it must be served from a secure, HTTPS domain and will be shown with a round mask so bear in mind that the corners of your image will not be shown.

As the platforms will not follow redirects, you must link directly to the image file

Adding icons to messages

Adding Android Large icon

Standard notification, Android M and N

Large icons on Android M and N

Rich Push

Rich Push allows you to include images and other media along with your notification. This is a sure-fire way of catching your users’ attention.

before you start

Before you can start using using rich push make sure that you are using SDK version 3.4 or higher. Additionally, while Android support does not require any special attention, an extra integration step is required for iOS. Make sure your developers are aware of this and have read the corresponding section of our SDK integration guide.

Rich notifications generally appear in a collapsed or expanded view. When collapsed your image will appear as a thumbnail, with the user able to slide the notification open, or long press on iOS 3D Touch capable devices to see the expanded view.

Android and iOS both support image attachments in .png or .jpg format. The recommended aspect ratio is 16:9. (hint Scroll to the bottom of this page for a note about cropping on Android.)

Adding your images couldn’t be easier, simply click the plus icon next to your message text to provide links to your images.

Add images to a notification

iOS devices also support animated gifs and video files. The maximum size for gifs is 10MB and the maximum size for video is 30MB, although we would recommend using smaller file sizes as there is a strict time limit for the device to fetch media once a notification has been received, and on slower (particularly cellular) connections, large files are more likely to time out.

To add media to an iOS notification use the same button to provide a link to your video or gif.

Adding video attachments for iOS 10

As both Android and iOS support images but only iOS supports video, we’ve made it easy for you to create your notifications with the best possible format per platform in a single campaign. Any images you add will automatically be valid for both iOS and Android devices targeted in the same campaign, a GIF or video which you add will only be sent to the iOS audience, no need to set up separate campaigns.

mix videos on iOS with matching images on Android


When adding media you can also provide a backup message for the case that your media can’t be downloaded in time. We would strongly recommend including an alternate text as a best practice.

On iOS Rich Push is supported on iPhone 5s or later, iPad Pro, iPad Air or later, and iPad mini 2 or later. Full support for image expansion is only available on devices with 3D Touch.

Actions tab

Under the Actions tab in the settings form, you have two options for what should happen when the user taps the push message notification:

  • Launch app (start screen): The app is launched.
  • Open URL: Either a web URL is defined which is then opened in the browser, or a deeplink that is opened in the app.

Actions tab

Timing tab

Under the Timing tab in the settings form, you decide when the message should be sent:

  • immediately. The action is executed immediately when the campaign triggers. You can set more than one action to be executed immediately.
  • after. The action is executed after a certain time has passed after the trigger happened. This delay is defined through the following settings:
    • X [time unit]: The number of minutes/hours/days delay that should be applied between the trigger and the execution of the action.
    • @ hh:mm: This setting is only available if “days” has been chosen as time unit for the delay. After waiting the set number of full days (24h) after the trigger taking place, the action will be executed on the first occurrence of this time. E.g.: the trigger happens 19:00 on the 1st of March. The delay is set to 1 day and the execution time to 18:00. The execution will then take place 18:00 on the 3rd of March (first 24h delay, then wait until 18:00).
    • [time zone]: Choosing “user local” will use the local time of the targeted device, whereas “UTC” will use the UTC time zone.

Timing tab

Other tab

Under the Other tab in the settings form, you can select which special which additional options should be applied to this notification. They are:

  • Show badge. Sets the badge counter on the app icon to 1. This feature is only available for iOS. (On Android it will have no effect.)
  • Play a custom sound. Plays a sound when the message is received. The sound file should be embedded in the app.

Other tab

Foreground notifications

A normal push message will not display to users who are in the app at the time of receiving the message. In order to get maximum reach for your content you can include these users too by setting the option to include active users in the ‘other’ tab to on.

before you start

For iOS this feature requires an additional integration step. Make sure you are using SDK version 3.6 or above and that your developers have integrated the Apple User Notification Framework and followed the steps laid out in our SDK integration guide. Foreground notifications are only available in iOS version 10.0 and above.

Here’s an example of how it looks on iphone for both a normal push and a push-announced inapp message:

A foreground notification arriving on an iPhone


Under the message preview, you have the option to add additional language versions of the message text. The one shown to the user will be the one matching their device language settings (the default if there is no match is the English version).

Language settings

In-App Message

In-app messages are images or other HTML-based rich content that is displayed within the app. Depending on your campaign type these are automatically shown if the app is open at the time of message delivery or may be stored in device memory until the trigger action is executed.

All inapp overlays are sent using the same services as push notifications. Even if a user has not opted in to push messaging, they are still provisioned a unique address by the iOS and Android platforms which can be used to send data, in this case, an HTML file.

Message content

To set the content of the in-app message, click the icon named “Provide URL”:

Provide URL

Enter a URL to the content that you want to be shown in the message. This can be either an HTML page or an image in .png or .jpg format. The file must be hosted externally and served from an HTTPS origin.

After entering the URL you will see a preview of how the message will look to the user. Note that the exact look depends on which model of device that it’s received on and transparent images will have a solid black background.

Any overlays based on images will be automatically converted to HTML by our system and will use the action, either close or Open URL, selected in the Actions tab.

Custom HTML Overlays

If you are providing your own custom HTML then read this section carefully

Inapp messages are preloaded by default so the user does not experience delays during display, however, it is important to note that the SDK will not follow external links when preloading, so all images should be included as base64 encoded versions and any css or javascript should be minified and inlined before using the HTML as a campaign creative. Most HTML creative designers will do this for you automatically or provide the option when saving. Consult the documentation for your toolset for details.

Links and any other action, such as close or requesting permission to send a user push notifications must use our d360:// schema (see below). This allows the actions to be tracked and correctly attributed to campaigns.

Native close buttons

If using simple image overlays our SDK will add a native close button so that users can exit the overlay screen, however, with custom HTML overlays it is completely up to you how and where the user can close the message. To be the most safe, you can leave the default setting intact which would instruct the SDK to read the contents of the overlay before displaying it and, if no close button is found, to automatically add one in either a dark or light style. If a close button is found, the SDK will not add anything as the user already has an option to exit.

customise the native close button for inapp messages

SDK compatibility

This feature is fully supported from version 3.8 of our SDK.

Close Overlay


Open URL


URL encoded example

please note the url in the example has been changed to

Request Push Permission


URL encoded example:

A best practice when using custom HTML overlays is to use a responsive design, not only will this look better on all screens sizes and aspect ratios, but it is also a generally cool thing to do. If working with a design team be sure to provide this in the brief and, if creating your own overlays using a tool such as Google Web Designer, use the options for creating different views for different orientations and media sizes.

Timing tab

Under the Timing tab in the settings form, you decide when the message should be sent, this is very much similar to the timing options for a push message.

In-app expiry

You can set an expiry time for your message so that it will not shown either after a given time window starting from the moment the user received the action, or fixed time and date at some point in the future.

setting the expiry

There are certain conditions under which it is not possible to set a message expiry: these include if you are using any kind of delay for this action, or if the action is triggered using advanced filtering to use both an event and any number of given properties of that event.


Under the message preview, you have the option to add additional language versions of the message text. The one shown to the user will be the one matching their device language settings (the default if there is no match is the English version).

Language settings

Web Push

Web Push messages are sent to users who have subscribed to messaging on their browser. This can be either a desktop, tablet or phone, as long as they can visit your website they can opt in to receive targeted messaging from your brand.

Check the apps section and our developer guide for help on how to set up your webpage for messaging.

send browser push to mobile and desktop users

As a CTA from your message you can lead users to a specific page in your web app (or indeed, any web or landing page) or simply open the home page by selecting either Open URL or Open App as an action.

While your messages will look slightly different depending on the target browser and platform (see below), the essential components of a browser notification are the subject, the message and an optional icon or, for Chrome browsers only, an image attachment.

message preview

Before you can send yourself preview messages you will need to accept the opt-in prompt. If, for some reason you decline this and later want to receive preview messages, check ‘site settings’ in Chrome by clicking on the padlock next to the URL, or in Firefox, head over to ‘about:preferences#content’ and adjust the permission setting or remove the site to have the notification prompt shown again the next time you try to send a preview message.


Images and icons should be served from a secure, HTTPS source and should be either .png or .jpg format only. For your icon we generally recommend something around 256x256 pixels. While larger image attachments can be higher resolutions, bear in mind that even though this not strictly mobile push, many users will still be using mobile devices, so aim to keep file sizes small and optimise your images before sending them. Animated gifs and videos are not supported.

Funnel Steps

As they very much resemble a traditional native mobile push, Web Push campaigns are tracked using the same funnel steps such as target, reach, response and conversion. However, bear in mind that for any campaigns involving conversions, you will need to provide a data stream of events in order for us to be able to track this properly.

See the section on campaign reporting for more info on our KPIs.

Using Tags

Tags can be used to tell the browser that a certain set of messages belongs together, this way, if multiple messages come in with the same tag, they will be automatically collapsed into one single, stacked notification rather than fill the screen with multiple message tiles.

Tags must not contain spaces or special characters but can otherwise be any combination of numbers and letters.

Enter your tag in the Other tab.

Example notifications:


Browser Mobile Desktop
Chrome chrome mobile chrome desktop
Chrome MacOS n/a chrome mac os
Firefix n/a firefox desktop

with image attachments (chrome only, Windows and Android/ChromeOS)

desktop Android
chrome desktop image chrome mobile image

Notice how there is a much more aggressive cropping factor in the mobile form factor, it’s almost a 4:1 aspect ratio and pretty much center weighted. This is definitely something to consider when selecting images and targeting for your campaign, depending on where the majority of users are opting in to your browser notifications.

Since Chrome 59 there has also been a change in the way that that browser renders notifications on Mac OS. Rather than using their own templates and keeping consistency with the rest of the Chrome/Android ecosystem, Chrome’s notifications are now more like Mac system notifications and match Firefox and Safari’s approach, as well as the overall look and feel of a Mac. This means that you lose the opportunity to attach a large image, but gain in that notifications will appear in a user’s notification panel and so potentially live a much longer life.

Supported Browsers, Platforms

Browser Platform From Version
Chrome Desktop 42.0
Chrome Android 42.0
Chrome iOS/iPhone OS n/a
Firefox Desktop 44.0
Firefox Android n/a
Firefox iOS/iPhone OS n/a

Data Push

before you start

Data push is a very powerful channel but requires careful planning to get the most out of. Make sure you discuss with both our integration engineers and your developers to come up with a viable and workable strategy.

Check our iOS and Android integration guides for details. Once this is done, your app will be listening for data we push to it, but not before.

Data push differs from the ‘message’ type actions, in that it doesn’t display any content to the user unless you configure your app to do so. You can basically think of it like a direct line to your app, to make changes on the fly or tweak configuration options based on any other event or simply because a user fits a certain targeting criteria.

Data is sent to your app using a format called JSON.

JSON is a way of sending key/value pairs and has fast become the de-facto way to communicate with computer systems on a lower level than a typical interface. Anybody whose seen an API or a proto-hipster-developer’s t-shirt will find it familiar. Typically, a JSON document will take the format:


You can pretty much think of JSON like a spreadsheet table without the lines, so, for example, if we wanted to represent a user and their associated data, in a table it might look like this:

username age gender country registered interests pets
desperateDAN 26 male texas yes cars,chicks,cowpie horse

Representing the same user in JSON, we would end up with an object that looks like this:

  "username": "desperateDAN",
  "age": 26,
  "gender": "male",
  "country": "spain",
  "registered": true,
  "interests": ["cars","chicks","cowpie"],
  "pets": ["horse"]

As you can see, it is quite similar, note how the curly braces essentially encapsulate the single row of our user data. This tells the system that the data inside belongs together.

Most of the words (in tech-speak “strings”) must be enclosed in apostrophes - this tells the system that this group of characters belongs together - but you can see from the example above that both the number 26 and the word true are not in quotes. This is because numbers (integers for anyone who still remembers maths class) and some special words like ‘true’ and ‘false’ are recognised concepts in JSON, we could have used “yes” instead of true in our example but then we would also have to tell the system what yes and no means.

It’s the up to the receiving app to interpret this data, be it for customisation of the app experience, showing of native ads, or something completely different. Speak to your app developers to find out what keys are available to you and what values they can take; this is a really powerful tool and so might take some getting used to, but once you do, you’ll find passing data between your CRM and app has never been easier.

Data content

To enter the data that should be pushed to the device, click on the editor that represents the Data Push action in the workflow, and start typing directly (or copy-paste previously prepared data into the editor). If in JSON-format, the editor will “prettify” the content to be easily readable, as well as give warnings for any format errors such as missing brackets. Note: newline characters are never stored as a part of the data content for the Data Push and will be ignored when saving the campaign, as well as the removal of all spaces (outside text values) to save (ironically) space.

Data input

Persisting data till the next app open

Our SDK will generally hand the data it receives straight to the app, however, in many cases you either don’t want your app to do the work of processing it in the background or just won’t need it until the next app open anyway. For these cases you can enable the option Persist to next app open which will instruct the SDK to hold on to the data until the app comes back to the foreground and is ready to respond. For users who are currently in the app, you can deal with the data as normal.

Persist Data Push

For these pushes you can also set an expiry date, either relative from the time the data is sent or as an explicit cutoff date and time after which the data will be redundant and shouldn’t be handed over to the app for processing. The expiry will be calculated from the time the message is sent from our system, and will take into account any delays set for the action. For campaigns with a conversion window, we would recommend an expiry just inside the conversion window; for multi-action campaigns, at least the same length as the delay to the next action in the workflow so as to avoid potentially showing actions out of order.

Example use cases for Data Push

As stated above, this is a really powerful and flexible way to communicate with your app, so let’s go into a couple of simple use cases to give you an idea of how this could be used:

Adapting views based on user preferences

Let’s say you have a website as well as an app and allow your users to define a preferred colour scheme. If a user expresses their preference on your mobile app there is no problem, you already have the data - but what happens if the user changes the setting on the website and then shortly after opens your app? Well, there has been no time to let the app know that the user now wants everything in a deep, blue hue, unless that is, you were using data push.

If all your data is flowing into your CRM, here we would simply set up a campaign that would trigger on a user setting the preferred colour scheme that might send a packet of data to the app that looks like this:

  "username": "desperateDan",
  "user_id": 5656543234,
  "background_colour": "blue",
  "button_colour": "dark_blue",
  "alert_light_colour": "blue",
  "display_confirmation_dialog", true,
  "confirmation_dialog_text": "Hey {{}}, we hope you like your new {{custom.background_colour}} colour scheme, if you do, click the lovely {{custom.button_colur}} button below to confirm the change."

With a listener set up in your app to receive this data and those keys being known, when the campaign is triggered by Dan’s website activities we dispatch the data to the app so that the next time he starts, the system already knows to use the blue colour scheme and to display a confirmation dialog. Thus Dan can confirm that blue is the warmest colour. Of course, for other users who have perhaps already opted to allow this change without needing to confirm every time, the “display_confirmation_dialog” might be set to false so the colour is updated automatically. It is totally up to how your app is developed.

Indeed, even if you don’t allow the user to change colour schemes on their own in this way, if your app is able to select between different screens, styles or colours based on parameters, you could create a data campaign to A/B test different layouts and designs, using reporting to see how the different groups of campaign members behaved during the experiment, and whether any change led to a significant uplift in engagement.

Offering a set of options based on user status or A/B testing offers

Let’s say you have an app where you offer your users packages of perks for a certain amount of in-app credits. With the Xray platform’s data push, you could effectively run an A/B test on how different price points or perks affect user engagement. This could be achieved by setting up a multi-worklow data push to control what each user sees when accessing the offer page in your app.

By defining your Xray campaign and app elements well, you could trigger a data push to tell your app exactly what options or prices to present to a certain segment of users, or run A/B tests among a set target group with randomised subgroups. Later in reporting you could drill down on users involved in this campaign and see which group was more engaged and which price points, perks and bundles work best.

To keep the example short we will just show a simple implementation.

  • data push 1 : 50% of users

    "user_perks": {
    "option_1": {
      "name": "one week premium",
      "credits": 750,
      "remaining": 420,
      "badges": null,
      "override_text": "less than 500 remaining at this price!"
    "option_2": {
      "name": "shinobi mode",
      "credits": 500,
      "remaining": 550,
      "badges": ["hot"]
    "option_3": {
      "name": "photo retouch",
      "credits": 750,
      "remaining": 420,
      "badges": null
  • data push 2 : 50% of users

    "user_perks": {
    "option_1": {
      "name": "shinobi mode",
      "credits": 500,
      "remaining": 200,
      "badges": ["hot"]
    "option_2": {
      "name": "five days premium",
      "credits": 700,
      "badges": ["evergreen"],
      "override_text": "but why not try a whole week for only fifty credits more?"
    "option_3": {
      "name": "one week premium",
      "credits": 750,
      "remaining": 267,
      "badges": ["limited"]

As you can see from that simple example, there is a whole lot you can change - and with a conversion event on your campaign to track which options users went for, you can test out offers, positioning, colour, whatever your app supports, and still get the benefits of having all your experiment reporting right there alongside your normal CRM data. This will allow you to slice and dice and find those small, highly engaged clusters of users and start talking to them directly - rather than screaming at a crowd through a megaphone!

SMS Message

If enabled for your app you can send SMS messages as campaign actions to devices for which we have a mobile phone number. As SMS is such a simple messaging format you will only be able to provide a message of up to 160 characters. The message can include web links although it is best to use a shortening service due to the length limits imposed on these messages.

send browser push to mobile and desktop users


You can trigger email templates which you have set up using our email partner SendGrid. Simply enter the template id or search by name to preview the template and load any personalisation keys.

Use SendGrid email templates as a campaign action

You can use static values or personalisation parameters but make sure that you set defaults here or in your SendGrid template so that messages don’t fail when one or more personalisation attribute is missing for a user involved in your campaign.

We will use the default sender name and address for your app so you do not need to provide anything unless you want to over ride the defaults for a particular campaign, for example, if an email should come from for purchase confirmations or for delivery updates.


A note about cropping on Android

On Android devices, images will be scaled to fit the full width and then centre-cropped to around a 2:1 aspect ratio (as indicated in the message preview) so make sure you also test your message on a range of devices to make sure nothing important is lost. Bear in mind different screen sizes and formats may crop to slightly narrower or shallower aspect ratios as shown in the example below. Android crop examples