iOS Google Ads Conversion Tracking: Why Adjust Alone Isn't Enough
Someone from the ad team told me: “Set up Google Ads iOS conversion tracking.”
I figured since Adjust was already in, updating the Adjust SDK would be enough.
Turned out that was completely wrong. You need all three: Adjust SDK + Firebase SDK + Adjust ODM plugin. And on top of that, you have to request a whitelist registration on the Adjust side.
Here’s a writeup on how iOS ad measurement has gotten more complicated than you’d expect.
Why iOS Ad Measurement Got Complex
ATT Restrictions Since iOS 14.5
Since iOS 14.5 (April 2021), getting the IDFA (Identifier for Advertisers) requires explicit user consent. This is ATT (App Tracking Transparency).
When a user selects “Don’t Allow Tracking,” the app can no longer access the IDFA. Consent rates are generally around 20–30% in practice.
In other words, the old IDFA-based measurement approach has mostly stopped working.
Why the Old Method Doesn’t Work Anymore
Before iOS 14.5:
- App → get IDFA → send to Google Ads → “Oh, this is the person who clicked that ad”
Since iOS 14.5:
- 20–30% of users → IDFA accessible (measurable)
- 70–80% of users → no IDFA (unmeasurable)
From Google Ads’ perspective, measurement only works for the minority. That makes it impossible to evaluate ad effectiveness.
Hence the need for an alternative: “On-Device Conversion.”
The Full Picture of Measurement Routes
Google Ads iOS conversion tracking has two main routes:
Route via Adjust
In-app event
↓
Adjust SDK + ODM plugin
↓
Firebase Analytics (for Google On-Device Conversion)
↓
Adjust server (S2S integration)
↓
Google Ads
Characteristics:
- Natural choice if you’re already using Adjust
- Strengths as an MMP (supports multiple ad platforms)
- Requires ICM whitelist registration on the Adjust side
Route via Firebase
In-app event
↓
Firebase SDK (v11.14.0+)
↓
Firebase Analytics (for Google On-Device Conversion)
↓
Google Ads
Characteristics:
- Self-contained within the Google ecosystem
- Relatively simple setup
- A viable option if you’re starting fresh
Which Should You Choose?
| Situation | Route |
|---|---|
| Already using Adjust | Via Adjust |
| Using Firebase only | Via Firebase |
| Either works | Via Firebase (simpler setup) |
Important: Whichever you choose, Firebase Analytics + Google On-Device Conversion (ODM) integration is mandatory. This is a Google Ads requirement.
The “Adjust Is Enough” Misconception
This is where I got tripped up at first.
I thought “Adjust is already in, so just updating the Adjust SDK should do it.”
But what’s actually required:
- Adjust SDK updated to v5.4.1 or higher
- Adjust ODM plugin added (for Google On-Device Measurement)
- Firebase SDK v11.14.0 or higher
- Firebase ↔ Google Ads integration configured
- ICM whitelist registration requested from Adjust
Just having “Adjust SDK installed” isn’t enough. Firebase is mandatory too. Only with all of these together does “Google On-Device Conversion” actually work.
Implementation Steps (via Adjust)
1. Update Adjust SDK & Add ODM Plugin
With CocoaPods
Add (or update) the following in your Podfile:
pod 'Adjust', '5.4.1'
pod 'Adjust/AdjustGoogleOdm'
pod 'GoogleAdsOnDeviceConversion', '3.0.0'
If you already have Firebase Analytics 11.14.0+ installed, GoogleAdsOnDeviceConversion will be pulled in as a dependency automatically — no manual addition needed.
Then run pod install:
pod install
With Swift Package Manager
In Xcode, go to File → Add Package Dependencies and add the GitHub repository:
https://github.com/adjust/ios_sdk
Select version 5.4.1 or higher and add AdjustGoogleOdm to your target.
2. Implement the ATT Permission Request
This is the part that displays the tracking permission dialog on iOS 14.5+, asking the user whether to allow tracking.
Swift (AppDelegate):
import AppTrackingTransparency
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
requestTrackingAuthorization()
return true
}
func requestTrackingAuthorization() {
if #available(iOS 14.5, *) {
ATTrackingManager.requestTrackingAuthorization { status in
DispatchQueue.main.async {
self.initializeAdjust()
}
}
} else {
initializeAdjust()
}
}
Timing note: Showing the dialog immediately at launch makes users more likely to deny. Best practice is to show it after the user has understood the app’s value (after 1–2 screens).
3. Initialize Adjust SDK (Flutter/Dart)
import 'package:adjust_sdk/adjust.dart';
import 'package:adjust_sdk/adjust_config.dart';
void initializeAdjust() {
AdjustConfig config = AdjustConfig(
'{YourAppToken}',
AdjustEnvironment.production, // production for release
);
// Very important: wait time for the ATT dialog response
config.attConsentWaitingInterval = 120; // 120 seconds
// Log level (for development)
config.logLevel = AdjustLogLevel.verbose;
Adjust.initSdk(config);
}
Setting attConsentWaitingInterval tells the Adjust SDK to wait for the ATT permission status. Forgetting this means ATT-denied users won’t be measured.
4. Verify Firebase SDK & Configure Google Ads Integration
Initialize Firebase Analytics from the Flutter side (usually not needed if Firebase is already set up):
import 'package:firebase_analytics/firebase_analytics.dart';
final analytics = FirebaseAnalytics.instance;
// Example event
await analytics.logEvent(
name: 'purchase',
parameters: {
'currency': 'JPY',
'value': 980,
'transaction_id': 'txn_12345',
},
);
Google Ads settings (dashboard):
- Log in to Google Ads
- “Tools” → “Conversions”
- Create a new conversion action, or duplicate your Android one for iOS
- Set the source to “Google Analytics for Firebase”
- Select the corresponding Firebase event (e.g.
purchase)
5. Configure Google Ads Integration in Adjust
In the Adjust dashboard:
- Partner setup → Enable Google Ads
- Register the conversion token issued by Google Ads in Adjust
- Also send the event to Adjust from the Flutter app:
void trackPurchase(double amount, String currency, String transactionId) {
// Also record in Adjust
AdjustEvent event = AdjustEvent('{AdjustPurchaseEventToken}');
event.setRevenue(amount, currency);
event.setTransactionId(transactionId);
Adjust.trackEvent(event);
}
6. ICM Whitelist Registration (Adjust-side Action)
Contact Adjust and provide the following for the target app:
- iOS App ID (e.g.
com.example.myapp) - Adjust App Token
Adjust will add it to the ICM (In-App Conversion Measurement) whitelist. Without this, no amount of implementation will start measurement.
Testing and Debugging
Verifying in the Sandbox Environment
The Testing Console in the Adjust dashboard lets you confirm whether events are arriving correctly.
Run the production app on a test device registered in the Testing Console, and events will appear in real time.
// Keep debug logging on
config.logLevel = AdjustLogLevel.verbose;
If you see messages like “Event logged” in the log output, the SDK side is working.
Checking Conversions in Google Ads
Conversion numbers in the Google Ads dashboard take 24–48 hours to reflect after measurement occurs.
Don’t panic when the debug screen shows nothing. Check the next morning — the numbers are often there by then.
Pitfalls and Caveats
1. Adjust SDK Alone Isn’t Enough
This is the biggest point. Firebase SDK integration is mandatory.
There’s a lot of documentation saying “you can measure with Adjust,” and the Firebase part tends to get glossed over. But Firebase Analytics + ODM integration is a Google Ads requirement.
2. Firebase SDK Must Be v11.14.0+
A June 2025 update added a new “event data method.”
Older versions (11.13 and earlier) don’t support this method. Forgetting to update may prevent measurement from starting.
3. Forgetting attConsentWaitingInterval
config.attConsentWaitingInterval = 120;
Without this setting, the Adjust SDK initializes without waiting for ATT permission.
Conversion measurement for ATT-denied users won’t work.
4. ICM Whitelist Registration Isn’t Automatic
You can implement everything on the code side, set up Firebase Analytics, and it still won’t start without the manual registration on Adjust’s end.
If “measurement isn’t working after implementation is complete,” this registration is almost always the culprit.
5. Don’t Forget to Switch Sandbox vs Production
During development:
AdjustEnvironment.sandbox
For production:
AdjustEnvironment.production
If you forget to change this to production at release time, real data won’t be sent to Google Ads.
6. ATT Dialog Timing
Showing the dialog immediately at launch means users are likely to tap “Don’t Allow” without understanding why.
Best practice:
- Show it after the user has understood the app’s value (2–3 screens in)
- Or show it at a point where tracking is clearly relevant
Firebase-Only Route (Supplemental)
If you’re not using Adjust, Firebase alone works:
import 'package:firebase_analytics/firebase_analytics.dart';
final analytics = FirebaseAnalytics.instance;
// Send event
await analytics.logEvent(
name: 'purchase',
parameters: {
'currency': 'JPY',
'value': 9800,
},
);
Configure Firebase Analytics integration in Google Ads, and ODM (On-Device Measurement) is automatically enabled.
It’s less flexible than Adjust, but the setup is simpler. If you’re starting iOS ad measurement from scratch, going straight to Firebase is a perfectly valid option.
Implementation Checklist
□ Update Adjust SDK to v5.4.1+
□ Add Adjust ODM plugin (Podfile/SPM)
□ Run pod install or update packages
□ Verify Firebase SDK version (v11.14.0+)
□ Implement ATT permission request in AppDelegate
□ Initialize Adjust SDK in Dart (set attConsentWaitingInterval)
□ Send events via Firebase Analytics
□ Enable Google Ads integration in Adjust dashboard
□ Create conversion action in Google Ads
□ Verify event delivery in Testing Console
□ Request ICM whitelist registration from Adjust
□ Set AdjustEnvironment.production for production builds
iOS 14.5+ restricted IDFA tracking, making alternatives necessary for Google Ads conversion measurement. It’s not as simple as “update Adjust SDK” — you need the full trio:
- Adjust SDK v5.4.1+ + ODM plugin
- Firebase SDK v11.14.0+
- Firebase ↔ Google Ads integration
And then manual whitelist registration on the Adjust side.
There’s also a 24–48 hour delay before measurement reflects. Don’t panic when the numbers don’t appear immediately after implementation — check again the next day.
Related Articles
- Integrating Adjust SDK into a Flutter App - Adjust SDK integration basics
- Adjust and Google Play Console Integration Setup - Android-side setup
- Tracking In-App Purchase Revenue with Adjust (Flutter) - Revenue event sending in detail
- Flutter App Initial Setup Checklist - Full list of setup items