iOS SDK Configuration
Initializing the SDK
SDK Initialization
Initialize the SDK as early as possible in your app lifecycle, preferably in AppDelegate.
Basic Initialization
- Swift
- Objective-C
import EmpowerMobileAds
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize the SDK with your app identifier
let config = EMAConfiguration(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
EMAManager.shared.initialize(configuration: config)
return true
}
}
EMAConfiguration is a Swift struct and is not available in Objective-C. Use the
initializeWithAppAdIdentifier: family of methods instead.
@import EmpowerMobileAds;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize the SDK with your app identifier
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"];
return YES;
}
@end
Initialization with Options
- Swift
- Objective-C
// Initialize with debug logging enabled
let config = EMAConfiguration(
appAdIdentifier: "YOUR_APP_AD_IDENTIFIER",
logLevel: .all
)
EMAManager.shared.initialize(configuration: config)
Or using the convenience initializer for minimal setup:
EMAManager.shared.initialize(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
// Initialize with options
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"
adAppVersion:@"1"
variant:@""
logLevel:LogLevelAll
nonPersonalizedAds:NO];
Or using the minimal initializer:
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"];
appAdIdentifier: Your app identifier which will be provided by us.
EMAConfiguration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
appAdIdentifier | String | Required | The app identifier provided by Empower |
adAppVersion | String | "1" | The ad app version |
variant | String | "" | A/B test variant string |
logLevel | LogLevel | .none | Logging level for SDK debug output |
privacyMode | EMAPrivacyMode | .automatic | GDPR / consent mode: .automatic, .nonPersonalized, or .manual (see GDPR Compliance) |
ext | String | "" | Optional external parameter |
customUserId | String? | nil | Custom user identifier |
customParameters | [String: String]? | nil | Additional custom parameters for ad requests |
appLovinSdkKey | String? | nil | AppLovin SDK key (required if using AppLovin mediation) |
Factory Methods
Swift only. The factory methods and the builder pattern below operate on the
EMAConfigurationstruct, which is not available in Objective-C. Objective-C apps configure the SDK through theinitializeWithAppAdIdentifier:adAppVersion:variant:logLevel:nonPersonalizedAds:method shown above, and adjust the rest at runtime viaEMASettings.shared.
// Basic configuration with defaults
let config = EMAConfiguration.basic(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
// Debug configuration with .all log level
let config = EMAConfiguration.debug(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
// GDPR-compliant configuration with non-personalized ads enabled
let config = EMAConfiguration.gdprCompliant(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
Builder Pattern
You can chain configuration options using the builder pattern:
let config = EMAConfiguration.basic(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
.with(logLevel: .all)
.with(variant: "variant_b")
.with(privacyMode: .nonPersonalized)
.with(customUserId: "user_123")
.with(customParameters: ["category": "news"])
.with(appLovinSdkKey: "YOUR_APPLOVIN_SDK_KEY")
EMAManager.shared.initialize(configuration: config)
Runtime Settings
You can modify certain settings at runtime via EMASettings.shared:
| Setting | Type | Default | Description |
|---|---|---|---|
logLevel | LogLevel | .none | Log verbosity |
isAdsDisabled | Bool | false | Disable all ads (e.g., for premium users) |
isAdsNonPersonalized | Bool | false | Request non-personalized ads |
Log Levels
| Swift | Objective-C | Description |
|---|---|---|
.none | LogLevelNone | Disables all logging |
.all | LogLevelAll | Logs all messages including debug information |
.normal | LogLevelNormal | Standard logging level for general information |
.error | LogLevelError | Logs errors only |
.warning | LogLevelWarning | Logs warnings and errors |
Runtime settings are identical in both languages via
EMASettings.shared, e.g.EMASettings.shared.logLevel = .all(Swift) /EMASettings.shared.logLevel = LogLevelAll;(Objective-C).
Impression Level Ad Revenue (ILRD) Integration
Available since EmpowerMobileAds SDK 9.4.9
Overview
Impression Level Ad Revenue (ILRD) lets you receive per-impression revenue data from AppLovin MAX and Google (AdMob / Ad Manager). Each time an ad generates a paid impression, the SDK calls your delegate with a structured EMAAdRevenue object containing the revenue details.
Supported ad formats: Banner, Interstitial, Rewarded, App Open
1. Implement EMAAdRevenueDelegate
extension YourViewController: EMAAdRevenueDelegate {
func empowerAdRevenueReceived(_ revenue: EMAAdRevenue) {
// revenue.adFormat → "BANNER", "INTERSTITIAL", "REWARDED", "APP_OPEN"
// revenue.zoneId → Empower zone ID (e.g. "161428")
// revenue.provider → "APPLOVIN_MAX", "GOOGLE_ADMOB", "GOOGLE_AD_MANAGER"
// revenue.adUnitId → Ad network unit ID
// revenue.valueMicros → Revenue in micros (e.g. 868 = $0.000868)
// revenue.currencyCode → "USD"
// revenue.eventTimeMillis → Unix timestamp in milliseconds
print("Revenue: \(revenue.valueMicros) micros from \(revenue.provider.rawValue)")
}
}
2. Register the Delegate
Assign before the SDK starts loading ads — typically in viewDidLoad or AppDelegate.
EMAManager.shared.adRevenueDelegate = self
Note: The delegate is a
weakreference. Make sure the object stays alive for the duration you want to receive events.
3. Revenue Model Reference
EMAAdRevenue
| Field | Type | Description |
|---|---|---|
adFormat | EMAAdFormat | Ad format enum |
zoneId | String | Empower zone identifier |
provider | EMAAdProvider | Ad network that served the ad |
adUnitId | String | Ad network's unit ID |
valueMicros | Int64 | Revenue × 1,000,000 (avoids float precision loss) |
currencyCode | String | Always "USD" |
eventTimeMillis | Int64 | Unix timestamp (ms) of the impression |
Notes
- ILRD fires only when an ad impression occurs, not on load.
- Preroll (IMA) ads are not supported — the IMA SDK does not provide per-impression revenue data.
- Test ads may report
valueMicros = 0or may not fire at all depending on the network.
Listening for SDK Ready State (Optional)
If you need to know exactly when the SDK is ready (for analytics, UI updates, etc.), you can implement EMASdkReadyDelegate (Swift only — Objective-C apps use the notification shown below):
import EmpowerMobileAds
@main
class AppDelegate: UIResponder, UIApplicationDelegate, EMASdkReadyDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Register as delegate before initialization
EMAManager.shared.sdkReadyDelegate = self
// Initialize the SDK
let config = EMAConfiguration(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
EMAManager.shared.initialize(configuration: config)
return true
}
// MARK: - EMASdkReadyDelegate
func onReady() {
// SDK is initialized and ready to load ads
// Use this for analytics or UI updates
print("Empower SDK is ready")
}
func onFailed(error: Error?) {
// SDK initialization failed
// Handle the error appropriately
print("Empower SDK initialization failed: \(error?.localizedDescription ?? "unknown")")
}
}
Alternatively, you can observe the SDK-ready notification. This is the recommended approach for
Objective-C, where EMASdkReadyDelegate is not available:
- Swift
- Objective-C
NotificationCenter.default.addObserver(
forName: EMAManager.adsReadyToLoadNotification,
object: nil,
queue: .main
) { _ in
print("SDK is ready to load ads")
}
[[NSNotificationCenter defaultCenter] addObserverForName:EMAManager.adsReadyToLoadNotificationName
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"SDK is ready to load ads");
}];
Note: This delegate is optional. Since all ad types automatically queue, you don't need to wait for
onReady()before loading ads.
GDPR Compliance
Recommended: use the default
.automaticmode. When you don't setprivacyMode(or set it to.automatic), the SDK runs the Google UMP / GDPR consent flow and the ATT prompt for you and applies the result to every ad request — you write no consent code. This is the right choice for most apps.// Automatic consent — privacyMode defaults to .automatic, nothing else to do.let config = EMAConfiguration(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")EMAManager.shared.initialize(configuration: config)
Use the options below only to override the automatic behavior — force non-personalized ads
(.nonPersonalized), or take full manual control of consent and ATT (.manual):
- Swift
- Objective-C
// Option 1: Use GDPR-compliant configuration
let config = EMAConfiguration.gdprCompliant(appAdIdentifier: "YOUR_APP_AD_IDENTIFIER")
EMAManager.shared.initialize(configuration: config)
// Option 2: Set the privacy mode explicitly
let config = EMAConfiguration(
appAdIdentifier: "YOUR_APP_AD_IDENTIFIER",
privacyMode: .nonPersonalized
)
EMAManager.shared.initialize(configuration: config)
// Option 3: At runtime based on user consent
EMASettings.shared.isAdsNonPersonalized = !userHasGivenConsent
// Option 1: request non-personalized ads at initialization
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"
adAppVersion:@"1"
variant:@""
logLevel:LogLevelNone
nonPersonalizedAds:YES];
// Option 2: at runtime based on user consent
EMASettings.shared.isAdsNonPersonalized = !userHasGivenConsent;
App Tracking Transparency (iOS 14+)
In .automatic and .nonPersonalized privacy modes the SDK requests ATT automatically (after
the UMP consent flow) and applies the result to ad requests for you — you do not call
requestTrackingAuthorization yourself. You only need to declare NSUserTrackingUsageDescription
in your Info.plist (see below), or the app crashes when the prompt is presented.
Only in .manual privacy mode do you drive ATT yourself. The example below shows that manual flow:
- Swift
- Objective-C
import AppTrackingTransparency
import EmpowerMobileAds
// Manual privacy mode: your app owns ATT (and any UMP/GDPR flow).
// In .manual mode the SDK does NOT auto-request ATT, so there is no double prompt.
func requestTrackingPermissionAndInitSDK() {
if #available(iOS 14, *) {
ATTrackingManager.requestTrackingAuthorization { status in
DispatchQueue.main.async {
// Personalized ads only when the user authorized tracking.
EMASettings.shared.isAdsNonPersonalized = (status != .authorized)
let config = EMAConfiguration(
appAdIdentifier: "YOUR_APP_AD_IDENTIFIER",
privacyMode: .manual
)
EMAManager.shared.initialize(configuration: config)
}
}
} else {
// iOS 13 and earlier - no ATT prompt.
let config = EMAConfiguration(
appAdIdentifier: "YOUR_APP_AD_IDENTIFIER",
privacyMode: .manual
)
EMAManager.shared.initialize(configuration: config)
}
}
#import <AppTrackingTransparency/AppTrackingTransparency.h>
@import EmpowerMobileAds;
// Manual privacy mode: your app owns ATT. In .manual mode the SDK does not
// auto-request ATT, so there is no double prompt.
- (void)requestTrackingPermissionAndInitSDK {
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
// Personalized ads only when the user authorized tracking.
EMASettings.shared.isAdsNonPersonalized = (status != ATTrackingManagerAuthorizationStatusAuthorized);
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"
adAppVersion:@"1"
variant:@""
ext:@""
logLevel:LogLevelNone
customUserId:nil
customParameters:nil
appLovinSdkKey:nil
privacyMode:EMAPrivacyModeObjCManual];
});
}];
} else {
// iOS 13 and earlier - no ATT prompt.
[[EMAManager shared] initializeWithAppAdIdentifier:@"YOUR_APP_AD_IDENTIFIER"
adAppVersion:@"1"
variant:@""
ext:@""
logLevel:LogLevelNone
customUserId:nil
customParameters:nil
appLovinSdkKey:nil
privacyMode:EMAPrivacyModeObjCManual];
}
}
Don't forget to add the NSUserTrackingUsageDescription key to your Info.plist:
<key>NSUserTrackingUsageDescription</key>
<string>This app uses your data to provide personalized ads.</string>
Lifecycle Management
The SDK automatically manages ad lifecycle based on your app's state.
Background/Foreground Handling
The SDK automatically handles app state transitions. For custom behavior, you can hook into these events:
// In AppDelegate or SceneDelegate
func applicationDidEnterBackground(_ application: UIApplication) {
// SDK automatically pauses all ad refresh timers
// No action required
}
func applicationWillEnterForeground(_ application: UIApplication) {
// SDK automatically resumes ad refresh timers
// If app was in background for extended period,
// SDK will refresh ad configuration automatically
}
Disabling Ads for Premium Users
- Swift
- Objective-C
// Disable all ads for premium users
func userPurchasedPremium() {
EMASettings.shared.isAdsDisabled = true
// Destroy any currently loaded ads
// (they will automatically stop showing)
}
// Re-enable ads if subscription expires
func premiumSubscriptionExpired() {
EMASettings.shared.isAdsDisabled = false
}
// Disable all ads for premium users
- (void)userPurchasedPremium {
EMASettings.shared.isAdsDisabled = YES;
// Currently loaded ads will automatically stop showing
}
// Re-enable ads if subscription expires
- (void)premiumSubscriptionExpired {
EMASettings.shared.isAdsDisabled = NO;
}