Advanced Settings
Ad Placements
You can set a placement name for each ad unit (for example, “Rewarded VideoLevels”, “INTER_levelEnd”, or “RewardedVideoCoinStore”). This can help you aggregate statistics for different placement categories. The following snippets show you how to set the placement name for various ad formats.
Banners / MRECs
adView.placement = @"«placement»";[adView loadAd];
adView.placement = "«placement»"adView.loadAd()
Interstitials
[interstitialAd showAdForPlacement: @"«placement»"];
interstitial.show(forPlacement: "«placement»")
Rewarded Ads
[rewardedAd showAdForPlacement: @"«placement»"];
rewardedAd.show(forPlacement: "«placement»")
Native Ads
nativeAdLoader.placement = @"«placement»";
nativeAdLoader.placement = "«placement»"
Native Ads (Ad Placer)
MAAdPlacerSettings *settings = [MAAdPlacerSettings settingsWithAdUnitIdentifier: @"«ad-unit-ID»"];settings.placement = @"«placement»";
let settings = MAAdPlacerSettings(adUnitIdentifier: "«ad-unit-ID»")settings.placement = "«placement»"
Mute Audio
You can mute audio for some mediated SDK networks when you launch your app. The networks that support this functionality via the AppLovin SDK are Google bidding and Google AdMob, AppLovin, DT Exchange, Google Ad Manager, LINE, Mintegral, Tencent, and Verve. For other networks, consult your network’s account team to learn whether this functionality is available and how to access it.
The following code snippets show how you mute audio on those networks that support this feature:
ALSdk *sdk = [ALSdk shared];sdk.settings.muted = YES; // to mutesdk.settings.muted = NO; // to unmute
let sdk = ALSdk.shared()sdk.settings.isMuted = true /// to mutesdk.settings.isMuted = false /// to unmute
Enable Verbose Logging
There are two ways to enable verbose logging:
Programmatically
You can enable verbose logging by setting the flag isVerboseLoggingEnabled
to YES
in the settings object of the SDK:
[ALSdk shared].settings.verboseLoggingEnabled = YES;
ALSdk.shared().settings.isVerboseLoggingEnabled = true
Info.plist
You can also enable verbose logging by setting AppLovinVerboseLoggingOn
to YES
in your application’s Info.plist
:
Verification
To verify that you enabled verbose logs successfully, check for the line that reads Verbose Logging On: true
in the initialization section of the AppLovin SDK logs:
AppLovin SDKVersion: 11.4.2⋮Verbose Logging On: true⋮
AppLovin SDK tags its logs with the tag “/AppLovinSdk: [AppLovinSdk]
”.
Creative ID and Network Name
You can retrieve the creative ID and the network name of displayed ads from various mediated networks. Refer to the Creative Debugger documentation for more information.
DSP Name
You can retrieve the name of the DSP for a MAX ad served from AppLovin Exchange with code like the following:
- (void)didLoadAd:(MAAd *)ad{ NSLog(@"AppLovin Exchange DSP name: %@", ad.DSPName);}
func didLoad(_ ad: MAAd){ print("AppLovin Exchange DSP name: (ad.dspName?)")}
Impression-Level User Revenue API
Starting in SDK version 10.3.0, you can access impression-level user revenue data on the client side. You can use this data to compare different sources and campaigns. You can also access this data by using the MAX User Revenue API. MMPs who want to access this data should refer to the Impression-Level User Revenue API for MMPs page.
You can share impression-level ad revenue data with your mobile measurement partner of choice, such as Adjust for all supported networks.
You can retrieve the revenue amount in all ad lifecycle callbacks. The following example shows how to do this within the “ad revenue paid” callback:
- (void)didPayRevenueForAd:(MAAd *)ad{ double revenue = ad.revenue; // In USD
// Miscellaneous data NSString *countryCode = [ALSdk shared].configuration.countryCode; // "US" for the United States, etc - Note: Do not confuse this with currency code which is "USD" NSString *networkName = ad.networkName; // Display name of the network that showed the ad NSString *adUnitId = ad.adUnitIdentifier; // The MAX Ad Unit ID MAAdFormat *adFormat = ad.format; // The ad format of the ad (e.g. BANNER, MREC, INTERSTITIAL, REWARDED) NSString *placement = ad.placement; // The placement this ad's postbacks are tied to NSString *networkPlacement = ad.networkPlacement; // The placement ID from the network that showed the ad}
func didPayRevenue(_ ad: MAAd){ let revenue = ad.revenue // In USD
// Miscellaneous data let countryCode = ALSdk.shared().configuration.countryCode // "US" for the United States, etc - Note: Do not confuse this with currency code which is "USD" let networkName = ad.networkName // Display name of the network that showed the ad let adUnitId = ad.adUnitIdentifier // The MAX Ad Unit ID let adFormat = ad.format // The ad format of the ad (e.g. BANNER, MREC, INTERSTITIAL, REWARDED) let placement = ad.placement // The placement this ad's postbacks are tied to let networkPlacement = ad.networkPlacement // The placement ID from the network that showed the ad}
You can also retrieve a precision evaluation for the revenue value, as shown in the following example:
NSString *revenuePrecision = ad.revenuePrecision;
let revenuePrecision = ad.revenuePrecision
This precision takes one of the following values:
"publisher_defined"
- the revenue amount is the price assigned by the publisher
"exact"
- the revenue amount is the result of a real-time auction
"estimated"
- the revenue amount is based on Auto-CPM or FB Bidding estimates
"undefined"
- no revenue amount is defined and there is not enough data to estimate
""
- revenue and precision are not valid (for example, in test mode)
Establishing Ad Request Callbacks
You can listen for when an ad request is made by setting a MAAdRequestDelegate
, implementing its [didStartAdRequestForAdUnitIdentifier:]
method, and setting that delegate to requestDelegate
.
The following example shows how to implement such an “ad request started” callback:
- (void)didStartAdRequestForAdUnitIdentifier:(NSString *)adUnitIdentifier{ // Ad request started here}
func didStartAdRequest(forAdUnitIdentifier adUnitIdentifier: String){ // Ad request started here}
Selective Init
You can initialize the SDK with specific ad units. If you do so, the SDK only initializes those networks that you have configured for the ad units you specify. (If you do not specify any ad units, the SDK assumes the current session needs all of your ad units. If so, it initializes all networks that you have configured for them.) The following example shows how you implement this feature:
ALSdkSettings *settings = [[ALSdkSettings alloc] init];settings.initializationAdUnitIdentifiers = @[@"«ad-unit-ID-1»", @"«ad-unit-ID-2»"];
ALSdk *sdk = [ALSdk sharedWithSettings: settings];sdk.mediationProvider = @"max";[sdk initializeSdkWithCompletionHandler:^(ALSdkConfiguration *configuration) { ⋮}];
let settings = ALSdkSettings()settings.initializationAdUnitIdentifiers = ["«ad-unit-ID-1»", "«ad-unit-ID-2»"]
let sdk = ALSdk.shared(with: settings)sdk.mediationProvider = "max"sdk.initializeSdk { _ in ⋮}
Starting with SDK version 12.3.1, and its new initialization API, you can specify your ad units in the ALSdkInitializationConfiguration
:
ALSdkInitializationConfiguration *initConfig = [ALSdkInitializationConfiguration configurationWithSdkKey:«your-SDK-key» builderBlock:^(ALSdkInitializationConfigurationBuilder *builder) { builder.mediationProvider = ALMediationProviderMAX; builder.adUnitIdentifiers = @[@"«ad-unit-ID-1»", @"«ad-unit-ID-2»"]; }];
[[ALSdk shared] initializeWithConfiguration: initConfig completionHandler:^(ALSdkConfiguration *sdkConfig) { ⋮}];
let initConfig = ALSdkInitializationConfiguration.configuration( withSdkKey: "«your-SDK-key»") { builder in builder.mediationProvider = ALMediationProviderMAX builder.adUnitIdentifiers = ["«ad-unit-ID-1»", "«ad-unit-ID-2»"]}
ALSdk.shared().initialize(with: initConfig) { sdkConfig in ⋮}
Waterfall Information API
The Waterfall Information API tells you about the current waterfall for an ad (one that has loaded or failed to load). The API returns the ad load state, latency, credentials, and mediated network information for each ad in the waterfall. If an ad in the waterfall fails to load, the API provides error information.
This API is supported as of iOS SDK version 10.3.7.
AdLoadState Values
value | explanation |
---|---|
0 | Ad Load Not Attempted |
1 | Ad Loaded |
2 | Ad Failed To Load |
Example
- Objective-C
- Swift
- Output
- (void)didLoadAd:(MAAd *)ad{ NSLog(@"Waterfall Name: %@ and Test Name: %@", ad.waterfall.name, ad.waterfall.testName); NSLog(@"Waterfall latency was: %f seconds", ad.waterfall.latency);
for (MANetworkResponseInfo *networkResponse in ad.waterfall.networkResponses) { NSLog(@"Network -> %@", networkResponse.mediatedNetwork); NSLog(@"...adLoadState: %ld", (long) networkResponse.adLoadState); NSLog(@"...latency: %f seconds", networkResponse.latency); NSLog(@"...credentials: %@", networkResponse.credentials); if (networkResponse.error) { NSLog(@"...error: %@", networkResponse.error); } }}
- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error{ if (!error.waterfall) { return; }
MAAdWaterfallInfo *waterfall = error.waterfall; NSLog(@"Waterfall Name: %@ and Test Name: %@", waterfall.name, waterfall.testName); NSLog(@"Waterfall latency was: %f seconds", waterfall.latency);
for (MANetworkResponseInfo *networkResponse in waterfall.networkResponses) { NSLog(@"Network -> %@", networkResponse.mediatedNetwork); NSLog(@"...latency: %f seconds", networkResponse.latency); NSLog(@"...credentials: %@", networkResponse.credentials); if (networkResponse.error) { NSLog(@"...error: %@", networkResponse.error); } }}
func didLoad(_ ad: MAAd){ print("Waterfall Name: (ad.waterfall.name) and Test Name: (ad.waterfall.testName)") print("Waterfall latency was: (ad.waterfall.latency) seconds")
for networkResponse in ad.waterfall.networkResponses { print("Network -> (networkResponse.mediatedNetwork)") print("...adLoadState: (networkResponse.adLoadState.rawValue)") print("...latency: (networkResponse.latency) seconds") print("...credentials: (networkResponse.credentials)") if let networkError = networkResponse.error { print("...error: (networkError)") } }}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError){ guard let waterfall = error.waterfall else { return } print("Waterfall Name: (waterfall.name) and Test Name: (waterfall.testName)") print("Waterfall latency was: (waterfall.latency) seconds")
for networkResponse in waterfall.networkResponses { print("Network -> (networkResponse.mediatedNetwork)") print("...latency: (networkResponse.latency) seconds") print("...credentials: (networkResponse.credentials)") if let networkError = networkResponse.error { print("...error: (networkError)") } }}
Waterfall Name: Default Waterfall and Test Name: ControlWaterfall latency was: 4.1710309982299805 secondsNetwork -> [MAMediatedNetworkInfo: name=Fyber, adapterClassName=ALInneractiveMediationAdapter, adapterVersion=8.1.1.0, sdkVersion=8.1.1]...adLoadState: 2...latency: 0.0057220458984375 seconds...credentials: ["placement_id": 235786, "app_id": 106516]...error: [MAAdapterError: errorCode=-5202, errorMessage="Invalid Configuration", thirdPartySdkErrorCode=495, thirdPartySdkErrorMessage="The operation couldn’t be completed. (There is no 235786 spot ID in current app config error 495.)"]
Network -> [MAMediatedNetworkInfo: name=AdMob, adapterClassName=ALGoogleMediationAdapter, adapterVersion=8.13.0.2, sdkVersion=afma-sdk-i-v8.13.0]...adLoadState: 1...latency: 3.0903170108795166 seconds...credentials: ["app_id": ca-app-pub-3555987499620362~1761536714, "event_id": 7f40fb8a9d64cbf1156909a514e53d8181fcf7a3, "placement_id": ca-app-pub-3555987499620362/1638443478]
Network -> [MAMediatedNetworkInfo: name=ironSource, adapterClassName=ALIronSourceMediationAdapter, adapterVersion=7.1.12.0.0, sdkVersion=7.1.12]...adLoadState: 0...latency: -1.0 seconds...credentials: ["placement_id": 1082713, "app_key": 882393cd]
Note that if the waterfall is empty, MAError.waterfall
returns nil
and so you cannot interrogate the waterfall properties.
However, you can still retrieve the ad load latency for an empty waterfall via requestLatency
:
- (void)didLoadAd:(MAAd *)ad{ NSLog(@"Succesful ad load latency: %f seconds", ad.requestLatency);}
- (void)didFailToLoadAdForAdUnitIdentifier:(NSString *)adUnitIdentifier withError:(MAError *)error{ NSLog("Failed ad load latency: %f seconds", error.requestLatency);}
func didLoad(_ ad: MAAd){ print("Successful ad load latency: (ad.requestLatency) seconds")}
func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError){ print("Failed ad load latency: (error.requestLatency) seconds")}
Customize Banner / MREC Ad Refresh
You can customize banner and MREC ad refresh intervals directly in your integration, just as you can configure them in the Ad Unit UI. The minimum refresh interval is 10 seconds. The maximum refresh interval is 120 seconds. Values outside of these limits are ignored. The following code samples show you how to customize these refresh intervals:
// Where adView is an instance of MAAdView[adView setExtraParameterForKey: @"ad_refresh_seconds" value: «ad-refresh-rate»];
// Where adView is an instance of MAAdViewadView.setExtraParameter("ad_refresh_seconds", «ad-refresh-rate»)
Audio Settings
To prevent interstitial and rewarded ad audio from interfering with your app’s background audio, AppLovin recommends that you stop your app’s background audio before you show an ad. You can resume your app’s background audio after you hide the ad.
- (void)didDisplayAd:(MAAd *)ad{ // Pause your app's background audio}
- (void)didHideAd:(MAAd *)ad{ // Resume your app's background audio}
func didDisplay(_ ad: MAAd){ // Pause your app's background audio}
func didHide(_ ad: MAAd){ // Resume your app's background audio}