Custom Events
Track user activity and conversions in your Airship channels, submit external events to Airship, trigger messages and sequences, and segment your audience with custom events.
Overview
Custom events extend our default events. Such events as opens or tag change are applicable to all apps and websites. Custom events, on the other hand, are specific to the needs of your app or website. For example, you may be interested in tracking the order created event in your e-commerce app, the playback started event in your content delivery platform, or the OnParticipatedInExperimentNotification event in your A/B testing application for tracking user participation.
You may track custom events either via our mobile and web SDKs or by using any other event tracking system.
In this guide, we will show you how to tie your digital engagement activities together using custom events:
- Set up via templates or directly in code
- Setting up a custom event for your app is easy. For common event types, we provide ready-made templates in our Mobile and Web SDKs. Alternatively, you can set up custom events directly in your code by instantiating a class from the SDK that implements the custom event API and passing a string that represents the name of the event.
- Extend with properties
- To provide more detail and customization to the events you are tracking, you may make use of event properties. These are key/value pairs, where the key represents the name of a property and the value is the information associated with this property. Examples of event properties are a product SKU on a purchase event, or a category on a viewed video event.
- Stream in real time
- Our Real-Time Data Streaming supports streaming custom events to your business systems in real time. See our Data Streaming API Reference for details.
- Trigger automation or sequence
- You may set up custom events and their properties to trigger an automation or sequence:
members of your audience may receive personalized messages with
Dynamic ContentVariable message content created using Handlebars syntax. The content is populated at send time, resulting in personalized messaging for each member of your audience. that includes information from the custom event.
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 — the value of theuser_name
property.
Tracking Custom Events
We recommend starting by identifying a few 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
Custom events track actions and not objects. For this reason, a good practice is to apply the verb-first naming convention to custom events.
You can also track these events in varying levels of detail, based on how you name them, and optionally include values with each event. 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 third variation above might provide the most detail, you can start with the first 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:
In our examples below, event names are lowercased. We use dashes to separate levels of granularity, and underscores for multi-word names/values. 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 |
We provide ready-made templates for our mobile 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.
With our mobile and web SDKs, tracking custom events is similar to adding an Airship segmentation tag. Set specific properties and assign a range of values that must be met in order to trigger
automation rules. Custom event properties can contain objects and arrays of objects. Use dot notation to access nested properties: parent_property.child_property
.
- API: Custom Event Selectors
- Dashboard: Manage Events
Custom event properties used to be referenced in the $data.events.[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 Support and move over to the simplified namespace for custom event properties.
To minimize battery consumption, custom events are automatically combined and sent batched in the background. For more information, see Tips and Code Samples.
- Simple example
- Here is a simple example that demonstrates how to track a custom event named consumed_content:
iOS
let event = UACustomEvent(name: "consumed_content", 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 event.properties = propertyDictionary // Record the event in analytics event.track()
// Create and name a custom event UACustomEvent *event = [UACustomEvent eventWithName:@"consumed_content"]; // Set 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"]; event.properties = propertyDictionary; // Start tracking the event [event track];
Android
// Create and name an event Builder builder = CustomEvent.newBuilder("consumed_content"); // 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>(); collection.add("string_array_value_1"); collection.add("string_array_value_2"); collection.add("string_array_value_3"); builder.addProperty("collection_property", JsonValue.wrapOpt(collection)); CustomEvent event = builder.build(); // Start tracking the event event.track();
Web
// Create and name an event var event = new sdk.CustomEvent("consumed_content") // Start tracking the event event.track()
- Assigning a value to a custom event
- In this example, you will create an event with a value for advanced analytics reporting:
iOS
// Create and name an event with a value UACustomEvent *event = [UACustomEvent eventWithName:@"event_name" value:@123.12]; // Start tracking the event [event track];
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 UAirship.shared().getAnalytics().addEvent(event);
Web
// Create and name an event with a value var event = new sdk.CustomEvent('event_name', 123.12) // Start tracking the event event.track()
Server-Side Events
Server-side events are sent through the Custom Events API. When you submit an event, you’ll provide the channel IDAn Airship-specific unique identifier used to address a channel instance, e.g., a smartphone, web browser, email address. or Named User IDA customer-provided identifier used for mapping multiple devices and channels to a specific individual. 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.
Server-side events cannot be used to trigger an In-App AutomationMessages cached on users’ devices and displayed when users meet certain conditions within your app, such as viewing a particular screen or opening the app a certain number of times. or SceneA single or multi-screen in-app experience cached on users’ devices and displayed when users meet certain conditions in your app or website, such as viewing a particular screen or when a Custom Event occurs. They can be presented in fullscreen, modal, or embedded format using the default swipe/click mode or as a Story. Scenes can also contain survey questions..
Custom Events used for In-App Automation or Scene triggers must be client-side events. Web Scenes can only use Custom Events tracked using the Web SDK. App Scenes and In-App Automations can only use Custom Events tracked using the Mobile SDK.
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": "your.store/us/en_us/pd/shoe/pid-11046546/pgid-10978234",
"interaction_type": "url",
"properties": {
"description": "Sneaker purchase",
"brand": "Victory Sneakers",
"colors": [
"red",
"blue"
],
"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 Segmentation Tags
Custom events are similar to audience segmentation tags. While tags target users via audience segmentation, custom events inform analytics reporting and trigger automated messages.
For example, a user can be tagged as a purchaser after making a purchase. This user can be segmented later for sending follow-up messages. You may use a custom event to track when the user purchased shoes. This is something that happened, and you may wish to calculate its business impact across all users.
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.
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 your 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 that you can manipulate as needed or import into business intelligence or analytics tools.
See View Attributed Events for detail.
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 so that you can see the full story of conversions following both direct and indirect opens.
We track how each custom event is attributed to a specific push. The following options are available:
- Direct Attribution of Events
- Indirect Attribution of Events
- Unattributed Events
- Direct attribution
- 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 the Direct attribution to that push notification.
- Indirect attribution
- 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 attribution window) and completes a custom event it will be recorded with Indirect attribution to that push notification. If the event is completed after 12 outside of the attribution window, then the event will be categorized as Unattributed.
- Unattributed events
- 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.
Tips and Code Samples
When setting up custom events, remember:
- Start by tracking two to five 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 will be ignored if their names contain more than 255 characters.
- Use consistent naming conventions for your events. We lowercase all incoming events for consistency in reports.
- 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 create a button (named buy-button)
which fires the “bought book” event with a value of 10.99
.
<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>
Our example detects if a page is a landing page, sets the
interaction_type
and interaction_id
if needed, emits an event to the Custom Events
system, and writes debugging information to the DOM.
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.
Injecting the Airship JavaScript Interface
If you have a WebView that exists outside of a Message Center, you can use the following examples to inject the Airship JavaScript interface in to your WebView to enable sending custom events.
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.
iOS Example
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
}
Allowlist Rules
For iOS, the UAURLAllowList controls which URLs the Airship SDK is able to act on. As of SDK 17, all URLs are allowed by default. See: iOS: Configuring Airship.
Android and Fire OS example
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.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new UAWebViewClient())
Allowlist Rules
For Android, the UrlAllowList controls which URLs the Airship SDK is able to act on. As of SDK 17, all URLs are allowed by default. See: Android: Configuring Airship.
Categories