Custom Events

Use custom events to track user activities and key conversions from inside or outside of your app or website, tying them back to corresponding digital engagement campaigns. You can also trigger automation based on custom events.

In this guide, we will show you how to implement custom event tracking both via our web and mobile SDKs and via your internal customer tracking systems, tying all digital engagement activities together regardless of source.

What are Custom Events?

Airship provides out-of-the-box analytics for many different kinds of events through our mobile and web SDKs. Many of these events are standard and therefore applicable to all apps and websites, e.g., opens or tag change events. Custom Events, as the name suggests, are customizable to suit the needs of your app or website.

Setting up custom events in your app is easy. We provide ready-made templates for certain common types of events in our iOS, Android, and Web SDKs, and we also provide you the flexibility to set up your own events with just a few lines of code.

Custom events can also have properties associated with them. Event properties are key/value pairs of data that can provide more detail and customization to the events you are tracking. Examples include a property for a product SKU on a purchase event, or a category on a viewed video event.

Additionally, Real-Time Data Streaming supports streaming custom events to your business systems in real time. See our Data Streaming API Reference for details.

Custom Events as Triggers

When you set up an automation or journey, you can specify the custom events and custom event properties that will trigger the automation or journey.


Server-side events cannot be used to trigger an In-App Automation.

You can also personalize your automations and journeys with values from the custom event that triggers your message using HandlebarsAirship’s message personalization syntax using double curly braces, more commonly known as {{handlebars}}. Use handlebars to insert variables and conditional logic in messages and templates. . When a member of your audience triggers the custom event, they will receive a personalized message with values from that event.

Custom event properties can contain objects and arrays of objects. Use dot notation to access nested properties — parent_property.child_property.

For example, if your custom event has a user_name property, you can add {{user_name}} to your message, and anybody receiving the message would see their user_name in the message they receive.


Custom event properties used to be referenced in the $[0].properties namespace. If you have templates referencing properties in this namespace, they’ll still work, but you’ll have to continue using this namespace until you contact Airship and move over to the simplified namespace for custom event properties.

Tracking Custom Events

Event Templates

We provide ready-made templates for our iOS, Android, and Web SDKs to get you started with a number of common account-, media-, and retail-related events.

To browse the available templates, see Custom Event Templates. Sample code is provided to get you started quickly.

Sample Custom Event Code

Tracking custom events in your app is similar to adding an Airship segmentation tag, requiring just a few lines of code to run when you would like to record the action.

Below are three simple examples of creating and tracking a custom event, with code samples for iOS, Android, and Web. You can find more detailed implementation details for iOS, Android, and JavaScript in the Appendix: Code Samples section below, including considerations and rules about using Event Name and Value fields. Events are automatically batched and sent in the background to minimize battery consumption.

Create a simple custom event

Here is an example of a custom event in its simplest form, tracking the number of videos played when a user taps a Play button in an app:


let event = UACustomEvent(name: "event_name", value: 123.12)

// Set custom event properties
var propertyDictionary = Dictionary <String, Any>()
propertyDictionary["boolean_property"] = true
propertyDictionary["string_property"] = "string_value"
propertyDictionary["number_property"] = 11 = propertyDictionary

// Record the event in analytics
// Create and name event
UACustomEvent *event = [UACustomEvent eventWithName:@"consumed_content"];

// Set custom event properties
NSMutableDictionary<NSString *, id> *propertyDictionary = [NSMutableDictionary dictionary];
[propertyDictionary setValue:@YES forKey:@"boolean_property"];
[propertyDictionary setValue:@"string_value" forKey:@"string_property"];
[propertyDictionary setValue:@11 forKey:@"number_property"]; = propertyDictionary;

// Then record it
[event track];


// Create and name an event
CustomEvent event = new CustomEvent.Builder("consumed_content").create();

// Set custom event properties on the builder
builder.addProperty("bool_property", true);
builder.addProperty("string_property", "string_property_value");
builder.addProperty("int_property", 11);
builder.addProperty("double_property", 11.0d);
builder.addProperty("long_property", 11L);

ArrayList<String> collection = new ArrayList<String>();
builder.addProperty("collection_property", JsonValue.wrapOpt(collection));

// Then record it


// Create and name an event
var event = new sdk.CustomEvent("consumed_content")

// Then record it

Assign a value to a custom event

In this example we create an event that assigns a value for advanced analytics reporting.


// Create and name an event with a value
UACustomEvent *event = [UACustomEvent eventWithName:@"event_name" value:@123.12];

// Record the event
[event track];


// Create and name a simple event - and with a value
CustomEvent event = new CustomEvent.Builder("event_name")

// Record the event it


// Create and name a simple event - and with a value
var event = new sdk.CustomEvent('event_name', 123.12)

// Record the event it

Google Analytics Tracker

If you are already using Google Analytics, we provide iOS and Android SDK extensions that proxy Google Analytics events as Airship custom events. To learn more, see iOS Custom Events, Android Custom Events, and our GA Tracker repos on Github:

Server-Side Events

Server-side events are sent through the Custom Events API. When you submit an event, you’ll provide the channel ID or named user ID of the user you want to associate the event with.

You can use Custom Event Triggers to send automated messages to the channel ID or named user associated with each event.

Attributing events to named users can help you better represent user actions and trigger automations for individual users without having to map channels to external IDs.

Server-side events are involved in a significant number of Airship integrations, including Radar, a location platform for apps.

Sample Custom Event

      "occurred": "2016-05-02T02:31:22",
      "user": {
         "named_user_id": "hugh.manbeing"
      "body": {
         "name": "purchased",
         "value": 239.85,
         "transaction": "886f53d4-3e0f-46d7-930e-c2792dac6e0a",
         "interaction_id": "",
         "interaction_type": "url",
         "properties": {
            "description": "Sneaker purchase",
            "brand": "Victory Sneakers",
            "colors": [
            "items": [
                  "text": "New Line Sneakers",
                  "price": "$ 79.95"
                  "text": "Old Line Sneakers",
                  "price": "$ 79.95"
                  "text": "Blue Line Sneakers",
                  "price": "$ 79.95"
            "name": "Hugh Manbeing",
            "userLocation": {
               "state": "CO",
               "zip": "80202"
         "session_id": "22404b07-3f8f-4e42-a4ff-a996c18fa9f1"

Custom Events vs. Audience Tags

Events consist of two very basic pieces of information. They tell us that a) something happened, b) at a particular time. Events are distinct from tags, which describe the condition of a user, e.g., a stated preference or information about their app version.

The implementation of Custom Events is similar to Airship’s audience segmentation tags. The differences are straightforward:

  • Tags represent a user condition, while Custom Events represent actions.

    • A user can be tagged as a purchaser after making a purchase. The user can then be segmented later for sending follow-up messages.
    • A Custom Event can be tracked when a user purchased shoes. This is something that happened, and you may wish to count its business impact across all users.
  • Tags are for targeting users via audience segmentation, while Custom Events inform analytics reporting and trigger automated messages.

    • Audience Tags are useful to identify users for future campaigns. A person who has purchased before may be receptive to a different type of future messaging.
    • A Tag only tells you that this user purchased at least once. Because it is useful to understand how many purchases are made in total during a period of time, we have Custom Events so you can keep track of both types of data.

Custom Event Properties

Set specific properties and assign a range of values that must be met in order to trigger automation rules.

Use Cases

We recommend starting by identifying the 3-5 most important actions that users perform in your app or site.

These could include:

  • Registering for an account
  • Using a new feature
  • Watching a video
  • Viewing a specific screen
  • Saving or sharing content
  • Adding a product to a list or cart
  • Making a purchase

We recommend that you practice verb-first naming for Custom Events, for the simple reason that these events are meant to track actions and not objects. Tags are better geared for users' conditions, and for audience segmentation.

You can also track these events in varying levels of detail, based on how you name them, and optionally include values with each event. Again, plan to keep it simple. You may have other systems that track the granular specifics of your e-commerce engine or content consumption—to measure the impact of push, consider keeping reports at a higher level when starting out. For example, as a publisher, you could track a purchase event in a few ways:

  • Purchased a Magazine
  • Purchased a Sports Magazine
  • Purchased Sports Illustrated, Volume 17, Issue 9

While the 3rd variation above might provide the most detail, you can start with the 1st level of granularity to keep your reports easy to digest and roll-up, and still see which push notifications were driving the most engagement or ROI.

Here are some examples in more detail:


Tip: In our examples below, we use dashes to separate levels of granularity, and underscores for multi-word names/values (so you can double-click to select an entire parameter/variable). Also note, Event Names are lowercased, for reporting consistency. For example:

  • event_name-event_category
  • purchased_item-sports_magazine

Market VerticalDescriptionExample Event NameEvent Value
AllUser registers for an accountregistered_account
AllUser stars any product, article, or contentstarred_content
MediaUser browses a category articles or contentbrowsed_content
MediaUser plays a video Could use the event value to set the amount of time spent watching the video. Report the event after the user navigates away from the video or stops the video.consumed_contentPercentage of content consumed
MediaUser shares contentshared_content
RetailUser adds item to cartadded_to_cart
RetailUser purchases an item Use event value to capture the value of the itempurchasedPurchase Price

Event Reporting

Once you have the latest SDK installed and a snippet of code tracking custom events, you’ll start to see Event data show up in our Message Reports.

These events will appear in each message report, and in an aggregate app report, with information on whether each event occurred on an Airship delivery channel (Landing Page or Message Center), or in a custom location in your app or website.

These reports display summary data, and a CSV export option will provide full data you can slice and dice as needed or import into business intelligence or analytics tools.

See View Attributed Events for detail about the values in the Event Tracking Report.

Push Attribution

Because Airship has visibility into both the sending and receiving (via SDK) of each push, our Push Attribution model ties these custom events back to each message in ways that many analytics tools don’t – you can see the full story of conversions following both direct and indirect opens.

We track whether or not each custom event is:

  • Directly attributed to a specific push (Direct Attribution of Events)
  • Indirectly attributed to a specific push (Indirect Attribution of Events)
  • Not attributed to any push notifications (Unattributed Events)

To do this, after each push is sent, we process each event as follows:

If a push notification is sent to a device and the user taps on the notification to open the app and complete a custom event, then the event will be recorded with Direct attribution to that push notification.

If a push notification is sent to the device and the user does not tap on the notification, but opens the app later that day (within a 12 hour window) and completes a custom event it will be recorded with Indirect attribution to that push notification. If the event is completed after 12 hours (outside the attribution window), then the event will be categorized as Unattributed.

If a user completes a custom event during a time when no push was sent, or that user is opted-out, then the event will be categorized as Unattributed.

Appendix: Code Samples


When setting up Custom Events, remember:

  • Start by tracking 2 to 5 key activities or conversion points in your app.
  • When naming events, keep the total number of unique event names reasonable, so your reports are easy to read.
  • Event Names must not exceed 255 characters, or they will be ignored.
  • We lowercase all incoming events for consistency in reports, so name your events accordingly.
  • Event Values must be between -231 and [231 - 1], or the value will be ignored.
  • Event Values cannot contain “$” or “,” characters, or the value will be ignored (decimals only).

JavaScript for Rich Pages

Send a Message Center Page or Landing Page with the following HTML to set a custom event on the button. In the example below we have created a buy button which when tapped will fire the custom event with an event name of “bought book” and a value of “10.99”.

Under the hood, a Landing Page is simply a web view, so in order to propagate the knowledge that the event was fired from a landing page to the Custom Events system, we must set the interaction_type to ua_landing_page and the interaction_id to the url of the landing page.

For a Message Center Page the UA SDK is able to detect that the event is fired from a Message Center Page so interaction_type and the interaction_id will be taken care of by the SDK.

The example below detects if a page is a landing page, and sets the interaction_type and interaction_id if needed, emits an event to the Custom Events system, and writes debugging information to the DOM.

            document.addEventListener('ualibraryready', onUAReady)

            function onUAReady() {
              // Name buttons below
              // The output variable is used for debugging - comment out if needed
              var buy_button = document.querySelector('[name=buy-button]')
                , output = document.querySelector('[name=ua-attributes]')

              // For debugging - can be commented out
              // Write all the results of all getters
              output.innerHTML += 'ATTRIBUTES \n'
              output.innerHTML += '---------- \n'
              output.innerHTML += 'User Id:' + UAirship.getUserId() +
               '\n Device Model: ' + UAirship.getDeviceModel() +
               '\n Message Id: ' + UAirship.getMessageId() +
               '\n Message Title: ' + UAirship.getMessageTitle() +
               '\n Message Sent Date: ' + UAirship.getMessageSentDate() +
               '\n Message Sent Date MS: ' + UAirship.getMessageSentDateMS() +

              // Enable buttons once the ualibrary is up and running on the page
              buy_button.disabled = false

              // Listen for taps/clicks
              buy_button.addEventListener('click', onclick)

            function onclick(ev) {
              // The output variable is used for debugging - comment out if needed
              var output = document.querySelector('[name=ua-custom-event-info]')
                , message_id = UAirship.getMessageId()

              var custom_event_object = {}
                , el = ev.currentTarget

              // get value and name from the element
              custom_event_object.event_value = el.getAttribute('data-event-value')
              custom_event_object.event_name = el.getAttribute('data-event-name')

              if(!UAirship.getMessageId()) {
                 // If we can't get a messageId, then we must be in a web
                 // view, which, in this case, implies we are on a landing
                 // page.

                 custom_event_object.interaction_type = 'ua_landing_page'
                 custom_event_object.interaction_id = '' + window.location

              // For debugging - can be commented out
              output.innerHTML += 'Sending Event: \n' +
                JSON.stringify(custom_event_object, null, 4) + '\n'

              //Send the event to the SDK
              UAirship.runAction('add_custom_event_action', custom_event_object, ready)

              function ready(error, result) {
                if(error) {
                  // For debugging - can be commented out
                  output.innerHTML += 'Woops! ' +
                    error.message + '\n'

                // For debugging - can be commented out
                output.innerHTML += 'Success! The server responded:\n' +
                   JSON.stringify(result, null, 4) + '\n'
       <!-- CUSTOMIZE EVENT DATA FOR BUTTON js is looking for data-event-name and data-event-value -->
      <button name="buy-button" data-event-name="clicked_button-Buy_Now" data-event-value="10.99" disabled>
          Buy Now
      <pre name="ua-attributes">
      <pre name="ua-custom-event-info">

Injecting the Airship JavaScript Interface


The Airship JavaScript interface runs Airship actions and exposes information about the application. It should only be loaded in WebViews that are displaying content from trusted sources and that only link to other trusted sources.

If you have a WebView that exists outside of a message center you can use the following example to inject the Airship JavaScript interface in to your WebView to be able to send custom events.


The Airship JavaScript interface can be added to any WKWebView whose navigation delegate is an instance of UANativeBridge . Custom WebViews can also implement the UANativeBridgeExtensionDelegate and UANativeBridgeDelegate protocols to extend the JavaScript environment or respond to SDK-defined JavaScript commands.

self.nativeBridge = [UANativeBridge nativeBridge];
self.nativeBridgeExtension = [[UAMessageCenterNativeBridgeExtension alloc] init];

self.nativeBridge.nativeBridgeExtensionDelegate = self.nativeBridgeExtension;
self.nativeBridge.nativeBridgeDelegate = self;
self.nativeBridge.forwardNavigationDelegate = self;
self.nativeBridge = UANativeBridge()
self.nativeBridgeExtension = UAMessageCenterNativeBridgeExtension()

self.nativeBridge.nativeBridgeExtensionDelegate = self.nativeBridgeExtension
self.nativeBridge.nativeBridgeDelegate = self
self.nativeBridge.forwardNavigationDelegate = self

Make sure to remove the delegate when the controller is being deallocated:

- (void)dealloc {
    self.webview.navigationDelegate = nil;
deint {
    self.webView.navigationDelegate = nil

Optionally, enable UAirship.close() by having the controller implement the close method in the UANativeBridgeDelegate protocol:

- (void)close {
    // Close the current window
func close() {
  // Close the current window

Allow List Rules

An allow list rule needs to be added for any URL that is not hosted by Airship:

[[UAirship shared].URLAllowList addEntry:@"https://*"];

Allow list rules can also be defined in AirshipConfig.plist:


See UAURLAllowList for more details on creating valid URL patterns.

Android and Amazon

The Airship JavaScript interface can be added to any web view as long as JavaScript is enabled and the client is set to an instance of UAWebViewClient.

webView.setWebViewClient(new UAWebViewClient())

Allow List Rules

Add an allow list rule for any URL that is not hosted by Airship:


Alternatively, define the allow list rule in

urlAllowList = https://*

See UrlAllowList for more details on creating valid url patterns.