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 event or
eventWithArgs methods for tracking user actions and behaviors.
-
Standard Events: Use the
event's iOS name
from the standard events list, e.g.,
EVENT_SNG_LOGIN - 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
event Method
Report user events without additional information for simple tracking scenarios.
Method Signature:
+ (void)event:(NSString *)name;
Usage Examples
// Example 1: Standard event
Singular.event(EVENT_SNG_LOGIN)
// Example 2: Custom event
Singular.event("signup")
// Example 1: Standard event
[Singular event:EVENT_SNG_LOGIN];
// Example 2: Custom event
[Singular event:@"signup"];
eventWithArgs Method
Report user events with additional information using dictionary format for structured data.
Method Signature:
+ (void)event:(NSString *)name withArgs:(NSDictionary *)args;
Note: The args parameter is an NSDictionary
containing one or more key-value pairs. Keys must be strings and
values can be any type allowed in an NSDictionary.
Usage Examples
// Example 1: Standard event with recommended attributes
var dic: [AnyHashable: Any] = [:]
dic[ATTRIBUTE_SNG_ATTR_CONTENT_TYPE] = "video"
dic[ATTRIBUTE_SNG_ATTR_CONTENT_ID] = "32"
dic[ATTRIBUTE_SNG_ATTR_CONTENT] = "Telugu"
dic[ATTRIBUTE_SNG_ATTR_SUCCESS] = "yes"
Singular.event(EVENT_SNG_TUTORIAL_COMPLETE, withArgs: dic)
// Example 2: Custom event with custom attributes
var bonusData: [AnyHashable: Any] = [
"level": 10,
"points": 500
]
Singular.event("Bonus Points Earned", withArgs: bonusData)
// Example 1: Standard event with recommended attributes
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"video" forKey:ATTRIBUTE_SNG_ATTR_CONTENT_TYPE];
[dic setValue:@"32" forKey:ATTRIBUTE_SNG_ATTR_CONTENT_ID];
[dic setValue:@"Telugu" forKey:ATTRIBUTE_SNG_ATTR_CONTENT];
[dic setValue:@"yes" forKey:ATTRIBUTE_SNG_ATTR_SUCCESS];
[Singular event:EVENT_SNG_TUTORIAL_COMPLETE withArgs:dic];
// Example 2: Custom event with custom attributes
NSMutableDictionary *bonusData = [[NSMutableDictionary alloc] init];
[bonusData setValue:@10 forKey:@"level"];
[bonusData setValue:@500 forKey:@"points"];
[Singular event:@"Bonus Points Earned" withArgs:bonusData];
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
SKPaymentTransaction Integration
Pass the
SKPaymentTransaction
object from StoreKit to the iapComplete method 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:
-
Required Object: The
iapCompletemethod requires the SKPaymentTransaction object - Currency Conversion: Revenue in different currencies is automatically converted to your organization's preferred currency
-
Custom Event Names: Use the
withNameparameter to categorize revenue by event type in reports
iapComplete Method
Send a revenue event with the SKPaymentTransaction object for automatic validation and enriched data.
Method Signatures:
+ (void)iapComplete:(id)transaction;
+ (void)iapComplete:(id)transaction withName:(NSString *)name;
Usage Examples
// Get the SKPaymentTransaction object
let transaction: SKPaymentTransaction = ...
// Send transaction without custom event name
Singular.iapComplete(transaction)
// Send transaction with custom event name
Singular.iapComplete(transaction, withName: "MyCustomRevenue")
// Get the SKPaymentTransaction object
SKPaymentTransaction *transaction = ...;
// Send transaction without custom event name
[Singular iapComplete:transaction];
// Send transaction with custom event name
[Singular iapComplete:transaction withName:@"MyCustomRevenue"];
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 SKPaymentTransaction 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 SKPaymentTransaction methods described above whenever possible.
revenue Method
Send revenue events with currency, amount, and optional product details.
Method Signatures:
+ (void)revenue:(NSString *)currency amount:(double)amount;
+ (void)revenue:(NSString *)currency
amount:(double)amount
productSKU:(NSString *)productSKU
productName:(NSString *)productName
productCategory:(NSString *)productCategory
productQuantity:(int)productQuantity
productPrice:(double)productPrice;
+ (void)revenue:(NSString *)currency
amount:(double)amount
withAttributes:(NSDictionary *)attributes;
Usage Examples
// Without product details
Singular.revenue("USD", amount: 1.99)
// With product details
Singular.revenue("EUR",
amount: 5.00,
productSKU: "SKU1928375",
productName: "Reservation Fee",
productCategory: "Fee",
productQuantity: 1,
productPrice: 5.00)
// With product details in a dictionary
var dic: [AnyHashable: Any] = [:]
dic[ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION] = "100% Organic Cotton Mixed Plaid Flannel Shirt"
dic[ATTRIBUTE_SNG_ATTR_ITEM_PRICE] = "$69.95"
dic[ATTRIBUTE_SNG_ATTR_RATING] = "5 Star"
dic[ATTRIBUTE_SNG_ATTR_SEARCH_STRING] = "Flannel Shirt"
Singular.revenue("USD", amount: 19.95, withAttributes: dic)
// Without product details
[Singular revenue:@"USD" amount:1.99];
// With product details
[Singular revenue:@"EUR"
amount:5.00
productSKU:@"SKU1928375"
productName:@"Reservation Fee"
productCategory:@"Fee"
productQuantity:1
productPrice:5.00];
// With product details in a dictionary
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"100% Organic Cotton Mixed Plaid Flannel Shirt"
forKey:ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION];
[dic setValue:@"$69.95" forKey:ATTRIBUTE_SNG_ATTR_ITEM_PRICE];
[dic setValue:@"5 Star" forKey:ATTRIBUTE_SNG_ATTR_RATING];
[dic setValue:@"Flannel Shirt" forKey:ATTRIBUTE_SNG_ATTR_SEARCH_STRING];
[Singular revenue:@"USD" amount:19.99 withAttributes:dic];
customRevenue Method
Send custom revenue events with a specified event name, currency, amount, and optional transaction attributes.
Method Signatures:
+ (void)customRevenue:(NSString *)eventName
currency:(NSString *)currency
amount:(double)amount;
+ (void)customRevenue:(NSString *)eventName
currency:(NSString *)currency
amount:(double)amount
productSKU:(NSString *)productSKU
productName:(NSString *)productName
productCategory:(NSString *)productCategory
productQuantity:(int)productQuantity
productPrice:(double)productPrice;
+ (void)customRevenue:(NSString *)eventName
currency:(NSString *)currency
amount:(double)amount
withAttributes:(NSDictionary *)attributes;
Usage Examples
// Without product details
Singular.customRevenue("MyCustomRevenue", currency: "USD", amount: 1.99)
// With product details
Singular.customRevenue("MyCustomRevenue",
currency: "EUR",
amount: 5.00,
productSKU: "SKU1928375",
productName: "Reservation Fee",
productCategory: "Fee",
productQuantity: 1,
productPrice: 5.00)
// With product details in a dictionary
var dic: [AnyHashable: Any] = [:]
dic[ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION] = "100% Organic Cotton Mixed Plaid Flannel Shirt"
dic[ATTRIBUTE_SNG_ATTR_ITEM_PRICE] = "$69.95"
dic[ATTRIBUTE_SNG_ATTR_RATING] = "5 Star"
dic[ATTRIBUTE_SNG_ATTR_SEARCH_STRING] = "Flannel Shirt"
Singular.customRevenue("CustomRevenueWithArgsDic",
currency: "USD",
amount: 44.99,
withAttributes: dic)
// Without product details
[Singular customRevenue:@"MyCustomRevenue" currency:@"USD" amount:1.99];
// With product details
[Singular customRevenue:@"MyCustomRevenue"
currency:@"EUR"
amount:5.00
productSKU:@"SKU1928375"
productName:@"Reservation Fee"
productCategory:@"Fee"
productQuantity:1
productPrice:5.00];
// With product details in a dictionary
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setValue:@"100% Organic Cotton Mixed Plaid Flannel Shirt"
forKey:ATTRIBUTE_SNG_ATTR_ITEM_DESCRIPTION];
[dic setValue:@"$69.95" forKey:ATTRIBUTE_SNG_ATTR_ITEM_PRICE];
[dic setValue:@"5 Star" forKey:ATTRIBUTE_SNG_ATTR_RATING];
[dic setValue:@"Flannel Shirt" forKey:ATTRIBUTE_SNG_ATTR_SEARCH_STRING];
[Singular customRevenue:@"MyCustomRevenue"
currency:@"USD"
amount:44.99
withAttributes:dic];
StoreKit2 Support
StoreKit2 Revenue Tracking
For apps using the StoreKit2 framework, use the customRevenue
method with transaction and product JSON representations.
Important: Purchase validation is not supported for StoreKit2. The methods require jsonRepresentation format for transaction and product objects.
Method Signatures:
+ (void)customRevenue:(NSData *)transactionJsonRepresentation
productJsonRepresentation:(NSData *)productJsonRepresentation;
+ (void)customRevenue:(NSString *)eventName
transactionJsonRepresentation:(NSData *)transactionJsonRepresentation
productJsonRepresentation:(NSData *)productJsonRepresentation;
Usage Examples
// Fetch transaction and product from StoreKit2
let transaction = ... // Valid StoreKit2 transaction
let product = ... // Valid StoreKit2 product
// Custom Revenue with default __iap__ event name
Singular.customRevenue(
transactionJsonRepresentation: transaction.jsonRepresentation,
productJsonRepresentation: product.jsonRepresentation)
// Custom Revenue with custom event name
Singular.customRevenue(
"PaymentSuccess",
transactionJsonRepresentation: transaction.jsonRepresentation,
productJsonRepresentation: product.jsonRepresentation)
// Fetch transaction and product from StoreKit2
SKTransaction *transaction = ...; // Valid StoreKit2 transaction
SKProduct *product = ...; // Valid StoreKit2 product
// Convert JSON representations to NSData
NSData *transactionData = [transaction.jsonRepresentation
dataUsingEncoding:NSUTF8StringEncoding];
NSData *productData = [product.jsonRepresentation
dataUsingEncoding:NSUTF8StringEncoding];
// Custom Revenue with default __iap__ event name
[Singular customRevenue:transactionData
productJsonRepresentation:productData];
// Custom Revenue with custom event name
[Singular customRevenue:@"PaymentSuccess"
transactionJsonRepresentation:transactionData
productJsonRepresentation:productData];
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.