Your MMP knows where an install came from. Your app export knows what the user did next. As long as those two live in separate dashboards, nobody can answer the only question that matters: which campaigns bring users who actually stick. Piping MMP data into BigQuery fixes that. Here's how.
The problem: two half-pictures
An MMP like AppsFlyer or Adjust attributes the install to a campaign, channel, and cost. Firebase or your product analytics tracks what happens after: activation, retention, revenue.
Keep them apart and you're stuck. The MMP can't see long-term value, and your app data can't see acquisition source. Joined, they tell the whole story of a user from ad to outcome.
Step one: land the raw data
The goal is to get both datasets into BigQuery, raw. You already know the app side from the Firebase export; the MMP side needs its own pipe.
- Most MMPs offer a native BigQuery or cloud export, sometimes called raw data export or data locker.
- If not, their scheduled CSV or S3 export can be loaded on a schedule.
- Push for cost data too, not just installs, so you can compute real ROAS later.
Land it untransformed first; clean it in the warehouse, not on the way in.
Step two: agree on a join key
The join only works if both sides share a stable identifier. The usual key is the app-instance or install id that both the MMP SDK and Firebase can see, or a user id you set once the user logs in.
This is the make-or-break step: if the MMP's id and the app export's id don't line up, everything downstream is guesswork. Confirm the match on a sample before you build on it.
Step three: build the joined model
With both datasets landed and a shared key agreed, the join itself is straightforward SQL:
SELECT m.install_id, m.media_source, m.campaign, m.cost, COUNT(DISTINCT e.event_date) AS active_days, SUM(IF(e.event_name='purchase',1,0)) AS purchases, SUM(e.revenue) AS revenue_30d FROM `project.mmp.installs` m LEFT JOIN `project.analytics.app_events` e USING (install_id) GROUP BY 1, 2, 3, 4
Now one row ties a campaign and its cost to real downstream behavior, which is exactly what neither dashboard could show alone.
Step four: make it the source of truth
Turn that query into a scheduled model in dbt or Dataform so it refreshes daily instead of living in someone's query history. From there it can feed dashboards, ROAS reports, and even audiences sent back to ad platforms.
The point of one source of truth is that everyone reads the same numbers, so put it somewhere shared and governed, not in a personal notebook.
What this unlocks
Once the joined model exists, the questions that used to bounce between teams get one answer. You can rank campaigns by 30-day revenue instead of installs, spot channels that buy cheap users who never return, and compute true ROAS because cost and outcome finally sit in the same row.
It also feeds back into acquisition: the same table can define a high-value user segment and, through reverse ETL, push it to Meta or Google as a seed audience, so your best downstream data starts improving your targeting instead of just describing it.
Where it goes wrong
- Mismatched ids, so the join silently drops or duplicates users.
- Importing installs but not cost, which makes ROAS impossible.
- Comparing MMP counts to SKAN counts and expecting them to match, when they measure differently.
Piping MMP data into BigQuery joins the source of an install to the story of what that user did, which is the whole picture neither tool holds alone. Land both raw, agree on a join key, model it on a schedule, and your scattered mobile dashboards finally collapse into one source of truth.
Want a stronger data analyst role or a raise? Grab the FREE Product Analyst Playbook and get the exact roadmap to your next offer.
