Introduction to AppLovin
AppLovin is a leading mobile marketing platform that provides developers with tools for user acquisition, monetization, and analytics. Founded in 2012, it offers various ad formats and mediation solutions that help mobile app developers grow their businesses through effective advertising strategies.
Key benefits of AppLovin include:
- Comprehensive monetization solutions across multiple ad formats
- Advanced machine learning algorithms for optimization
- Simplified SDK integration process
- Robust reporting and analytics tools
- Access to high-quality demand sources through the AppLovin Exchange
- MAX mediation platform to maximize ad revenue
Core AppLovin Products
| Product | Description | Best Used For |
|---|
| AppLovin SDK | Core software development kit that enables ad display in mobile apps | Basic integration of AppLovin ads into mobile applications |
| MAX | Advanced in-app mediation platform that optimizes revenue across multiple ad networks | Maximizing revenue by managing multiple ad networks with a single SDK |
| AppDiscovery | User acquisition platform for driving app installs | Acquiring new users for your app |
| SparkLabs | In-house creative team that designs ad creatives | Creating high-performing ad creatives |
| AppLovin Exchange | Marketplace connecting advertisers with publishers | Accessing premium demand |
| AXON | Machine learning engine that powers optimization | Automated optimization of ad performance |
SDK Integration
SDK Version & Requirements
| Platform | Latest SDK Version | Minimum OS Requirements | Download Size |
|---|
| iOS | 11.11.3+ | iOS 9.0+ | ~500KB (base), ~3-6MB (with dependencies) |
| Android | 11.11.3+ | Android 4.4+ (API level 19+) | ~400KB (base), ~3-5MB (with dependencies) |
| Unity | 11.11.3+ | Unity 2017.4+ | Depends on platform |
| Flutter | 2.0.0+ | Flutter 1.20.0+ | Depends on platform |
| React Native | 11.11.3+ | React Native 0.60.0+ | Depends on platform |
Basic Integration Steps – iOS
// 1. Add AppLovin SDK to your project using CocoaPods
// In your Podfile:
pod 'AppLovinSDK'
// 2. Initialize the SDK in your AppDelegate
import AppLovinSDK
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ALSdk.shared()!.mediationProvider = "max"
ALSdk.shared()!.initializeSdk { (configuration: ALSdkConfiguration) in
// SDK has been initialized, start loading ads
}
return true
}
// 3. Set up privacy settings (before initialization)
let privacySettings = ALPrivacySettings()
privacySettings.hasUserConsent = true // Set based on user consent
privacySettings.isAgeRestrictedUser = false // Set based on user age
privacySettings.isDoNotSell = false // Set for CCPA compliance
Basic Integration Steps – Android
// 1. Add AppLovin SDK to your project
// In your build.gradle (app level):
dependencies {
implementation 'com.applovin:applovin-sdk:11.11.3'
}
// 2. Initialize the SDK in your Application class
import com.applovin.sdk.AppLovinSdk;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
AppLovinSdk.getInstance(this).setMediationProvider("max");
AppLovinSdk.initializeSdk(this, new AppLovinSdk.SdkInitializationListener() {
@Override
public void onSdkInitialized(AppLovinSdkConfiguration config) {
// SDK has been initialized, start loading ads
}
});
}
}
// 3. Add your SDK key to AndroidManifest.xml
// Inside the <application> tag:
<meta-data android:name="applovin.sdk.key"
android:value="YOUR_SDK_KEY" />
// 4. Set up privacy settings (before initialization)
AppLovinPrivacySettings.setHasUserConsent(true, context); // Set based on user consent
AppLovinPrivacySettings.setIsAgeRestrictedUser(false, context); // Set based on user age
AppLovinPrivacySettings.setDoNotSell(false, context); // Set for CCPA compliance
Basic Integration Steps – Unity
// 1. Import the AppLovin MAX SDK Unity package
// 2. Initialize the SDK in a MonoBehaviour script
using AppLovinMax;
private const string MaxSdkKey = "YOUR_APPLOVIN_SDK_KEY";
void Start()
{
MaxSdkCallbacks.OnSdkInitializedEvent += (MaxSdkBase.SdkConfiguration sdkConfiguration) => {
// SDK has been initialized, start loading ads
};
// Set privacy settings
MaxSdk.SetHasUserConsent(true); // Set based on user consent
MaxSdk.SetIsAgeRestrictedUser(false); // Set based on user age
MaxSdk.SetDoNotSell(false); // Set for CCPA compliance
// Initialize the SDK
MaxSdk.SetSdkKey(MaxSdkKey);
MaxSdk.InitializeSdk();
}
Ad Format Implementation
Banner Ads
| Property | Details |
|---|
| Ad Sizes | Standard: 320×50, Leader: 728×90, MREC: 300×250 |
| Placements | Top or bottom of screen, or custom position |
| Refresh Rate | Default: 60 seconds (configurable) |
| Load Time | Typically 1-2 seconds |
iOS Banner Implementation
import AppLovinSDK
class ViewController: UIViewController, MAAdViewAdDelegate {
var adView: MAAdView!
override func viewDidLoad() {
super.viewDidLoad()
// Create banner ad
adView = MAAdView(adUnitIdentifier: "YOUR_AD_UNIT_ID")
adView.delegate = self
// Set up ad parameters
adView.frame = CGRect(x: 0, y: view.frame.size.height - 50, width: view.frame.size.width, height: 50)
// Load the ad
view.addSubview(adView)
adView.loadAd()
}
// MARK: - MAAdViewAdDelegate
func didLoad(_ ad: MAAd) {
// Banner ad loaded
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// Banner ad failed to load
}
func didClick(_ ad: MAAd) {
// Banner ad clicked
}
}
Android Banner Implementation
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdViewAdListener;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.ads.MaxAdView;
public class MainActivity extends AppCompatActivity implements MaxAdViewAdListener {
private MaxAdView adView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create banner ad
adView = new MaxAdView("YOUR_AD_UNIT_ID", this);
adView.setListener(this);
// Set up ad parameters
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int heightDp = MaxAdFormat.BANNER.getAdaptiveSize(this).getHeight();
int heightPx = AppLovinSdkUtils.dpToPx(this, heightDp);
adView.setLayoutParams(new FrameLayout.LayoutParams(width, heightPx));
// Add to view hierarchy and load
ViewGroup rootView = findViewById(R.id.main_container);
rootView.addView(adView);
adView.loadAd();
}
// MaxAdViewAdListener implementation
@Override
public void onAdLoaded(MaxAd ad) {
// Banner ad loaded
}
@Override
public void onAdLoadFailed(String adUnitId, MaxError error) {
// Banner ad failed to load
}
@Override
public void onAdClicked(MaxAd ad) {
// Banner ad clicked
}
// Other required listener methods...
}
Interstitial Ads
| Property | Details |
|---|
| Format | Full-screen ads shown at natural transition points |
| Frequency Cap | Recommended: Every 3-4 minutes (configurable) |
| Best Practices | Show between levels, after completing tasks |
| Load Time | Typically 1-3 seconds (preload recommended) |
iOS Interstitial Implementation
import AppLovinSDK
class ViewController: UIViewController, MAAdDelegate {
var interstitialAd: MAInterstitialAd!
override func viewDidLoad() {
super.viewDidLoad()
// Create interstitial ad
interstitialAd = MAInterstitialAd(adUnitIdentifier: "YOUR_AD_UNIT_ID")
interstitialAd.delegate = self
// Load the ad
interstitialAd.load()
}
func showInterstitialIfReady() {
if interstitialAd.isReady {
interstitialAd.show()
}
}
// MARK: - MAAdDelegate
func didLoad(_ ad: MAAd) {
// Interstitial ad loaded
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// Interstitial ad failed to load
// Retry with exponential backoff
retryAttempt += 1
let delaySec = pow(2.0, min(6.0, retryAttempt))
DispatchQueue.main.asyncAfter(deadline: .now() + delaySec) {
self.interstitialAd.load()
}
}
func didDisplay(_ ad: MAAd) {
// Interstitial ad displayed
retryAttempt = 0
}
func didHide(_ ad: MAAd) {
// Interstitial ad hidden
interstitialAd.load() // Load the next ad
}
func didClick(_ ad: MAAd) {
// Interstitial ad clicked
}
// Other delegate methods...
private var retryAttempt = 0
}
Android Interstitial Implementation
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdListener;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.ads.MaxInterstitialAd;
public class MainActivity extends AppCompatActivity implements MaxAdListener {
private MaxInterstitialAd interstitialAd;
private int retryAttempt = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create interstitial ad
interstitialAd = new MaxInterstitialAd("YOUR_AD_UNIT_ID", this);
interstitialAd.setListener(this);
// Load the ad
interstitialAd.loadAd();
}
public void showInterstitialIfReady() {
if (interstitialAd.isReady()) {
interstitialAd.showAd();
}
}
// MaxAdListener implementation
@Override
public void onAdLoaded(MaxAd ad) {
// Interstitial ad loaded
retryAttempt = 0;
}
@Override
public void onAdLoadFailed(String adUnitId, MaxError error) {
// Interstitial ad failed to load
// Retry with exponential backoff
retryAttempt++;
long delayMillis = (long) Math.pow(2, Math.min(6, retryAttempt)) * 1000;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
interstitialAd.loadAd();
}
}, delayMillis);
}
@Override
public void onAdDisplayed(MaxAd ad) {
// Interstitial ad displayed
}
@Override
public void onAdHidden(MaxAd ad) {
// Interstitial ad hidden
interstitialAd.loadAd(); // Load the next ad
}
@Override
public void onAdClicked(MaxAd ad) {
// Interstitial ad clicked
}
// Other required listener methods...
}
Rewarded Ads
| Property | Details |
|---|
| Format | Full-screen ads that reward users for watching |
| Reward Types | Virtual currency, extra lives, power-ups, content unlock |
| Completion Rate | Typically 70-85% (users choose to watch) |
| Best Practices | Implement as user choice, clearly communicate reward |
iOS Rewarded Implementation
import AppLovinSDK
class ViewController: UIViewController, MARewardedAdDelegate {
var rewardedAd: MARewardedAd!
override func viewDidLoad() {
super.viewDidLoad()
// Create rewarded ad
rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: "YOUR_AD_UNIT_ID")
rewardedAd.delegate = self
// Load the ad
rewardedAd.load()
}
func showRewardedIfReady() {
if rewardedAd.isReady {
rewardedAd.show()
}
}
// MARK: - MARewardedAdDelegate
func didLoad(_ ad: MAAd) {
// Rewarded ad loaded
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// Rewarded ad failed to load
// Retry with exponential backoff similar to interstitial
}
func didStartRewardedVideo(for ad: MAAd) {
// Rewarded ad started playing
}
func didCompleteRewardedVideo(for ad: MAAd) {
// Rewarded ad completed playing
}
func didRewardUser(for ad: MAAd, with reward: MAReward) {
// User earned reward
let rewardAmount = reward.amount
let rewardType = reward.label
// Provide reward to user
}
func didHide(_ ad: MAAd) {
// Rewarded ad hidden
rewardedAd.load() // Load the next ad
}
// Other delegate methods...
}
Android Rewarded Implementation
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.MaxReward;
import com.applovin.mediation.MaxRewardedAdListener;
import com.applovin.mediation.ads.MaxRewardedAd;
public class MainActivity extends AppCompatActivity implements MaxRewardedAdListener {
private MaxRewardedAd rewardedAd;
private int retryAttempt = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create rewarded ad
rewardedAd = MaxRewardedAd.getInstance("YOUR_AD_UNIT_ID", this);
rewardedAd.setListener(this);
// Load the ad
rewardedAd.loadAd();
}
public void showRewardedIfReady() {
if (rewardedAd.isReady()) {
rewardedAd.showAd();
}
}
// MaxRewardedAdListener implementation
@Override
public void onRewardedVideoStarted(MaxAd ad) {
// Rewarded ad started playing
}
@Override
public void onRewardedVideoCompleted(MaxAd ad) {
// Rewarded ad completed playing
}
@Override
public void onUserRewarded(MaxAd ad, MaxReward reward) {
// User earned reward
int rewardAmount = reward.getAmount();
String rewardType = reward.getLabel();
// Provide reward to user
}
@Override
public void onAdLoaded(MaxAd ad) {
// Rewarded ad loaded
retryAttempt = 0;
}
@Override
public void onAdLoadFailed(String adUnitId, MaxError error) {
// Rewarded ad failed to load
// Retry with exponential backoff
}
@Override
public void onAdHidden(MaxAd ad) {
// Rewarded ad hidden
rewardedAd.loadAd(); // Load the next ad
}
// Other required listener methods...
}
App Open Ads
| Property | Details |
|---|
| Format | Full-screen ads shown during app launch or resume |
| Best Placement | App launch, app resume after background |
| Frequency Cap | Recommended: Once per 4+ hours |
| Important Note | Respect user experience; avoid disrupting critical flows |
iOS App Open Implementation
import AppLovinSDK
class AppOpenManager: NSObject, MAAdDelegate {
static let shared = AppOpenManager()
private var appOpenAd: MAAppOpenAd?
private var loadTime: Date?
private override init() {
super.init()
appOpenAd = MAAppOpenAd(adUnitIdentifier: "YOUR_AD_UNIT_ID")
appOpenAd?.delegate = self
}
func loadAd() {
appOpenAd?.load()
}
func showAdIfReady() {
// Check if ad exists and is not expired (loaded more than 4 hours ago)
if appOpenAd?.isReady == true && isAdNotExpired() {
appOpenAd?.show()
} else {
loadAd()
}
}
private func isAdNotExpired() -> Bool {
guard let loadTime = loadTime else { return false }
let now = Date()
let timeIntervalSinceLoad = now.timeIntervalSince(loadTime)
return timeIntervalSinceLoad <= 4 * 3600 // 4 hours
}
// MARK: - MAAdDelegate
func didLoad(_ ad: MAAd) {
loadTime = Date()
}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// Handle load failure
}
func didDisplay(_ ad: MAAd) {
// App open ad displayed
}
func didHide(_ ad: MAAd) {
// App open ad hidden
loadAd() // Load next ad
}
// Other delegate methods...
}
// In AppDelegate:
func applicationDidBecomeActive(_ application: UIApplication) {
AppOpenManager.shared.showAdIfReady()
}
Android App Open Implementation
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdListener;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.ads.MaxAppOpenAd;
public class AppOpenManager implements MaxAdListener, LifecycleObserver {
private static AppOpenManager instance;
private MaxAppOpenAd appOpenAd;
private long loadTime = 0;
private Activity currentActivity;
public static AppOpenManager getInstance() {
if (instance == null) {
instance = new AppOpenManager();
}
return instance;
}
public void init(Application application) {
appOpenAd = new MaxAppOpenAd("YOUR_AD_UNIT_ID", application);
appOpenAd.setListener(this);
// Register lifecycle callbacks
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
showAdIfReady();
}
public void loadAd() {
appOpenAd.loadAd();
}
public void showAdIfReady() {
// Check if ad exists and is not expired (loaded more than 4 hours ago)
if (appOpenAd.isReady() && !isAdExpired()) {
appOpenAd.showAd();
} else {
loadAd();
}
}
private boolean isAdExpired() {
long now = System.currentTimeMillis();
long hoursElapsed = (now - loadTime) / (60 * 60 * 1000);
return hoursElapsed > 4; // 4 hours
}
@Override
public void onAdLoaded(MaxAd ad) {
loadTime = System.currentTimeMillis();
}
@Override
public void onAdHidden(MaxAd ad) {
loadAd(); // Load next ad
}
// Other required listener methods...
}
Native Ads
| Property | Details |
|---|
| Format | Customizable ads that match app UI/UX |
| Components | Icon, headline, description, CTA button, media view |
| Templates | Grid, list, carousel, custom layouts |
| Best Practices | Match app’s design language, label as “Ad” or “Sponsored” |
iOS Native Ad Implementation
import AppLovinSDK
class NativeAdViewController: UIViewController, MANativeAdDelegate, MAAdViewAdDelegate {
var nativeAdLoader: MANativeAdLoader!
var nativeAd: MAAd?
@IBOutlet weak var nativeAdView: MANativeAdView!
override func viewDidLoad() {
super.viewDidLoad()
// Create native ad loader
nativeAdLoader = MANativeAdLoader(adUnitIdentifier: "YOUR_AD_UNIT_ID")
nativeAdLoader.nativeAdDelegate = self
nativeAdLoader.adViewAdDelegate = self
// Load native ad
nativeAdLoader.loadAd(into: nativeAdView)
}
// MARK: - MANativeAdDelegate
func didLoadNativeAd(_ nativeAdView: MANativeAdView?, for ad: MAAd) {
// Native ad loaded
nativeAd = ad
// Add nativeAdView to your view hierarchy if using manual integration
if let adView = nativeAdView {
// Add adView to container
}
}
func didFailToLoadNativeAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) {
// Native ad failed to load
}
// MARK: - MAAdViewAdDelegate
func didClick(_ ad: MAAd) {
// Native ad clicked
}
}
Android Native Ad Implementation
import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxError;
import com.applovin.mediation.nativeAds.MaxNativeAdListener;
import com.applovin.mediation.nativeAds.MaxNativeAdLoader;
import com.applovin.mediation.nativeAds.MaxNativeAdView;
public class NativeAdActivity extends AppCompatActivity {
private MaxNativeAdLoader nativeAdLoader;
private MaxAd nativeAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_native_ad);
// Create native ad loader
nativeAdLoader = new MaxNativeAdLoader("YOUR_AD_UNIT_ID", this);
nativeAdLoader.setNativeAdListener(new MaxNativeAdListener() {
@Override
public void onNativeAdLoaded(final MaxNativeAdView nativeAdView, final MaxAd ad) {
// Native ad loaded
// Clean up previous ad
if (nativeAd != null) {
nativeAdLoader.destroy(nativeAd);
}
nativeAd = ad;
// Add nativeAdView to your view hierarchy
FrameLayout adContainer = findViewById(R.id.native_ad_container);
adContainer.removeAllViews();
adContainer.addView(nativeAdView);
}
@Override
public void onNativeAdLoadFailed(final String adUnitId, final MaxError error) {
// Native ad failed to load
}
@Override
public void onNativeAdClicked(final MaxAd ad) {
// Native ad clicked
}
});
// Load native ad
nativeAdLoader.loadAd();
}
@Override
protected void onDestroy() {
if (nativeAd != null) {
nativeAdLoader.destroy(nativeAd);
}
super.onDestroy();
}
}
MAX Mediation
Mediation Setup
- Create a MAX account at AppLovin.com
- Create an app in the MAX dashboard
- Set up ad networks:
- Select desired ad networks
- Follow network-specific setup instructions
- Enter credentials for each network
- Create ad units for each format
- Set up waterfall (automatic or manual priority)
- Configure bidding for supported networks
Supported Ad Networks
| Network | Banner | Interstitial | Rewarded | Native | App Open |
|---|
| AdColony | ✓ | ✓ | ✓ | ✓ | ✗ |
| AdMob | ✓ | ✓ | ✓ | ✓ | ✓ |
| AppLovin Exchange | ✓ | ✓ | ✓ | ✓ | ✓ |
| Chartboost | ✓ | ✓ | ✓ | ✓ | ✗ |
| Facebook (Meta Audience Network) | ✓ | ✓ | ✓ | ✓ | ✗ |
| ironSource | ✓ | ✓ | ✓ | ✓ | ✗ |
| Mintegral | ✓ | ✓ | ✓ | ✓ | ✗ |
| Tapjoy | ✗ | ✓ | ✓ | ✗ | ✗ |
| Unity Ads | ✓ | ✓ | ✓ | ✗ | ✗ |
| Vungle | ✓ | ✓ | ✓ | ✓ | ✗ |
| Yahoo | ✓ | ✓ | ✓ | ✓ | ✗ |
Bidding vs Waterfall
| Feature | Bidding | Waterfall |
|---|
| How It Works | Real-time auction among all networks | Sequential calls to networks in order of priority |
| Advantages | Higher revenue, faster load times, less latency | More control over ad sources |
| Disadvantages | Limited network support | Potential revenue loss, higher latency |
| Setup Complexity | Simple (automatic optimization) | Complex (manual optimization) |
| Best For | Most apps, especially high-volume apps | Special cases requiring manual control |
Network-Specific Setup Tips
| Network | Required IDs | Special Considerations |
|---|
| AdMob | App ID, Ad Unit IDs | Requires Google Play Services, separate iOS/Android setup |
| Facebook | App ID, Placement IDs | Requires Facebook App ID even for ads only |
| Unity Ads | Game ID, Placement IDs | Separate iOS/Android credentials |
| ironSource | App Key | Single credential for all formats |
| Vungle | App ID, Placement IDs | Separate reporting dashboard |
Reporting & Analytics
Key Metrics
| Metric | Description | Formula |
|---|
| ARPDAU | Average Revenue Per Daily Active User | Daily revenue ÷ Daily active users |
| eCPM | Effective Cost Per Mille (Revenue per 1000 impressions) | (Revenue ÷ Impressions) × 1000 |
| Fill Rate | Percentage of ad requests that receive an ad | (Impressions ÷ Requests) × 100 |
| CTR | Click-Through Rate | (Clicks ÷ Impressions) × 100 |
| Completion Rate | Percentage of video ads watched to completion | (Completions ÷ Starts) × 100 |
Accessing Reports
- Log in to AppLovin Dashboard
- Select your app
- Navigate to “Reporting” section
- Select desired date range
- Choose metrics to display
- Filter by ad format, network, country, etc.
- Export data if needed (CSV, Excel)
Real-time Monitoring
- Use “Analytics” tab for real-time data
- Set up alerts for performance drops
- Monitor network-specific issues
- Track mediation performance
Optimization Best Practices
Ad Implementation
| Tip | Impact |
|---|
| Preload ads before showing them | Reduces user wait time |
| Implement smart retries with exponential backoff | Improves fill rate |
| Test ad placements extensively | Improves user experience |
| Cache ads when possible | Faster display, better user experience |
| Implement proper lifecycle management | Prevents memory leaks, crashes |
Revenue Optimization
| Tip | Impact |
|---|
| Enable MAX bidding for all supported networks | 10-30% revenue increase |
| Test frequency caps to find optimal balance | Balances user experience and revenue |
| Optimize waterfall for non-bidding networks | 5-15% revenue increase |
| Implement A/B testing for ad strategies | Data-driven optimization |
| Monitor eCPM trends by network | Identify opportunities for adjustment |
User Experience
| Tip | Impact |
|---|
| Avoid ads during critical gameplay | Reduces negative reviews |
| Clearly indicate rewarded value | Increases completion rate |
| Implement loading indicators for ads | Sets user expectations |
| Respect natural break points in app flow | Improves user retention |
| Gradually introduce ad formats to new users | Better long-term engagement |
Common Issues & Troubleshooting
Ad Not Showing
| Possible Cause | Solution |
|---|
| Ad not loaded | Ensure ad.isReady() returns true before showing |
| Test mode enabled | Check if device is in test mode in dashboard |
| No fill | Implement retry logic with backoff |
| Network issues | Check device connectivity |
| Ad limit reached | Check frequency cap settings |
SDK Integration Issues
| Issue | Solution |
|---|
| Compatibility conflicts | Check for duplicate ad SDKs or version conflicts |
| Missing dependencies | Review required dependencies in documentation |
| ProGuard issues (Android) | Add proper ProGuard rules |
| Thread exceptions | Ensure ad operations run on main thread |
| Initialization failure | Verify SDK key is correct |
Testing Ads
| Method | How To |
|---|
| Test mode | Enable in dashboard for specific devices |
| Test ads | Use special test ad units for d |