How to Integrate an MMP SDK (Step-by-Step Guide)
Complete guide to integrating mobile measurement partner SDKs. Avoid common mistakes and get attribution working correctly the first time.

How to Integrate an MMP SDK (Step-by-Step Guide)
MMP SDK integration is straightforward if you follow the right sequence. Most issues come from configuration mistakes, not technical complexity.
This guide covers the complete integration process across major MMPs, common pitfalls, and how to validate everything works before going live.
The actual code implementation takes a few hours. The setup, configuration, and testing determine whether your attribution works correctly from day one.
Pre-Integration Checklist
Before writing any code, prepare:
1. Account Setup
Create your MMP account and complete basic configuration:
- Company profile
- Billing information
- Team member access
2. App Details
Have ready:
- iOS: Bundle ID, App Store ID
- Android: Package name, SHA-1 fingerprint for Google Play
- App name and category
- Primary timezone (must match your analytics tools)
3. Partner Credentials
Gather API credentials for ad networks you'll integrate:
- Facebook/Meta app ID
- Google Ads conversion ID
- TikTok advertiser ID
- Other network-specific identifiers
4. Development Resources
- Access to your app's codebase
- Development environment set up for iOS and/or Android
- Test devices for both platforms
- Staging/development MMP account (if available)
Step 1: Dashboard Setup
Create Your App Profile
All MMPs follow a similar pattern:
- Log into your MMP dashboard
- Navigate to "Add App" or "Apps" section
- Enter app details:
- App name
- Platform (iOS, Android, or both)
- Bundle ID (iOS) / Package name (Android)
- Store URLs
- Primary category
Configure Basic Settings
Timezone:
- Must match your other analytics tools
- Cannot be changed after data starts flowing
- Affects cohort reporting boundaries
Attribution Windows:
- Click-through attribution: 7 days (industry standard)
- View-through attribution: 1 day (industry standard)
- Reattribution window: 30-90 days
Privacy Settings:
- Enable/disable IP collection
- Configure data retention periods
- Set GDPR/CCPA compliance flags
Generate SDK Credentials
Most MMPs provide:
- App token or SDK key (unique identifier for your app)
- Secret key (for server-to-server communication)
- Environment flags (production vs sandbox)
Important: Keep these credentials secure. Don't commit them directly to version control—use environment variables or secure credential management.
Step 2: SDK Installation
iOS Integration (Swift)
Using CocoaPods:
Add to your Podfile:
pod 'Adjust', '~> 4.38'
# or
pod 'AppsFlyerFramework', '~> 6.14'
# or
pod 'BranchSDK', '~> 3.3'
Run:
pod install
Using Swift Package Manager:
- In Xcode, go to File → Add Packages
- Enter the MMP's SDK repository URL
- Select version and add to target
Manual installation:
- Download the framework
- Drag to your Xcode project
- Add to "Frameworks, Libraries, and Embedded Content"
Android Integration (Kotlin)
Add to your app-level build.gradle:
dependencies {
implementation 'com.adjust.sdk:adjust-android:4.38.0'
// or
implementation 'com.appsflyer:af-android-sdk:6.14.0'
// or
implementation 'io.branch.sdk.android:library:5.9.0'
// Required for most MMPs
implementation 'com.android.installreferrer:installreferrer:2.2'
}
Add required permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Optional but recommended for attribution accuracy -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
React Native
Most MMPs provide React Native wrappers:
npm install react-native-appsflyer
# or
npm install react-native-adjust
# or
npm install react-native-branch
Then link:
cd ios && pod install && cd ..
Flutter
dependencies:
appsflyer_sdk: ^6.14.0
# or
adjust_sdk: ^4.38.0
# or
flutter_branch_sdk: ^7.0.0
Step 3: SDK Initialization
iOS (Swift)
Initialize in AppDelegate.swift:
import Adjust
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Create Adjust config
let adjustConfig = ADJConfig(
appToken: "YOUR_APP_TOKEN",
environment: ADJEnvironmentProduction // Use ADJEnvironmentSandbox for testing
)
// Optional: Set log level for debugging
adjustConfig?.logLevel = ADJLogLevelVerbose
// Optional: Enable event buffering
adjustConfig?.eventBufferingEnabled = true
// Initialize SDK
Adjust.appDidLaunch(adjustConfig)
return true
}
For AppsFlyer:
import AppsFlyerLib
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().appsFlyerDevKey = "YOUR_DEV_KEY"
AppsFlyerLib.shared().appleAppID = "YOUR_APP_ID"
// For debugging
AppsFlyerLib.shared().isDebug = true
// Start SDK
AppsFlyerLib.shared().start()
return true
}
For Branch:
import Branch
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize Branch
Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
// Handle deep link data
if let params = params {
// Process attribution data
print("Branch params: \(params)")
}
}
return true
}
Android (Kotlin)
Initialize in your Application class:
import com.adjust.sdk.Adjust
import com.adjust.sdk.AdjustConfig
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Create Adjust config
val config = AdjustConfig(
this,
"YOUR_APP_TOKEN",
AdjustConfig.ENVIRONMENT_PRODUCTION // Use ENVIRONMENT_SANDBOX for testing
)
// Optional: Set log level
config.setLogLevel(LogLevel.VERBOSE)
// Initialize SDK
Adjust.onCreate(config)
}
}
For AppsFlyer:
import com.appsflyer.AppsFlyerLib
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
AppsFlyerLib.getInstance().init("YOUR_DEV_KEY", null, this)
AppsFlyerLib.getInstance().start(this)
// For debugging
AppsFlyerLib.getInstance().setDebugLog(true)
}
}
Don't forget to register your Application class in AndroidManifest.xml:
<application
android:name=".MyApplication"
...>
</application>
Critical Timing Considerations
Initialize before any other SDKs when possible. This ensures:
- Attribution data is captured first
- Deep link parameters are available to other SDKs
- All subsequent events are properly attributed
iOS-specific: For SKAdNetwork support, initialization must happen before the first app open completes.
Android-specific: Install referrer can only be fetched once per install. Early initialization is critical.
Step 4: Deep Linking Configuration
iOS Universal Links
-
Enable Associated Domains in Xcode capabilities
-
Add your domain:
applinks:yourdomain.com -
Create
apple-app-site-associationfile on your server at:https://yourdomain.com/.well-known/apple-app-site-association -
Handle universal links in
AppDelegate:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// For Adjust
Adjust.appWillOpen(userActivity.webpageURL)
// For AppsFlyer
AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
// For Branch
Branch.getInstance().continue(userActivity)
return true
}
Android App Links
- Add intent filter to your
AndroidManifest.xml:
<activity android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="yourdomain.com" />
</intent-filter>
</activity>
-
Create
assetlinks.jsonfile at:https://yourdomain.com/.well-known/assetlinks.json -
Handle deep links in your Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle deep link
val data: Uri? = intent?.data
// For Adjust
Adjust.appWillOpenUrl(data, applicationContext)
// For AppsFlyer
AppsFlyerLib.getInstance().performOnAppAttribution(this, data)
}
Step 5: Event Tracking Implementation
Define Your Event Schema
Before implementing, document:
- Event names (use consistent naming convention)
- Event parameters/properties
- When each event fires
- Expected volume per event
Example schema:
Event: purchase_completed
Parameters:
- revenue (number, required)
- currency (string, required)
- product_id (string, required)
- category (string, optional)
Fires: After successful purchase confirmation
iOS Event Tracking
import Adjust
// Simple event
let event = ADJEvent(eventToken: "abc123")
Adjust.trackEvent(event)
// Event with revenue
let purchaseEvent = ADJEvent(eventToken: "abc123")
purchaseEvent?.setRevenue(9.99, currency: "USD")
purchaseEvent?.setTransactionId("unique_transaction_id") // Prevents duplicate tracking
Adjust.trackEvent(purchaseEvent)
// Event with custom parameters
let registrationEvent = ADJEvent(eventToken: "def456")
registrationEvent?.addCallbackParameter("user_id", value: "12345")
registrationEvent?.addCallbackParameter("signup_method", value: "email")
Adjust.trackEvent(registrationEvent)
Android Event Tracking
import com.adjust.sdk.Adjust
import com.adjust.sdk.AdjustEvent
// Simple event
val event = AdjustEvent("abc123")
Adjust.trackEvent(event)
// Event with revenue
val purchaseEvent = AdjustEvent("abc123")
purchaseEvent.setRevenue(9.99, "USD")
purchaseEvent.setOrderId("unique_transaction_id") // Prevents duplicate tracking
Adjust.trackEvent(purchaseEvent)
// Event with custom parameters
val registrationEvent = AdjustEvent("def456")
registrationEvent.addCallbackParameter("user_id", "12345")
registrationEvent.addCallbackParameter("signup_method", "email")
Adjust.trackEvent(registrationEvent)
Best Practices for Event Tracking
Prevent duplicate events:
- Always use transaction IDs for revenue events
- Implement debouncing for user-triggered events
- Don't track events in loops or frequently-called functions
Parameter naming:
- Use snake_case consistently
- Keep names descriptive but concise
- Document all parameters
Data types:
- Revenue: Always use decimal/float, never integers
- Currency: ISO 4217 codes (USD, EUR, GBP)
- IDs: Strings, not numbers (preserves leading zeros)
Step 6: Partner Integration
Configure Ad Network Integrations
In your MMP dashboard:
- Navigate to "Integrations" or "Partners"
- Find your ad network (Facebook, Google, TikTok, etc.)
- Click "Enable" or "Add"
- Enter required credentials
- Configure postback URLs
Facebook/Meta Integration
Requirements:
- Facebook App ID
- Business Manager ID
- System User token (for Advanced Mobile Measurement)
Steps:
- In MMP dashboard, go to Facebook integration
- Enter Facebook App ID
- Enable "Advanced Mobile Measurement" (if available)
- Configure event mapping (map MMP events to Facebook events)
Google Ads Integration
Requirements:
- Google Ads customer ID
- Conversion tracking ID
- Google Play API access (for Android)
Steps:
- In MMP dashboard, go to Google Ads integration
- Enter customer ID
- Link Google Play Console (for Android conversion tracking)
- Configure event mapping
TikTok Integration
Requirements:
- TikTok advertiser ID
- App ID from TikTok dashboard
Steps:
- In MMP dashboard, go to TikTok integration
- Enter advertiser ID and app ID
- Configure event mapping
- Enable postbacks
Step 7: Testing and Validation
Test Device Setup
Most MMPs provide test modes that don't affect production data.
Adjust test mode:
// iOS
adjustConfig?.logLevel = ADJLogLevelVerbose
// Add test device
adjustConfig?.addTestDevice("YOUR_DEVICE_ADVERTISING_ID")
AppsFlyer test mode:
// iOS
AppsFlyerLib.shared().isDebug = true
Validation Checklist
1. Attribution Testing:
- Install app from different sources (organic, Facebook ad, Google ad)
- Verify install is attributed correctly in dashboard
- Check attribution data appears within 5 minutes
2. Event Tracking:
- Trigger each implemented event
- Verify events appear in dashboard
- Check event parameters are captured correctly
- Confirm revenue values display accurately
3. Deep Linking:
- Click universal link/app link
- Verify app opens to correct screen
- Check deep link data is accessible in app
- Test deferred deep linking (click before install)
4. Platform-Specific:
iOS:
- SKAdNetwork postbacks are configured
- ATTrackingManager permission is implemented
- Install validates on first app open
Android:
- Install referrer is captured
- Play Store attribution works
- Deferred deep linking functions correctly
Using Debug Tools
Adjust:
- Use "Testing Console" in dashboard
- View real-time event logs
- Check attribution data for test devices
AppsFlyer:
- Use "Test Mode" in dashboard
- View SDK integration status
- Real-time event debugger
Branch:
- Use "Link Validation" tool
- Test deep links in Link Debugger
- View session data in real-time
Common Issues and Fixes
Attribution not working:
- Check SDK is initialized before any other code
- Verify app token/key is correct
- Confirm network connectivity permissions
- Check timezone matches across MMP and analytics tools
Events not appearing:
- Verify event tokens match dashboard configuration
- Check event naming follows MMP requirements
- Ensure SDK is initialized before tracking events
- Review log output for error messages
Deep links not opening:
- Validate AASA/assetlinks file is accessible via HTTPS
- Check bundle ID/package name matches exactly
- Verify domain is added to MMP dashboard
- Test with https://branch.io/resources/universal-links/ (for universal links)
Revenue not tracking:
- Ensure revenue events include currency code
- Use unique transaction IDs
- Don't track negative revenue
- Verify numeric format (decimal, not integer)
Step 8: Production Deployment
Pre-Launch Checklist
- Remove or disable verbose logging
- Switch from sandbox to production environment
- Remove test device identifiers
- Verify all partner integrations are enabled
- Document event schema for your team
- Set up attribution dashboards
- Configure alerts for attribution drops
Gradual Rollout Strategy
Phase 1: Internal Testing (Days 1-3)
- Release to internal testers
- Monitor attribution for 100% of test installs
- Verify all events track correctly
Phase 2: Beta Release (Days 4-7)
- Release to 5-10% of users
- Monitor for attribution issues
- Check event volume matches expectations
Phase 3: Full Release (Day 8+)
- Roll out to 100% of users
- Continue monitoring for 30 days
- Document any issues and resolutions
Monitoring Post-Launch
Daily (first week):
- Check install attribution rate (should be 90%+)
- Verify event volume matches user activity
- Monitor for attribution delays (should be under 5 minutes)
Weekly (first month):
- Review cohort retention data
- Compare MMP data to ad network dashboards
- Check for attribution discrepancies
- Audit fraud prevention filters
FAQs
How long does MMP SDK integration take?
Basic SDK integration takes 2-6 hours for experienced developers. Full implementation including custom events, deep linking, and partner integrations typically takes 1-3 days. Add another 1-2 days for thorough testing and validation.
Do I need separate SDKs for iOS and Android?
Yes, you'll implement platform-specific SDKs for iOS and Android. For cross-platform frameworks like React Native or Flutter, most MMPs provide wrapper SDKs that handle both platforms with unified code.
When should I initialize the MMP SDK?
Initialize the SDK as early as possible in your app's lifecycle—ideally in application:didFinishLaunchingWithOptions on iOS or Application.onCreate on Android. This ensures you capture all attribution data and don't miss early events.
Can I track events before SDK initialization completes?
No, events tracked before SDK initialization will be lost. Always initialize the SDK first, then track events. For events that might fire early (like app open), use SDK callbacks to ensure initialization is complete.
How do I test without affecting production data?
Use your MMP's sandbox/test environment, enable debug logging, and add your test device IDs to the SDK configuration. Most MMPs filter test devices from production reporting automatically.
MMP integration is straightforward when you follow the sequence: account setup, SDK installation, initialization, event implementation, partner configuration, and thorough testing. Most issues come from configuration mistakes—not technical complexity. Take time to validate everything before going live, and you'll avoid attribution gaps that are difficult to fix retroactively.
Related Resources

How to Build Effective MMP Reporting Dashboards (2025)
Create mobile attribution dashboards that actually drive decisions. Learn which metrics to track, how to structure reports, and dashboard templates for growth teams.

Adjust vs AppsFlyer vs Branch: Which MMP is Right for You? (2025)
Compare the top mobile measurement partners in 2025. Honest breakdown of Adjust, AppsFlyer, and Branch pricing, features, and strengths.

Best Deep Linking Tools for Mobile Apps (2025)
Branch, AppsFlyer, Adjust, and Firebase alternatives compared. Find the right deep linking platform for attribution, routing, and user experience.