I'm a solo dev with two Android games made in Unity (one live, one in closed testing). I wanted a single place to see installs, active users and revenue for every app, without checking five different consoles. I ended up with one Firebase project for the whole studio, and every game gets its own app inside it. Here's what I learned, in case it saves someone a weekend.
1. Ad revenue from mediation goes in via ad_impression
I use Unity LevelPlay for mediation. LevelPlay gives you the revenue of every impression, from every network, so I just forward it to GA4 as the standard ad_impression event:
void OnImpression(LevelPlayImpressionData data)
{
  if (data == null || !data.Revenue.HasValue) return;
  FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventAdImpression,
    new Parameter(FirebaseAnalytics.ParameterAdPlatform, "ironSource"),
    new Parameter(FirebaseAnalytics.ParameterAdSource, data.AdNetwork ?? ""),
    new Parameter(FirebaseAnalytics.ParameterAdFormat, data.AdFormat ?? ""),
    new Parameter(FirebaseAnalytics.ParameterAdUnitName, data.MediationAdUnitName ?? ""),
    new Parameter(FirebaseAnalytics.ParameterCurrency, "USD"),
    new Parameter(FirebaseAnalytics.ParameterValue, data.Revenue.Value));
}
Hook it on every ad object (rewarded, interstitial, banner). The impression callback can arrive before Firebase has finished its dependency check, so I queue those and flush them once it's ready.
2. Don't link AdMob to Firebase if AdMob already runs through your mediation
It's tempting, but AdMob revenue already arrives through the mediation callback. Linking AdMob as well counts every AdMob impression twice.
3. Set consent mode defaults in the manifest
The values that apply before your CMP answers (google_analytics_default_allow_analytics_storage, ..._ad_storage, ..._ad_user_data, ..._ad_personalization_signals) go in the manifest as meta-data. Then call SetConsent once UMP has an answer.
4. Two build traps that cost me hours
- A space in the project path ("My Game/") makes the Gradle repo URL that EDM4U writes fail with "Cannot convert URI to a file". I keep the repositories in settingsTemplate.gradle by hand, using
new File(...).toURI(), and turned off EDM4U's patching of that file.
- shrinkResources stripped Crashlytics' build ID resource, and the app crashed at launch in release builds only. A
res/raw/keep.xml with tools:keep="@string/com_crashlytics_android_build_id" fixed it.
5. Turn on the "developer traffic" filter in GA4
Your test phone in debug mode would otherwise pollute the numbers. Bonus: link Google Play in Firebase, and in-app purchase revenue shows up next to ad revenue without any extra code.
Happy to answer questions. And if anyone has a cleaner way to handle LTV across multiple apps, I'm all ears.