Unity SDK - Ad Revenue Tracking

Ad Revenue Attribution

Track ad revenue from mediation platforms and attribute it to the marketing campaigns that acquired your users, providing complete ROI visibility across campaign costs, in-app purchases, and advertising monetization.

Overview

What Is Ad Revenue Attribution

Ad Revenue Attribution connects mobile app advertising revenue to the user acquisition campaigns that drove app installs, enabling you to measure true campaign profitability including ad monetization.

Key Benefits:

  • Unified ROI View: See campaign costs, in-app revenue, and ad revenue in a single dashboard
  • Campaign Optimization: Send ad revenue data back to ad networks to improve bidding and targeting
  • LTV Measurement: Calculate complete user lifetime value including advertising monetization

Data Sources: Ad revenue data typically comes from your mediation platform (e.g., AdMob, AppLovin MAX, IronSource) at either the user level or impression level. Singular supports multiple integration methods to receive this data.

Learn More: See the Ad Revenue Attribution FAQ for comprehensive details on setup, reporting, and troubleshooting.


Implementation Requirements

Critical Guidelines

Data Accuracy Is Critical:

  1. Currency Codes: Use three-letter ISO 4217 currency codes (e.g., USD, EUR, INR). Many mediation platforms report in USD—verify your platform's currency before implementation
  2. Validate Before Sending: Always validate revenue and currency data before calling SingularSDK.AdRevenue(). Incorrect data cannot be corrected after submission
  3. Platform Differences: AdMob reports revenue in micros on Unity and Android (divide by 1,000,000) but in standard units on iOS. Check your platform's documentation

Setup Steps

Follow these steps to implement ad revenue attribution:

  1. Update SDK: Ensure you're using the latest Singular SDK version
  2. Choose Integration: Select the mediation platform integration below that matches your setup
  3. Implement Callbacks: Add platform-specific paid event listeners to capture revenue data
  4. Validate Data: Test revenue reporting and verify data appears in Singular dashboard

Platform Integrations

AdMob Integration

Track ad revenue from Google AdMob using the paid event listener for impression-level revenue reporting.

Requirements:

Platform Revenue Reporting: AdMob reports revenue differently by platform. Ad revenue of $0.005 will be returned as 5000 on Unity and Android platforms but as 0.005 on iOS. For iOS, send 0.005 directly to the Singular SDK. On other platforms, convert adValue from micros to dollars before sending it to Singular.

Implementation

Register an OnAdPaid event handler when loading ads to capture revenue data and send it to Singular.

C#
using UnityEngine;
using Singular;
using GoogleMobileAds.Api;

public class AdMobRevenueTracking : MonoBehaviour
{
    private const string AD_UNIT_ID = "YOUR_AD_UNIT_ID";
    private RewardedAd rewardedAd;
    
    void Start()
    {
        // Initialize Mobile Ads SDK
        MobileAds.Initialize(initStatus =>
        {
            Debug.Log("AdMob initialized");
            LoadRewardedAd();
        });
    }
    
    private void LoadRewardedAd()
    {
        // Create ad request
        AdRequest adRequest = new AdRequest();
        
        // Load rewarded ad
        RewardedAd.Load(AD_UNIT_ID, adRequest, (RewardedAd ad, LoadAdError error) =>
        {
            if (error != null || ad == null)
            {
                Debug.LogError($"Rewarded ad failed to load: {error}");
                return;
            }
            
            Debug.Log("Rewarded ad loaded");
            rewardedAd = ad;
            
            // Register event handlers
            RegisterEventHandlers(ad);
        });
    }
    
    private void RegisterEventHandlers(RewardedAd ad)
    {
        // Raised when the ad is estimated to have earned money
        ad.OnAdPaid += (AdValue adValue) =>
        {
            // Validate and ensure revenue data is within an expected range
            float revenue = adValue.Value / 1_000_000f; // Convert micros to dollars
            string currency = adValue.CurrencyCode;
            
            // Check if revenue is positive and currency is valid
            if (revenue > 0 && !string.IsNullOrEmpty(currency))
            {
                // Construct and send the Singular Ad Revenue Event
                SingularAdData data = new SingularAdData(
                    "AdMob",
                    currency,
                    revenue
                );
                
                SingularSDK.AdRevenue(data);
                
                // Log the revenue data for debugging purposes
                Debug.Log($"Ad Revenue reported to Singular: {data}");
            }
            else
            {
                Debug.LogError($"Invalid ad revenue data: revenue = {revenue}, currency = {currency}");
            }
        };
        
        // Additional event handlers
        ad.OnAdFullScreenContentOpened += () =>
        {
            Debug.Log("Rewarded ad full screen content opened");
        };
        
        ad.OnAdFullScreenContentClosed += () =>
        {
            Debug.Log("Rewarded ad full screen content closed");
            // Load next ad
            LoadRewardedAd();
        };
        
        ad.OnAdFullScreenContentFailed += (AdError error) =>
        {
            Debug.LogError($"Rewarded ad failed to show: {error}");
            // Load next ad
            LoadRewardedAd();
        };
    }
    
    public void ShowRewardedAd()
    {
        if (rewardedAd != null && rewardedAd.CanShowAd())
        {
            rewardedAd.Show((Reward reward) =>
            {
                Debug.Log($"User earned reward: {reward.Type} - {reward.Amount}");
            });
        }
        else
        {
            Debug.Log("Rewarded ad is not ready yet");
        }
    }
}

AppLovin MAX Integration

Track impression-level ad revenue using the AppLovin Impression-Level User Revenue API.

Requirements:

  • Implement AppLovin MAX SDK for Unity (see Getting Started Guide)
  • Attach revenue paid callbacks to all ad formats you are using

Implementation

Register OnAdRevenuePaidEvent callbacks to capture and send revenue data to Singular.

C#
using UnityEngine;
using Singular;

public class AppLovinRevenueTracking : MonoBehaviour
{
    void Start()
    {
        // Attach callbacks based on the ad format(s) you are using
        MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
        MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
        MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
        MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
    }
    
    private void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
    {
        double revenue = adInfo.Revenue;
        
        if (revenue > 0)
        {
            // Create a SingularAdData object with relevant information
            SingularAdData adData = new SingularAdData(
                "AppLovin",
                "USD", // AppLovin typically reports in USD
                revenue
            );
            
            // Send ad revenue data to Singular
            SingularSDK.AdRevenue(adData);
            
            Debug.Log($"Ad Revenue reported to Singular: {revenue} USD from {adUnitId}");
        }
        else
        {
            Debug.LogError("Failed to parse valid revenue value from ad info or revenue is not greater than 0");
        }
    }
    
    void OnDestroy()
    {
        // Detach callbacks to prevent memory leaks
        MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent -= OnAdRevenuePaidEvent;
        MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent -= OnAdRevenuePaidEvent;
        MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent -= OnAdRevenuePaidEvent;
        MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent -= OnAdRevenuePaidEvent;
    }
}

Unity LevelPlay (IronSource) Integration

Track impression-level revenue from ironSource and mediated networks using the IronSource SDK.

Requirements:

  • Implement ironSource Unity SDK (see Getting Started Guide)
  • Enable ARM SDK Postbacks flag in your IronSource dashboard
  • Set impression data listener to receive revenue callbacks

Learn More: See IronSource Ad Revenue Documentation for complete setup details.

Implementation

Subscribe to the ImpressionDataReadyEvent to capture and send revenue data.

C#
using UnityEngine;
using Singular;

public class IronSourceRevenueTracking : MonoBehaviour
{
    void Start()
    {
        // Ensure the listener is added before initializing the SDK
        IronSourceEvents.onImpressionDataReadyEvent += ImpressionDataReadyEvent;
        
        // Initialize the IronSource SDK here if not already done
        // IronSource.Agent.init("YOUR_IRONSOURCE_APP_KEY");
    }
    
    private void ImpressionDataReadyEvent(IronSourceImpressionData impressionData)
    {
        if (impressionData != null)
        {
            // Ensure revenue value is valid
            double? revenue = impressionData.revenue;
            
            if (revenue.HasValue && revenue.Value > 0)
            {
                // Create SingularAdData object with appropriate values
                SingularAdData adData = new SingularAdData(
                    "IronSource",
                    "USD", // IronSource typically reports in USD
                    revenue.Value
                );
                
                // Send the Ad Revenue data to Singular
                SingularSDK.AdRevenue(adData);
                
                // Log the data for debugging
                Debug.Log($"Ad Revenue reported to Singular: AdPlatform: {adData.AdPlatform}, " +
                         $"Currency: {adData.Currency}, Revenue: {adData.Revenue}");
            }
            else
            {
                Debug.LogError($"Invalid revenue value: {revenue}");
            }
        }
        else
        {
            Debug.LogError("Impression data is null");
        }
    }
    
    void OnDestroy()
    {
        // Detach the callback to prevent memory leaks
        IronSourceEvents.onImpressionDataReadyEvent -= ImpressionDataReadyEvent;
    }
}

TradPlus Integration

Capture ad revenue from TradPlus mediation using the global impression listener.

Requirements:

  • Add global ad impression listener via TradplusAds.Instance().AddGlobalAdImpression()
  • Handle OnGlobalAdImpression callback to receive revenue data
  • Convert eCPM from milli-units to standard currency (divide by 1000)

Implementation

Register a global impression listener to track all ad impressions and revenue.

C#
using UnityEngine;
using Singular;
using System.Collections.Generic;
using System.Globalization;

public class TradPlusRevenueTracking : MonoBehaviour
{
    private const string TAG = "TradPlusRevenue";
    
    void Start()
    {
        // Add Global Ad Impression Listener
        TradplusAds.Instance().AddGlobalAdImpression(OnGlobalAdImpression);
    }
    
    void OnGlobalAdImpression(Dictionary<string, object> adInfo)
    {
        // Ensure adInfo is not null
        if (adInfo == null)
        {
            Debug.LogError($"{TAG}: AdInfo is null");
            return;
        }
        
        // Ensure eCPM is present and valid
        if (!adInfo.ContainsKey("ecpm") || adInfo["ecpm"] == null)
        {
            Debug.LogError($"{TAG}: eCPM value is null or missing");
            return;
        }
        
        // Parse the eCPM value
        if (!double.TryParse(adInfo["ecpm"].ToString(), NumberStyles.Float | NumberStyles.AllowThousands, 
            CultureInfo.InvariantCulture, out double revenue))
        {
            Debug.LogError($"{TAG}: Failed to parse eCPM value");
            return;
        }
        
        // Convert eCPM to revenue (eCPM is in milli-units)
        revenue = revenue / 1000.0;
        
        // Validate the revenue value
        if (revenue <= 0)
        {
            Debug.LogError($"{TAG}: Ad Revenue value out of expected range: {revenue}");
            return;
        }
        
        // Create SingularAdData object with the necessary fields
        SingularAdData data = new SingularAdData(
            "TradPlus",
            "USD",
            revenue
        );
        
        // Send the Ad Revenue data to Singular
        SingularSDK.AdRevenue(data);
        
        // Log the data for debugging purposes
        Debug.Log($"{TAG}: Ad Revenue reported to Singular: AdPlatform: {data.AdPlatform}, " +
                 $"Currency: {data.Currency}, Revenue: {data.Revenue}");
    }
}

Generic Integration (Other Platforms)

Integrate any mediation platform using the generic SingularAdData interface.

Requirements:

  • Access to impression-level revenue data from your mediation platform
  • Revenue amount in standard currency units (not micros)
  • ISO 4217 currency code (e.g., USD, EUR, INR)

Data Accuracy: Validate revenue and currency data before sending to Singular. Incorrect data cannot be corrected after submission.

Implementation

Create a SingularAdData object with platform name, currency, and revenue, then call SingularSDK.AdRevenue().

C#
using UnityEngine;
using Singular;

public class GenericAdRevenueTracking : MonoBehaviour
{
    // Function to report ad revenue to Singular
    public void ReportAdRevenue(string adPlatform, string currency, float revenue)
    {
        // Validate the input: ensure revenue is positive and currency is not null or empty
        if (revenue > 0 && !string.IsNullOrEmpty(currency))
        {
            // Create a SingularAdData object with the validated data
            SingularAdData data = new SingularAdData(
                adPlatform,
                currency,
                revenue
            );
            
            // Send the ad revenue data to Singular
            SingularSDK.AdRevenue(data);
            
            // Log the reported data for debugging
            Debug.Log($"Ad Revenue reported to Singular: Platform = {adPlatform}, " +
                     $"Currency = {currency}, Revenue = {revenue}");
        }
        else
        {
            // Log a warning if validation fails
            Debug.LogWarning($"Invalid ad revenue data: Platform = {adPlatform}, " +
                           $"Revenue = {revenue}, Currency = {currency}");
        }
    }
    
    // Example usage
    void ExampleUsage()
    {
        // Report revenue from a custom mediation platform
        ReportAdRevenue("MyMediationPlatform", "USD", 0.05f);
    }
}

Testing and Validation

Verify Revenue Reporting

Test your ad revenue implementation to ensure data flows correctly to Singular.

  1. Check Logs: Verify revenue callback logs appear with correct values and currency in Unity Console
  2. Test Ads: Load and display test ads to trigger revenue events
  3. Dashboard Verification: Confirm revenue appears in Singular dashboard within 24 hours
  4. Data Accuracy: Validate revenue amounts match your mediation platform reports

Troubleshooting: If revenue doesn't appear in Singular, check that:

  • Ad revenue attribution is enabled in your Singular account
  • Revenue values are greater than 0
  • Currency codes are valid ISO 4217 codes
  • Platform name matches Singular's expected format
  • Event handlers are properly registered before ads load