A grocery delivery app in Almaty and Astana gets about 10,000 installs a month from Meta, TikTok, Google and Apple Ads, and one in ten people who install it places a first order within the first week (the numbers in this lesson are made up). At the end of September the marketer adds up the reports from the four ad accounts and gets 1,270 first orders, while AppsFlyer credits the same networks with 1,000. Nothing is broken: each ad account counts by its own rules, and one order easily lands in two of them.

What an MMP does and what AppsFlyer setup looks like
An MMP (mobile measurement partner) decides which ad gets credit for an app install and for everything the person does after it. AppsFlyer and Adjust work in much the same way:
- The SDK inside the app tells the MMP about the first launch and about events such as the first order. AppsFlyer counts the first launch as the install, not the download from the store (AppsFlyer attribution model).
- Ad networks report clicks and impressions. Meta, Google Ads, TikTok and Apple Ads (Apple Search Ads until 2025) are self-reporting networks (SRNs): the MMP tells them about a new install, and the network claims it if the person saw or tapped one of its ads (how AppsFlyer works with SRNs).
- If several networks claim the install, the MMP gives it to one of them by shared rules: a click beats an impression, the last click inside the attribution window wins the install, and if there were no clicks, the last impression does. The other networks show up in the report as assists (assisted installs).
- Everything the person does next is tied to the same source and sent to the networks as postbacks, so their algorithms learn from orders rather than installs.
Ad accounts have no shared rules: Meta credits itself with installs regardless of other sources (AppsFlyer and Meta discrepancies), and the other networks count by their own windows. A customer taps an Instagram ad on Tuesday and a TikTok ad on Thursday, installs the app and orders 9,000 ₸ of groceries that evening. The order can show up in both ad accounts, while AppsFlyer gives it to TikTok and lists Meta as an assist. Only shared rules let you compare networks with each other and tie each install to the revenue it later brought in.
In practice, AppsFlyer setup comes down to six steps, each covered below:
- Get the dev key and build the SDK into the iOS and Android apps.
- Define the
first_purchaseandpurchaseevents with the amount in tenge. - Connect the ad networks and decide which events they receive.
- Set the attribution windows and the time zone.
- Run one test purchase from the phone to the network's ad account.
- Open the report by network and work out the spend per first order.
How an MMP works inside, and when Firebase alone is enough, is explained in the article on AppsFlyer, Adjust and Firebase. This lesson is about practice.
The SDK and the dev key
AppsFlyer recognises your account by the dev key. It sits under Settings → App Settings → Dev Key Management, and you send it to the developer together with the app ID (basic SDK integration).
iOS has a trap. If the app shows the ATT prompt, the developer has to make the SDK wait for the answer (waitForATTUserAuthorization). Without it, the first launch goes to AppsFlyer without the IDFA even when the person taps Allow, and the networks can't match the install to a click by ID.
Ask the developer to pass your customer ID to the SDK when the person signs in. In AppsFlyer this is the Customer User ID: it lands in the raw data next to the AppsFlyer ID, and with it you find the person from the MMP in your customer database.
Adjust uses an app token instead of a dev key, plus an environment: sandbox for testing and production for the build that goes to the store (Adjust Android SDK).
The first order and revenue
There are two revenue events: first_purchase for the first order and purchase for every one after it. They are sent not when the person taps Checkout but when the server has confirmed payment for the order. With a card payment, the app sends the event. An order paid to the courier counts once the courier closes it, and then the server sends the event, as in SDK integration. The app learns from the server whether this is the first order: only the server sees the full order history. The same release also sends sign_up and address_out_of_zone to AppsFlyer: they show where people drop off before ordering. The full event plan is in in-app events.
AppsFlyer treats only the af_revenue parameter as revenue, in reports and in raw data alike. The currency goes in af_currency as a three-letter ISO 4217 code. If you leave the currency out, the SDK assumes dollars (in-app events in the Android SDK), and a 9,000 ₸ order turns into 9,000 dollars in the report.
Your own event names must not start with af_, which is the prefix of AppsFlyer's predefined events (naming rules).
Adjust works the other way round. You first create the event in the interface (AppView → All apps → your app → Events → Add event), and Adjust gives it a token (how to add an event). The token goes into the code, and the amount is set with setRevenue(9000.0, "KZT") (events in the Adjust SDK). So a new event in Adjust doesn't exist until someone with access to the interface creates it.
Ad networks and postbacks
In AppsFlyer you connect networks under Collaborate → Partner Integrations: find the network, click Integrate and turn on Activate partner (setting up a partner). Leave that toggle alone for as long as you work with the network and pause ads in the ad account instead: AppsFlyer warns that turning the integration off can cause irreversible damage to running campaigns.
Each network needs its own key. For Meta it's the Facebook App ID (Meta integration); for Google Ads it's a link ID (Google Ads integration). An admin creates it in Google Ads itself: Tools → Data manager → + Connect Product → Third-party app analytics → Create link ID (how to create a link ID). The four networks in the example don't need a tracking link because they are SRNs; for the rest you create one on the Attribution link tab.
Next comes the In-app event postbacks block, where you decide what the network learns about orders:
- Map
first_purchaseto the network's purchase event, or the network won't receive it. Names are case-sensitive: to AppsFlyer,First_Purchaseandfirst_purchaseare different events, so copy them from your event table. - Under including, pick Values & revenue. With the other options the network gets the order without the amount and can't optimise for revenue.
- Under for users from, choose whose events to send: only users from this network (This partner only) or everyone, organic included (All media sources including organic). The second option gives the network's algorithm more data, but it is also why a network can claim an order AppsFlyer gave to someone else.
The integration is set up per app: after saving, switch to the Android app and repeat the steps.
In Adjust the path is Campaign Lab → Partners → New partner. For Meta you also have to connect Adjust as a data source in Events Manager, or Meta can't claim a single install that Adjust measures. Events you haven't mapped are not shared with Meta (setting up Meta in Adjust).
Attribution windows and the time zone
An attribution window is how much time can pass between a click or an impression and the first launch for the network to get the install. By default AppsFlyer allows 7 days for a click (adjustable from 1 to 30) and 1 day for an impression (AppsFlyer attribution model); Adjust allows 7 days and 24 hours (Adjust attribution windows).
For SRNs, AppsFlyer recommends matching the network's own windows (AppsFlyer attribution model). On Meta that is 7 days for a click and 1 day for a view (AppsFlyer and Meta discrepancies), and for Google Ads AppsFlyer recommends a 30-day click window (Google Ads integration). The flip side: with a 30-day window Google gets installs that happen 8-30 days after the click, while TikTok, on 7 days, gets none of those. Write each network's windows into the report so the comparison is read with that in mind.
The app's time zone in AppsFlyer defaults to UTC+0 and can be changed in the app settings (AppsFlyer and Meta discrepancies). The Google Ads time zone, on the other hand, can't be changed once the account is created (Google Ads time zone). So align the AppsFlyer app time zone with the ad accounts and note the offset for the other ad accounts in the report, or night and morning orders will fall on different days in the MMP and the ad account.
One test purchase before you sign
Before you turn on the ads, take one 9,000 ₸ test order all the way through: first_purchase with the amount and the KZT currency in AppsFlyer, the same row in the raw export under Export → Raw Data Export (raw data export page) and the purchase in Meta's Events Manager. Registering a test device and testing the SDK follow SDK integration, and if you are still choosing an MMP, run the same check on a trial account before you sign.
Which report to open first
The Overview dashboard that older guides refer to was closed by AppsFlyer on 30 June 2026 and replaced by My Dashboards (AppsFlyer announcement). For Android, open the Performance Analysis template; for iOS, if Single Source of Truth is set up, the template of the same name (My Dashboards templates). Group by media source, add installs and unique users of first_purchase for the D7 period with the Cumulative calculation. Take the spend from the ad accounts.
| Network | Installs in AppsFlyer | CPI | Spend | First orders in the ad account | First orders in AppsFlyer, D7 | Spend per first order |
|---|---|---|---|---|---|---|
| Meta | 4,000 | 500 ₸ | 2,000,000 ₸ | 520 | 400 | 5,000 ₸ |
| TikTok | 3,000 | 300 ₸ | 900,000 ₸ | 210 | 150 | 6,000 ₸ |
| Google App campaigns | 2,000 | 600 ₸ | 1,200,000 ₸ | 360 | 300 | 4,000 ₸ |
| Apple Ads | 1,000 | 900 ₸ | 900,000 ₸ | 180 | 150 | 6,000 ₸ |
| Total | 10,000 | 500 ₸ | 5,000,000 ₸ | 1,270 | 1,000 | 5,000 ₸ |
TikTok has the cheapest installs, but a first order from it costs 6,000 ₸. Google's installs cost more, and its first orders cost less than anyone's. Part of that advantage is the 30-day window against TikTok's 7. One month can't tell you whether TikTok's audience is worse or its users simply order later, so before you cut the budget, wait for the same cohort at D30. Repeat orders are read in the MMP too: Meta shows events up to 7 days after the click, while AppsFlyer keeps a Meta user tied to that source for up to 180 days (AppsFlyer and Meta discrepancies).
Two corrections follow:
- Matching the ad accounts. The LTV period and the D7 cohort tie orders to the install date, while the Meta ad account counts by event date. To reconcile with the ad account, switch the period to Actual (AppsFlyer and Meta discrepancies).
- iOS. If ATT consent is missing in at least one of the two apps, yours or the one where the person saw the ad, the networks can't match the install to a click by ID, and in the regular dashboard such an install will most likely end up as organic. AppsFlyer recommends reading SRN results on iOS in the SKAN dashboard or in Single Source of Truth (how AppsFlyer works with SRNs); more in the lesson on SKAdNetwork.
In Adjust you read the same numbers in Datascape, its reporting area (Datascape).
AppsFlyer, Adjust or MyTracker
AppsFlyer publishes its prices: on the Growth plan the first 12,000 conversions (attributed installs and re-engagements) in the first year are free, then each costs $0.07, and Raw Data and Data Locker are paid separately (AppsFlyer pricing). At 10,000 installs from ads a month the package runs out in the second month, after which it comes to about $700 a month. Adjust's terms and how each one accepts server-side events are compared in the article on choosing an MMP. If your media plan includes VK Ads and Yandex Direct, look at MyTracker as well: both platforms are on the integration list on the MyTracker site, and its basic plan is free.
Exercise: a spec for connecting an MMP
Take an app you work with, or the delivery app from this lesson, and put together a one-page spec for the developer and the marketer:
Then write a paragraph for the app owner who saw 1,270 first orders in the ad accounts and 1,000 in your report and asks where the 270 went and which network is lying.
No orders went missing, and nobody is lying. Each network claims an install based on its own data, impressions included, and doesn't check whether there was a click in another network. The order of someone who saw ads in two networks sits in two ad accounts. AppsFlyer gives each order to one network by shared rules, so it is the only place where networks can be added up and compared. Its total is reconciled with the order system: the people who installed the app in September should have at least 1,000 first orders there, since organic installs land there too, and if there are fewer, look for duplicate events. One more thing: attribution says which network got credit for an order, not whether the order would have happened without the ads. That is a separate question, covered in the lesson on attribution models.
Video: why brands need an MMP
A video from AppsFlyer itself on why you need an intermediary between the app and the ad networks.