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.
Event Implementation Guidelines
Event Naming Best Practices
Send events to Singular using the SendEvent and
SendEventWithArgs methods with descriptive event names and
optional attributes for enriched data.
Event Name Recommendations:
- 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
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.
Sending Events
Simple Event Tracking
Send basic user events to Singular with a custom event name to track user actions like logins, tutorial completions, or level ups.
// Send an event without any parameters, just a name
USingularSDKBPLibrary::SendEvent(TEXT("Login"));
// Example: Track tutorial completion
USingularSDKBPLibrary::SendEvent(TEXT("TutorialComplete"));
// Example: Track level progression
USingularSDKBPLibrary::SendEvent(TEXT("LevelUp"));
Method Signature:
static void SendEvent(FString eventName);
Event Tracking with Attributes
Send user events with additional custom parameters to capture contextual information like level numbers, item IDs, or user actions.
// Example 1: Login with user tier
TMap<FString, FString> LoginArgs;
LoginArgs.Add(TEXT("user_tier"), TEXT("premium"));
LoginArgs.Add(TEXT("login_method"), TEXT("email"));
USingularSDKBPLibrary::SendEventWithArgs(TEXT("Login"), LoginArgs);
// Example 2: Tutorial completion with metadata
TMap<FString, FString> TutorialArgs;
TutorialArgs.Add(TEXT("tutorial_name"), TEXT("BasicControls"));
TutorialArgs.Add(TEXT("completion_time"), TEXT("120"));
TutorialArgs.Add(TEXT("difficulty"), TEXT("easy"));
USingularSDKBPLibrary::SendEventWithArgs(TEXT("TutorialComplete"), TutorialArgs);
// Example 3: Level progression with game state
TMap<FString, FString> LevelArgs;
LevelArgs.Add(TEXT("level_number"), TEXT("5"));
LevelArgs.Add(TEXT("character_class"), TEXT("warrior"));
LevelArgs.Add(TEXT("total_playtime"), TEXT("3600"));
USingularSDKBPLibrary::SendEventWithArgs(TEXT("LevelUp"), LevelArgs);
// Example 4: Item purchase with details
TMap<FString, FString> PurchaseArgs;
PurchaseArgs.Add(TEXT("item_id"), TEXT("sword_legendary_001"));
PurchaseArgs.Add(TEXT("item_category"), TEXT("weapons"));
PurchaseArgs.Add(TEXT("item_rarity"), TEXT("legendary"));
USingularSDKBPLibrary::SendEventWithArgs(TEXT("ItemPurchased"), PurchaseArgs);
Method Signature:
static void SendEventWithArgs(FString eventName, TMap<FString, FString> args);
Best Practice: Use descriptive attribute names that clearly indicate the data being tracked. This improves data analysis and makes reports more understandable for your marketing team.
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
Currency Conversion: Revenue in different currencies is automatically converted to your organization's preferred currency set in your Singular account.
Revenue Event Guidelines
Revenue Event Limitations
Revenue Event Requirements:
- 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, GBP, JPY)
Sending Revenue Events
Simple Revenue Tracking
Send revenue events to Singular with event name, currency code, and transaction amount to track basic purchase data.
// Example 1: Basic purchase tracking
USingularSDKBPLibrary::SendRevenue(TEXT("Purchase Completed"), TEXT("USD"), 9.99f);
// Example 2: Subscription purchase
USingularSDKBPLibrary::SendRevenue(TEXT("SubscriptionPurchase"), TEXT("USD"), 29.99f);
// Example 3: In-game currency purchase
USingularSDKBPLibrary::SendRevenue(TEXT("CoinPackagePurchase"), TEXT("EUR"), 4.99f);
// Example 4: Premium item purchase
USingularSDKBPLibrary::SendRevenue(TEXT("PremiumItemPurchase"), TEXT("GBP"), 19.99f);
Method Signature:
static void SendRevenue(FString eventName, FString currency, float amount);
Note: Pass currency as a three-letter ISO 4217 currency code, such as "USD", "EUR", "INR".
Revenue Tracking with Attributes
Send revenue events with additional custom parameters to capture transaction details like product SKUs, categories, or promo codes.
// Example 1: Revenue with product details
TMap<FString, FString> PurchaseArgs;
PurchaseArgs.Add(TEXT("product_id"), TEXT("coin_pack_100"));
PurchaseArgs.Add(TEXT("product_name"), TEXT("100 Coin Pack"));
PurchaseArgs.Add(TEXT("product_category"), TEXT("currency"));
USingularSDKBPLibrary::SendRevenueWithArgs(
TEXT("Purchase Completed"),
TEXT("USD"),
4.99f,
PurchaseArgs
);
// Example 2: Subscription with billing details
TMap<FString, FString> SubArgs;
SubArgs.Add(TEXT("subscription_tier"), TEXT("premium"));
SubArgs.Add(TEXT("billing_period"), TEXT("monthly"));
SubArgs.Add(TEXT("trial_period"), TEXT("false"));
SubArgs.Add(TEXT("renewal_count"), TEXT("3"));
USingularSDKBPLibrary::SendRevenueWithArgs(
TEXT("SubscriptionRenewal"),
TEXT("USD"),
9.99f,
SubArgs
);
// Example 3: Purchase with promotional discount
TMap<FString, FString> PromoArgs;
PromoArgs.Add(TEXT("product_id"), TEXT("bundle_mega_001"));
PromoArgs.Add(TEXT("promo_code"), TEXT("SUMMER2025"));
PromoArgs.Add(TEXT("discount_amount"), TEXT("5.00"));
PromoArgs.Add(TEXT("original_price"), TEXT("19.99"));
USingularSDKBPLibrary::SendRevenueWithArgs(
TEXT("BundlePurchase"),
TEXT("USD"),
14.99f,
PromoArgs
);
// Example 4: IAP with transaction metadata
TMap<FString, FString> IAPArgs;
IAPArgs.Add(TEXT("platform"), TEXT("google_play"));
IAPArgs.Add(TEXT("transaction_id"), TEXT("GPA.1234-5678-90AB"));
IAPArgs.Add(TEXT("item_type"), TEXT("consumable"));
IAPArgs.Add(TEXT("user_level"), TEXT("42"));
USingularSDKBPLibrary::SendRevenueWithArgs(
TEXT("IAP_Consumable"),
TEXT("USD"),
2.99f,
IAPArgs
);
Method Signature:
static void SendRevenueWithArgs(FString eventName, FString currency, float amount, TMap<FString, FString> args);
Best Practice: Include as many transaction details as possible in the attributes to enable granular revenue analysis and optimize marketing spend based on product performance.
Revenue Tracking Best Practices
Recommended Attributes
Include these common attributes in your revenue events for comprehensive transaction tracking:
- product_id: Unique identifier for the purchased item or SKU
- product_name: Human-readable product name
- product_category: Category or type of product (e.g., "currency", "weapons", "subscription")
- transaction_id: Unique transaction identifier from the payment platform
- platform: Purchase platform (e.g., "app_store", "google_play", "steam")
- promo_code: Promotional code used for discounts
- user_tier: User subscription or membership tier
- quantity: Number of items purchased
Implementation Tips:
- Non-Zero Amounts: Only send revenue events when the amount is greater than or less than 0
- Consistent Naming: Use consistent attribute names across all revenue events for easier analysis
- Test Purchases: Use small amounts (e.g., $0.01) for testing to avoid skewing production revenue data
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 Attribution Considerations:
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 Options
Sending Events from an Internal Server
Collect revenue data from your internal server to analyze campaign performance and ROI when client-side tracking is insufficient.
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, GAID for Android 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 Revenue Providers
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
Note: When using revenue providers, ensure they're configured to send the correct device identifiers that match what the Singular SDK captures to maintain attribution accuracy.
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.
Configuration Note: Segment integration requires Cloud-Mode destination setup to ensure events are properly routed to Singular with the correct device identifiers and attribution context.