Tracking In-app Events
Singular can collect data about in-app events to help analyze the performance of your campaigns and measure KPIs. For example, your organization may want to collect data about user logins, registrations, tutorial completions, or leveling up in a gaming app.
Standard Events and Attributes
Singular supports a variety of standard events. These commonly used events are often supported by ad networks for reporting and optimization. Another advantage is that when you use standard event names, Singular recognizes them automatically and adds them to the Events list without you having to define them manually. We recommend using standard events whenever possible.
The list of events sent to Singular (with the accompanying attributes) should be compiled by the UA/marketing/business team based on your organization's marketing KPIs. The business team can follow the guide at How to Track In-App Events: Guide For Singular Attribution Customers.
With each event you track, you can pass various attributes. See the recommended standard attributes per event.
Sending Events
In your code, send events to Singular using the eventJSON or event methods (we recommend eventJSON for readability).
- For standard events, use the event's Android name as it appears in the list of standard events and attributes for the Android SDK, e.g., sngTutorialComplete. See the code examples below.
- If you send any custom events (events that your organization wants to measure that do not match any of Singular's standard events), use any string you like that complies with the limitations.
Custom Event Limitations:
- We highly recommend passing event names and attributes in English to guarantee compatibility with third-party partners and analytics solutions if you plan to use them.
- Event names are limited to 32 ASCII characters. Strings in non-ASCII characters have to be under 32 bytes once converted to UTF-8.
- Attributes and values are limited to 500 ASCII characters.
Singular.eventJSON Method
Report a user event to Singular with additional information in JSONObject format.
Signatures
Singular.eventJSON(String name, JSONObject args)
Usage Examples
// Example 1:
// Send the standard event sng_tutorial_complete with the
// recommended standard attributes
JSONObject att = new JSONObject();
try {
att.put(Attributes.sngAttrContent.toString(), "Telugu");
att.put(Attributes.sngAttrContentId.toString(), 32);
att.put(Attributes.sngAttrContentType.toString(), "video");
att.put(Attributes.sngAttrSuccess.toString(), 92);
} catch (JSONException e) {
e.printStackTrace(); // Or log the exception
}
Singular.eventJSON(Events.sngTutorialComplete.toString(), att);
// Example 2:
// Send a custom event named "bonus_points_earned" with custom attributes
JSONObject att = new JSONObject();
try {
att.put("Points", 500);
att.put("score", 650);
} catch (JSONException e) {
e.printStackTrace(); // Or log the exception
}
Singular.eventJSON("Bonus Points Earned", att);
// Example 1:
// Send the standard event sng_tutorial_complete with the
// recommended standard attributes
val att = JSONObject().apply {
put(Attributes.sngAttrContent.toString(), "Telugu")
put(Attributes.sngAttrContentId.toString(), 32)
put(Attributes.sngAttrContentType.toString(), "video")
put(Attributes.sngAttrSuccess.toString(), 75)
}
Singular.eventJSON(Events.sngTutorialComplete.toString(), att)
// Example 2:
// Send a custom event named "bonus_points_earned" with custom attributes
val att = JSONObject().apply {
put("Points", 500)
put("score",650)
}
Singular.eventJSON("Bonus Points Earned", att)
Singular.event Method
Report a user event to Singular with or without additional information.
Signatures
Singular.event(String eventName)
Singular.event(String eventName, Object... args)
Note: 'args' is one or more key-value pairs (see the example below). The key is a string and the value can be any type that's allowed as a JSONObject value (i.e., JSONObject, JSONArray, String, Boolean, Integer, Long, Double or NULL).
The 'args' list must contain an even number of elements or the event will be rejected by Singular.
Usage Examples
// Example 1:
// Send the standard event "Subscribe" (sng_subscribe) without any attributes
Singular.event(Events.sngSubscribe.toString());
// Example 2:
// Send the standard event "sng_tutorial_complete" with the
//recommended standard attributes
Singular.event(Events.sngTutorialComplete.toString(),
Attributes.sngAttrContent.toString(), "Spanish",
Attributes.sngAttrContentId.toString(), 52,
Attributes.sngAttrContentType.toString(), "video",
Attributes.sngAttrSuccess.toString(), 46
);
// Example 3:
// Send a custom event named "SignUp" without any custom attributes
Singular.event("SignUp");
// Example 4:
// Send a custom event named "bonus_points_earned" with a custom attribute
Singular.event("Bonus Points Earned", "Points", 500);
// Example 1:
// Send the standard event "Subscribe" (sng_subscribe) with no attributes
Singular.event(Events.sngSubscribe.toString())
// Example 2:
// Send the standard event sng_tutorial_complete with the
// recommended standard attributes
Singular.event(Events.sngTutorialComplete.toString(),
Attributes.sngAttrContent.toString(), "Telugu",
Attributes.sngAttrContentId.toString(), "32",
Attributes.sngAttrContentType.toString(), "video",
Attributes.sngAttrSuccess.toString(), "yes"
)
// Example 3:
// Send a custom event named "SignUp" with no custom attributes
Singular.event("SignUp")
// Example 4:
// Send a custom event named "bonus_points_earned" with a custom attribute
Singular.event("Bonus Points Earned", "Points", 500)
Tracking In-app Revenue
Singular captures revenue events from in-app purchases (IAP), subscriptions, and custom revenue to measure campaign performance and return on ad spend (ROAS). The revenue data becomes available through three key channels:
- Interactive reports in the Singular dashboard
- Detailed export logs and ETL data destinations for custom analysis
- Real-time postbacks to external platforms
This comprehensive revenue tracking enables data-driven decisions about marketing spend and campaign optimization while providing flexibility in how you consume and analyze the data.
- If Custom Revenue Event Names are used the Custom Revenue Event Names are limited to 32 ASCII characters. For non-ASCII characters, the limit is 32 bytes once converted to UTF-8.
- Event attribute names and attribute values are limited to 500 ASCII characters.
-
Currency codes must be ALL CAPS and adhere to the three-letter ISO 4217 currency code:
USD, EUR, INR
Best Practice
- Singular recommends passing events using Singular's standard event and attribute naming convention.
- If Custom Revenue Event Names are used they should be sent in English to improve compatibility with Ad Network postbacks.
- Revenue Events should only be sent to Singular when the Revenue Amount is greater than or less than 0.
Non-Subscription In-App Purchase
To report revenue events to Singular, pass the Purchase object received from the Google Billing Library into the revenue or customRevenue SDK methods. This has two advantages:
- Singular gets all the details of the transaction, which enriches your Singular reports.
- Singular gets the transaction receipt from Google which can be used to validate the transaction in the context of fighting in-app fraud.
Notes:
- customRevenue allows you to pass a custom event name, so that you'll be able to view revenue in Singular reports broken down by the different types of revenue events.
- Any revenue reported in a different currency will be auto-converted to your organization's preferred currency, as set in your Singular account.
revenue Method
Send a revenue event to Singular with the Purchase object.
Signatures
Singular.revenue(String currency, double amount, Object purchase)
Usage Examples
Singular.revenue("USD", 5.50, purchase);
Singular.revenue("USD", 5.50, purchase)
customRevenue Method
Send a revenue event to Singular with a custom event name and the Purchase object.
Signatures
Singular.customRevenue(String eventName, String currency, double amount, Object purchase)
Usage Examples
Singular.customRevenue("MyCustomRevenue", "USD", 5.50, purchase);
Singular.customRevenue("MyCustomRevenue", "USD", 5.50, purchase)
Subscription Revenue
Tracking Subscriptions:
Singular enables you to track your subscriptions and renewals within your app, providing insights into user behavior and revenue generation. Review our comprehensive guide on how to implement subscription events using the Singular SDK. [Subscription Event Technical Implementation Guide]
Custom Revenue without Purchase Validation
While we strongly recommend reporting revenue events the way described above, you can also use revenue and customRevenue without passing the purchase object. Instead, you pass the currency and amount of the transaction, and optional product details.
The customRevenue method also lets you pass a custom event name.
Note that if you use these methods, Singular does not get the transaction receipt and cannot validate the transaction.
revenue Method
Send a revenue event to Singular with the revenue amount, currency, and optional details.
Signatures
Singular.revenue(String currency, double amount)
Singular.revenue(String currency, double amount, String productSKU, String productName, String productCategory, int productQuantity, double productPrice)
Singular.revenue(String currency, double amount, Map<String, Object> attributes)
Usage Examples
Without Product Details
Singular.revenue("USD", 5.50);
With Product Details
Singular.revenue("EUR", 5.00, "SKU1928375", "Reservation Fee", "Fee" , 1, 5.00);
With Product Details in an Attribute Map
Map<string, object="Object"> attributes = new HashMap<>();
attributes.put("product_id", "com.app.premium");
attributes.put("transaction_id", "T12345");
attributes.put("quantity", 1);
attributes.put("is_trial", false);
// Call the revenue method
Singular.revenue("USD", 9.99, attributes);
Without Product Details
Singular.revenue("USD", 5.50)
With Product Details
Singular.revenue("EUR", 5.00, "SKU1928375", "Reservation Fee", "Fee" , 1, 5.00)
With Product Details in an Attribute Map
val attributes = mutableMapOf<String, Any>().apply {
put("product_id", "com.app.premium")
put("transaction_id", "T12345")
put("quantity", 1)
put("is_trial", false)
}
// Call the revenue method
Singular.revenue("USD", 9.99, attributes)
customRevenue Method
Send custom revenue events to Singular by specifying the event name, revenue amount, currency code, and any additional transaction attributes. Singular processes these events to track in-app revenue.
Signatures
Singular.customRevenue(String eventName, String currency, double amount)
Singular.customRevenue(String eventName, String currency, double amount, String productSKU, String productName, String productCategory, int productQuantity, double productPrice)
Singular.customRevenue(String eventName, String currency, double amount, Map<String, Object> attributes)
Usage Examples
Without Product Details
Singular.customRevenue("MyCustomRevenue", "USD", 5.50);
With Product Details
Singular.customRevenue("MyCustomRevenue", "EUR", 5.00, "SKU1928375", "Reservation Fee", "Fee" , 1, 5.00);
With Product Details in an Attribute Map
Map<string, object="Object"> attributes = new HashMap<>();
attributes.put("product_id", "com.app.premium");
attributes.put("transaction_id", "T12345");
attributes.put("quantity", 1);
attributes.put("is_trial", false);
// Call the revenue method
Singular.customRevenue("MyCustomRevenue", "USD", 9.99, attributes);
Without Product Details
Singular.customRevenue("MyCustomRevenue", "USD", 5.50)
With Product Details
Singular.customRevenue("MyCustomRevenue", "EUR", 5.00, "SKU1928375", "Reservation Fee", "Fee" , 1, 5.00)
With Product Details in an Attribute Map
val attributes = mutableMapOf<String, Any>().apply {
put("product_id", "com.app.premium")
put("transaction_id", "T12345")
put("quantity", 1)
put("is_trial", false)
}
// Call the revenue method
Singular.customRevenue("MyCustomRevenue", "USD", 9.99, attributes)
Hybrid Event Tracking (Advanced)
Singular recommends sending all events and revenue through the Singular SDK integrated into your app. However, Singular can collect events and revenue from other sources.
Any event NOT sent from the Singular SDK must comply with Singular's Server-to-Server Event documentation requirements and provide the matching device identifier to correctly attribute an event.
Important:
Discrepancies will occur if device identifiers used on Server-to-Server event requests do not have a matching device identifier in Singular. Be aware of the following possibilities:
- If an event request is received "before" the Singular SDK has recorded the device identifier, from an App Session, then the event request will be considered the "first session" for the unknown device, and Singular will attribute the device as an organic attribution.
- If the Singular SDK did record a device identifier, but the Singular SDK identifier differs from the device identifier specified in the Server-to-Server Event request then the event will be attributed incorrectly.
Hybrid Event Tracking Guides
Sending Events from an Internal Server
Singular can collect data about revenue from your Server to help analyze the performance and ROI of your campaigns.
Requirements:
- From an in-app Registration or Login Event, capture and pass the device identifiers and store this data with the User ID on your server. Because device identifiers may change for a user, be sure to update the identifiers when a user generates an app session. This guarantees the server-side event will be attributed to the correct device.
- Server-side events are platform specific and should only be sent with the device identifier matching the device platform (e.g., IDFA or IDFV for iOS devices).
- You can use the Singular Internal BI postback mechanism to push an event in real time to your internal endpoint so that you can update the data set on the server side. See the Internal BI Postback FAQ.
- Review the "Tracking Revenue" section in the Server-to-Server Integration guide for details.
Sending Events from a Revenue Provider
Third-party providers like RevenueCat or adapty can provide Purchase and Subscription Revenue to Singular.
Follow the links below for details on how to enable these partners.
Sending Events from Segment
To enable Segment to send events to Singular, in parallel with the Singular SDK, you must add a "Cloud-Mode" Destination in Segment. Follow our guide HERE.