Tracking In-App Events
Track in-app events to analyze campaign performance and measure key performance indicators (KPIs) such as user logins, registrations, tutorial completions, or progression milestones.
Standard Events and Attributes
Using Standard Events
Singular supports standard events that are recognized by ad networks for reporting and optimization. Use standard event names whenever possible for automatic recognition and simplified setup.
Your UA, marketing, or business team should compile the list of events based on your organization's marketing KPIs. Reference the guide How to Track In-App Events: Guide For Singular Attribution Customers for planning.
Each event supports various attributes. See the recommended standard attributes per event for implementation details.
Sending Events
Event Implementation Guidelines
Send events to Singular using the eventJSON or
event methods (we recommend eventJSON for improved
readability).
-
Standard Events: Use the
event's Android name
from the standard events list, e.g.,
sngTutorialComplete - Custom Events: For events unique to your app that don't match standard events, use any descriptive string that complies with the character limitations
Custom Event Limitations:
- Language: Pass event names and attributes in English to ensure compatibility with third-party partners and analytics solutions
- Event Names: Limited to 32 ASCII characters. Non-ASCII strings must be under 32 bytes when converted to UTF-8
- Attributes and Values: Limited to 500 ASCII characters
eventJSON Method
Report user events with additional information using JSONObject format for structured data.
Method Signature:
Singular.eventJSON(String name, JSONObject args)
Note: The args parameter is a JSONObject
containing one or more key-value pairs. Keys must be strings and
values can be any type allowed as a JSONObject value.
Usage Examples
// Example 1: Standard event with recommended 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: Custom event with custom attributes
val att = JSONObject().apply {
put("Points", 500)
put("score", 650)
}
Singular.eventJSON("Bonus Points Earned", att)
// Example 1: Standard event with recommended 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();
}
Singular.eventJSON(Events.sngTutorialComplete.toString(), att);
// Example 2: Custom event with custom attributes
JSONObject att = new JSONObject();
try {
att.put("Points", 500);
att.put("score", 650);
} catch (JSONException e) {
e.printStackTrace();
}
Singular.eventJSON("Bonus Points Earned", att);
event Method
Report user events with or without additional information using variable arguments.
Method Signatures:
Singular.event(String eventName)
Singular.event(String eventName, Object... args)
Note: The args parameter accepts one
or more key-value pairs. Keys must be strings and values can be any
type allowed as a JSONObject value (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.
Usage Examples
// Example 1: Standard event without attributes
Singular.event(Events.sngSubscribe.toString())
// Example 2: Standard event with recommended attributes
Singular.event(Events.sngTutorialComplete.toString(),
Attributes.sngAttrContent.toString(), "Telugu",
Attributes.sngAttrContentId.toString(), "32",
Attributes.sngAttrContentType.toString(), "video",
Attributes.sngAttrSuccess.toString(), "yes"
)
// Example 3: Custom event without attributes
Singular.event("SignUp")
// Example 4: Custom event with custom attribute
Singular.event("Bonus Points Earned", "Points", 500)
// Example 1: Standard event without attributes
Singular.event(Events.sngSubscribe.toString());
// Example 2: Standard event with recommended attributes
Singular.event(Events.sngTutorialComplete.toString(),
Attributes.sngAttrContent.toString(), "Spanish",
Attributes.sngAttrContentId.toString(), 52,
Attributes.sngAttrContentType.toString(), "video",
Attributes.sngAttrSuccess.toString(), 46
);
// Example 3: Custom event without attributes
Singular.event("SignUp");
// Example 4: Custom event with custom attribute
Singular.event("Bonus Points Earned", "Points", 500);
Tracking In-App Revenue
Track revenue from in-app purchases (IAP), subscriptions, and custom revenue sources to measure campaign performance and return on ad spend (ROAS).
Revenue data flows through three channels:
- Interactive Reports: View revenue metrics in the Singular dashboard
- Export Logs: Access detailed ETL data for custom analysis
- Real-Time Postbacks: Send revenue events to external platforms
Revenue Event Limitations:
- Event Names: Custom revenue event names are limited to 32 ASCII characters (or 32 bytes for non-ASCII when converted to UTF-8)
- Attributes: Event attribute names and values are limited to 500 ASCII characters
- Currency Codes: Must be ALL CAPS and follow the three-letter ISO 4217 standard (e.g., USD, EUR, INR)
Best Practices
- Standard Naming: Use Singular's standard event and attribute naming convention
- Language: Send custom revenue event names in English for improved ad network postback compatibility
- Non-Zero Amounts: Only send revenue events when the amount is greater than or less than 0
Non-Subscription In-App Purchase
Purchase Object Integration
Pass the
Purchase
object from Google Billing Library to the revenue or
customRevenue methods for enriched reporting and transaction
validation.
Benefits:
- Rich Data: Singular receives complete transaction details for comprehensive reports
- Fraud Prevention: Transaction receipts enable validation to combat in-app fraud
Notes:
-
Custom Event Names: The
customRevenuemethod accepts custom event names for breaking down revenue by event type in reports - Currency Conversion: Revenue in different currencies is automatically converted to your organization's preferred currency
revenue Method with Purchase
Send a revenue event with the Purchase object for automatic validation and enriched data.
Method Signature:
Singular.revenue(String currency, double amount, Object purchase)
Usage Example
Singular.revenue("USD", 5.50, purchase)
Singular.revenue("USD", 5.50, purchase);
customRevenue Method with Purchase
Send a revenue event with a custom name and the Purchase object for categorized revenue tracking.
Method Signature:
Singular.customRevenue(String eventName, String currency, double amount, Object purchase)
Usage Example
Singular.customRevenue("MyCustomRevenue", "USD", 5.50, purchase)
Singular.customRevenue("MyCustomRevenue", "USD", 5.50, purchase);
Subscription Revenue
Subscription Event Implementation
Track subscription purchases and renewals to gain insights into user behavior and recurring revenue generation.
Implementation Guide: Review the comprehensive Subscription Event Technical Implementation Guide for detailed instructions on tracking subscriptions with the Singular SDK.
Custom Revenue without Purchase Validation
Manual Revenue Tracking
Track revenue by passing currency, amount, and optional product details without the Purchase object. Note that this method does not provide transaction receipts for validation.
Important: When using these methods, Singular cannot validate transactions. We strongly recommend using the Purchase object methods described above whenever possible.
revenue Method without Purchase
Send revenue events with currency, amount, and optional product details.
Method 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
val attributes = mutableMapOf<String, Any>().apply {
put("product_id", "com.app.premium")
put("transaction_id", "T12345")
put("quantity", 1)
put("is_trial", false)
}
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
Map<String, 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);
Singular.revenue("USD", 9.99, attributes);
customRevenue Method without Purchase
Send custom revenue events with a specified event name, currency, amount, and optional transaction attributes.
Method 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
val attributes = mutableMapOf<String, Any>().apply {
put("product_id", "com.app.premium")
put("transaction_id", "T12345")
put("quantity", 1)
put("is_trial", false)
}
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
Map<String, 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);
Singular.customRevenue("MyCustomRevenue", "USD", 9.99, attributes);
Hybrid Event Tracking (Advanced)
Send all events and revenue through the Singular SDK integrated into your app for optimal attribution. However, Singular can collect events from other sources when necessary.
Events sent outside the Singular SDK must comply with Singular's Server-to-Server Event documentation and provide matching device identifiers for correct attribution.
Important:
Discrepancies occur when device identifiers in server-to-server requests don't match identifiers recorded by the Singular SDK:
- Early Events: If an event arrives before the Singular SDK records the device identifier, the event becomes the "first session" for an unknown device, resulting in organic attribution
- Mismatched Identifiers: If the Singular SDK recorded a different device identifier than the one in the server-to-server request, the event will be attributed incorrectly
Hybrid Event Tracking Guides
Sending Events from an Internal Server
Collect revenue data from your internal server to analyze campaign performance and ROI.
Requirements:
- Capture Device Identifiers: During in-app registration or login events, capture and pass device identifiers, then store this data with the User ID on your server. Update identifiers when users generate new app sessions to ensure correct attribution
- Platform-Specific Identifiers: Send server-side events with the device identifier matching the platform (e.g., IDFA or IDFV for iOS devices)
- Real-Time Updates: Use the Singular Internal BI postback mechanism to push events in real-time to your endpoint. See the Internal BI Postback FAQ
- Implementation Details: Review the "Tracking Revenue" section in the Server-to-Server Integration guide
Sending Events from a Revenue Provider
Integrate third-party revenue providers like RevenueCat or adapty to send purchase and subscription revenue to Singular.
Supported Providers:
- RevenueCat: Learn more in the RevenueCat documentation
- adapty: Learn more in the adapty documentation
Sending Events from Segment
Enable Segment to send events to Singular in parallel with the Singular SDK by adding a "Cloud-Mode" destination in Segment.
Follow the implementation guide Singular-Segment Integration for detailed setup instructions.