Firebase / Google Analytics 4
Your players: new players by first-open day, where they came from (first-user source and medium) and country; how far they get in your funnel; whether they come back; and the ad and purchase revenue each first-open cohort has earned so far. This is the source that ties spend to players, so set it up first.
"ga4": { "enabled": true, "properties": ["123456789"], "auth": "service-account" }
| Setting | Meaning |
|---|---|
properties |
GA4 property ids (Admin → Property details). For Firebase apps, the property linked to the Firebase project. Add each id to the app’s keys too. |
auth |
service-account (default) or oauth (your own Google login). |
Access
Service account (recommended): use the same key as for Google Ads (google-ads.md), enable the Google Analytics Data API in that Cloud project, and in GA4 open Admin → Property access management → + and add the service account’s email as Viewer.
Your own login: set "auth": "oauth" and run earnback connect google (see admob.md).
Funnel
The funnel in the config lists the events that make up your funnel, in order. first_open (logged by Firebase automatically) marks a new player and must come first. Add the events your game logs:
"funnel": [
{ "event": "first_open", "label": "Opened" },
{ "event": "tutorial_begin", "label": "Started tutorial" },
{ "event": "tutorial_complete", "label": "Finished tutorial" },
{ "event": "level_up", "label": "Reached level 2" }
]
A step counts players of a first-open day who logged that event at any time since, so the numbers of recent days still grow.
Channels
Players are credited to the channel of their first-user source / medium in GA4. The defaults:
| GA4 source / medium | Channel |
|---|---|
google / cpc (and paid, ppc) |
Google Ads |
sources containing facebook, instagram, fb4a, meta |
Meta |
sources containing tiktok |
TikTok |
google-play, play.google.com, apps.apple.com, app store |
Store (organic) |
(direct), (not set), empty |
Unknown |
| anything else | Other (the report lists the sources) |
Add your own rules under channels in the config; they are checked first. source and medium are case-insensitive regular expressions matched against the whole value:
"channels": [{ "source": "partner-network", "medium": "referral", "channel": "partner" }]
Revenue
- Ad revenue per cohort needs AdMob’s impression-level ad revenue in Firebase: link each AdMob app to its Firebase project and turn on impression-level ad revenue in AdMob’s settings. Firebase then logs an
ad_impressionevent with its value, and GA4’stotalAdRevenuecan be split by the player’s first-open day and source, which is what payback curves are built from. - Purchase revenue comes from GA4’s
purchaseRevenue(Firebase logs Play and App Store purchases within_app_purchase).
Without impression-level ad revenue, use the AdMob connector for totals; payback per channel then counts purchases only.
Caveats
- Players who don’t allow analytics (consent declined, EEA consent mode) are missing, so cost per player for one channel is an upper bound.
- GA4 needs about two days to settle. Earnback re-reads the last 35 days and marks data complete up to two days ago.
- GA4 withholds small numbers when Google Signals is on (data thresholds). If the report says so, switch Admin → Reporting identity to Device-based.
(direct) / (none)is common for store installs whose referrer Google didn’t pass on. It lands in Unknown, in plain view.
Errors
| Message | Fix |
|---|---|
analyticsdata.googleapis.com answered 403 |
Add the service account (or your login) as Viewer on the property, and enable the Analytics Data API in its Cloud project. |
analyticsdata.googleapis.com answered 400 about the property |
Use the numeric property id, not the measurement id (G-…) or the Firebase app id. |