Custom Events

Custom Events let you track user activities and key conversions from inside or outside of your app, tying them back to corresponding digital engagement campaigns. In this guide, we will show you how to implement custom event tracking from both within your app and on the server-side, tying activites from your website or CRM to users of your app.

What are Custom Events?

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

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

Additionally, Connect supports streaming custom events to your business systems in real time. See our Connect API Reference for details.

Tracking Custom Events

Event Templates

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

To browse the 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 Urban Airship segmentation tag, requiring just a few lines of code to run when you would like to record the action.

Below are two simple examples of creating and tracking a custom event, with code samples for iOS and Android. 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:

iOS

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

// Then record it
[[UAirship shared].analytics addEvent:event];

Android

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

// Then record it
UAirship.shared().getAnalytics().addEvent(event);

Assign a value to a custom event

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

iOS

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

// Record the event
[[UAirship shared].analytics addEvent:event];

Android

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

// Record the event it
UAirship.shared().getAnalytics().addEvent(event);

Google Analytics Tracker

If you are already using Google Analytics, we provide iOS and Android SDK extensions that proxy Google Analytics events as Urban 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 our Server-Side Custom Events API.

To submit an event, provide the channel ID, a timestamp, a body describing the event, and a session ID. Server-side events that are submitted can be used to create automated messages using Custom Event Triggers.

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

Use Cases

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

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 Vertical Description Example Event Name Event Value
All User registers for an account registered_account
All User stars any product, article, or content starred_content
Media User browses a category articles or content browsed_content
Media User 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_content Percentage of content consumed
Media User shares content shared_content
Retail User adds item to cart added_to_cart
Retail User purchases an item Use event value to capture the value of the item purchased Purchase 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 dashboard.

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

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.

Custom Events in the Message Report:

Custom Events

Event Tracking Report:

See Event Tracking for detail on the values in the Event Tracking Report.

Push Attribution

Because Urban 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 can not 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.

<html>
    <head>
        <title>Store</title>
        <script>
            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() +
               '\n\n'

              // 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'

                  return
                }
                // For debugging - can be commented out
                output.innerHTML += 'Success! The server responded:\n' +
                   JSON.stringify(result, null, 4) + '\n'
              }
            }
        </script>
    </head>
    <body>
       <!-- 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
      </button>
      <!-- START EVENT DATA OUTPUT FOR DEBUGGING COMMENT OUT IF NEEDED-->
      <pre name="ua-attributes">
      </pre>
      <pre name="ua-custom-event-info">
      </pre>
      <!-- END EVENT DATA OUTPUT FOR DEBUGGING -->
    </body>
</html>

Injecting the Urban Airship JavaScript Interface

The Urban Airship JavaScript interface runs Urban 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 Urban Airship JavaScript interface in to your WebView to be able to send custom events.

iOS

The Urban Airship JavaScript interface can be added to any UIWebView whose delegate is an instance of the UAWebViewDelegate or any WKWebView whose navigation delegate is an instance of UAWKWebViewNativeBridge .

UIWebView
self.webViewDelegate = [[UAWebViewDelegate alloc] init];
self.webViewDelegate.forwardDelegate = self;
self.webview.delegate = self.webViewDelegate;

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

- (void)dealloc {
    self.webView.delegate = nil;
}


Optionally, enable UAirship.close() by using one of the following techniques.

Have the controller implement UARichContentWindow :

- (void)closeWebView:(UIWebView *)webView animated:(BOOL)animated {
    // Close the current window
}


Then assign the richContentWindow on the UAWebViewDelegate :

self.webview.richContentWindow = self;
WKWebView
self.nativeBridge = [[UAWKWebViewNativeBridge alloc] init];
self.nativeBridge.forwardDelegate = self;
self.webview.navigationDelegate = self.nativeBridge;


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

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


Optionally, enable UAirship.close() by having the controller implement:

- (void)closeWebViewAnimated:(BOOL)animated {
    // Close the current window
}


There is no need to assign another delegate for WKWebViews.

Note: A whitelist rule needs to be added for any URL that is not hosted by Urban Airship:

[[UAirship shared].whitelist addEntry:@"https://*.yourdomain.com"];


See UAWhitelist for more details on creating valid URL patterns.

Android and Amazon

The Urban 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.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new UAWebViewClient())


A whitelist rule needs to be added for any URL that is not hosted by Urban Airship:

UAirship.shared().getWhitelist().addEntry("https://*.yourdomain.com");


Whitelist rules can also be defined in the airshipconfig.properties file:

whitelist = https://*.yourdomain.com


See Whitelist for more details on creating valid url patterns.