Tips and Tricks for the Airship + Movable Ink Integration

By John Greene, Director of Engineering for Partner Integrations.

Marketers are constantly exploring ways to master the art of personalization. As we’ve discussed before, any type of personalization can help drive engagement with messages. We have great tools for targeting users via behavior, preferences, and location (big “P”), and lots of ways to engage them personally (little “p”). Here is a deep dive on the Airship + Movable Ink integration that can combine both types.

While previously used mainly with web and email marketing, there are some surprising and delightful ways to incorporate Movable Ink’s image personalization into the mobile experience with Airship.

The first thing to note is that the foundation upon which personalization is built varies by use case and interface. Movable Ink does some things such as location detection out of the box, so simply including a link to an image asset may be enough to get some degree of personalization. But it also provides a means to personalize based on a customer identifier of some sort, and that’s the really powerful part.

There are two fundamental ways to render personalized Movable Ink images in a mobile context:

  1. Send the personalization information along with the API call that triggers the message
  2. Get the personalization information at load time, from the device or an API

Both options are interesting and useful for different workflows and have specific requirements for the templates used. In the first case, the template will simply transform the specific personalization parameters into image URLs, each distinct per recipient. In the second case, we make use of the Airship Javascript Bridge to execute predefined logic in the SDK to fetch personalization parameters from there when the message is viewed by the user, then the images are created dynamically using those parameters.

Naturally, it’s all about the details so it’s important to understand what’s supported, and how. It’s also important to remember that sending personalization information along with the API call doesn’t necessarily have to mean large amounts of development work: Our SFMC integration supports this out of the box.

The first type of MI-integrated personalization can work with:

  • Lock-Screen notifications (Rich Media displayed on Lock Screen has some limitations.)
  • Rich Message Center messages

The second type can work with:

  • Rich Message Center messages
  • Landing Pages
  • In-App Automations

In order to trigger a 1:1 Personalized Rich Message from an API call, the best approach is probably to use Airship’s Custom Event framework. A Custom Event can be used as a trigger for an Automation, and Automations can be pretty flexible about leveraging Custom Event properties.

We think of Custom Events as ephemeral signals sent to Airship in order to report engagement or conversion, or to trigger automations. Custom Events are flexible, and can have arbitrary properties and values associated with them. These in turn can be leveraged in the Automations as personalization data, and in this case used to allow Movable Ink to personalize images and assets.

Without delving into how the Custom Event gets to Airship (consider the SFMC example above), it’s simple to render MI images, both on the Lock Screen and in Rich Messages. Consider this payload:

{     “occurred”: “2020–07–20T06:00:00”,     “user”: {         “named_user_id”: “jg”     },     “body”: {         “name”: “golly”,         “interaction_type”: “crm”,         “value”: 1000,         “properties”: {             “first_name”: “John”,             “named_user”: “jg”,             “email_address”: “”          },          “session_id”: “cd1d893b-cafa-4636–9dac-d83138bef8bf”      }}

Including a Rich Media URL in the Push Notification configuration can leverage whatever properties are needed from that Custom Event:{{$[0].properties.named_user}}

The image I set up in MI simply reflects the Named User back, which is fine for this example:

Using the Custom Event properties in a Message Center message is accomplished by manually uploading your markup that uses Handlebars in much the same way. In my case, I just created an <img> tag and used that URL as the source:

<img src=”{{$[0].properties.first_name}}&userid={{$[0].properties.named_user}}">

Sending personalization data 1:1 in an API call is straightforward and easy to understand. Where things become a bit more challenging (and possibly rewarding!) is getting the personalization key at runtime from the device and coupling that with Movable Ink’s capabilities.

Personalization from a Broadcast Message

Sending a message to a segment in Airship is a pretty common workflow; for example, it’s easy to define an audience and compose a message, and Airship handles making sure it gets to the right devices. However, this is typically a uniform message for the entire segment. We’ve made some significant changes recently to make it possible to personalize these types of messages, but assuming that the necessary attributes have not been associated with the users or devices in Airship, it’s still possible to get a key to pass to Movable Ink in order to render a personalized image, even in an In-App Automation.

Let’s assume that there is a common user identifier that systems recognize, and when a user authenticates on a mobile device, this value is set as the “Named User.” The Airship SDK makes certain information about the device available to Web Views that it provides out of the box, including Message Center, Landing Pages, and In-App Automations. That is how it works: the Airship mobile SDKs inject a JavaScript object in pages rendered by it called UAirship. This object has methods for running actions (such as setting Custom Events or Tags) and getting properties. For example: UAirship.getNamedUser(), obviously for getting the Named User associated with the device. Since this happens at runtime, it’s fairly straightforward to:

  1. Execute some custom code when the UAirship interface and page content are fully loaded
if(typeof UAirship === ‘object’ && UAirship.runAction) {onload()} else {document.addEventListener(‘ualibraryready’, onUAReady, false)}
  1. Grab the Named User and assign it to a variable
var named = UAirship.getNamedUser()
  1. Create an <img> element and insert it into the DOM
if(named !== null && named !== “”) {var replaceElement = document.getElementById(“banner_image”);var newImageElement = document.createElement(“img”);newImageElement.src = movable_ink_image + “?mi_u=” + encodeURI(named);replaceElement.firstChild.replaceWith(newImageElement);

Those are the fundamental steps, but the integration allows for some more advanced functionality. For example, a Deep Link would normally need to redirect a user through the browser; this is not optimal in an app context because it would effectively cause them to leave the app and be redirected back into it. Some custom code can work around that:

var xhr = new XMLHttpRequest();‘GET’, url, true);xhr.setRequestHeader(“Accept”, “application/json”);xhr.send();xhr.onload = function() {    if (xhr.status != 200) {        console.log(`Error ${xhr.status}: ${xhr.statusText}`);    } else {        var json_response = JSON.parse(xhr.responseText);        var deep_link = json_response[‘location’];        var action = “^d”;        if (deep_link.startsWith(“http”)) {           action = “^u”;        }        UAirship.runAction(           action,           deep_link,           function() {               return true           }         )     }  }

* Please note that this approach will only work with our specific hostname, but you are free to use that!

This snippet gets the redirect location from the response header, examines it, and does the right thing from within the app itself.

It’s a good idea to set Airship Custom Events for tracking things such as conversions, which is also easily done from the markup. It’s useful to assign a class to any conversion event and set an event listener on it to do that in the background:

function capture() {    // This creates a Custom Event object and sets it in the SDK    console.log(‘running custom event’)    var custom_event_object = {};        custom_event_object.event_name = “open_movable”;    custom_event_object.event_value = 1; = {}; = “” + UAirship.getNamedUser();    UAirship.runAction(“add_custom_event_action”, custom_event_object, true);    return;}

Airship has gone ahead and put it all together here. Feel free to use this template as is (replace the movable_ink_image and movable_ink_url variables with the ones you generate), or extend it to do more things! That could include keying off of a different identifier, such as Airship’s Channel ID (also available via JS Bridge), or including multiple Movable Ink images. Also, let us know how it works for you, or if you’ve done something cool with it!

Urban Airship is now Airship! Leading brands trust us to help them achieve digital growth. We make mobile moments magic.