> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Interstitial Ads

> Guide to implementing interstitial ads in iOS apps.

## Overview

Interstitial ads are ads displayed in full-screen format covering the entire app screen. They are suitable for display at natural transition points in the app, such as game level transitions or content page changes.

### Features

* Immersive ads covering the entire screen
* Maintained until user explicitly closes
* Supports both image and video ads
* High visual attention

<Note>
  Use test unit ID in development environment: `PUBLIC_TEST_UNIT_ID_INTERSTITIAL`
</Note>

***

## Implementation Steps

Implement interstitial ads in 4 steps:

1. **Initialize** - Create AdropInterstitialAd instance
2. **Set Delegate** - Set delegate to receive ad events
3. **Load Ad** - Request and receive ad
4. **Show Ad** - Display ad on screen

***

## UIKit Implementation

### Basic Implementation

<CodeGroup>
  ```swift Swift theme={null}
  import AdropAds

  class ViewController: UIViewController {
      private var interstitialAd: AdropInterstitialAd?

      override func viewDidLoad() {
          super.viewDidLoad()
          loadInterstitialAd()
      }

      // 1. Initialize and load ad
      private func loadInterstitialAd() {
          interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
          interstitialAd?.delegate = self
          interstitialAd?.load()
      }

      // 2. Show ad
      private func showInterstitialAd() {
          guard let interstitialAd = interstitialAd,
                interstitialAd.isLoaded else { return }
          interstitialAd.show(fromRootViewController: self)
      }
  }
  ```

  ```objc Objective-C theme={null}
  @import AdropAds;

  @interface ViewController () <AdropInterstitialAdDelegate>
  @property (nonatomic, strong) AdropInterstitialAd *interstitialAd;
  @end

  @implementation ViewController

  - (void)viewDidLoad {
      [super viewDidLoad];
      [self loadInterstitialAd];
  }

  // 1. Initialize and load ad
  - (void)loadInterstitialAd {
      self.interstitialAd = [[AdropInterstitialAd alloc] initWithUnitId:@"YOUR_UNIT_ID"];
      self.interstitialAd.delegate = self;
      [self.interstitialAd load];
  }

  // 2. Show ad
  - (void)showInterstitialAd {
      if (self.interstitialAd && self.interstitialAd.isLoaded) {
          [self.interstitialAd showFromRootViewController:self];
      }
  }

  @end
  ```
</CodeGroup>

### isLoaded Property

Property to check if the ad is loaded. It's recommended to check this value before calling `show()`.

<CodeGroup>
  ```swift Swift theme={null}
  if interstitialAd?.isLoaded == true {
      interstitialAd?.show(fromRootViewController: self)
  }
  ```

  ```objc Objective-C theme={null}
  if (self.interstitialAd.isLoaded) {
      [self.interstitialAd showFromRootViewController:self];
  }
  ```
</CodeGroup>

### Delegate Implementation

<CodeGroup>
  ```swift Swift theme={null}
  extension ViewController: AdropInterstitialAdDelegate {
      // Ad received successfully (required)
      func onAdReceived(_ ad: AdropInterstitialAd) {
          print("Interstitial ad received")
          // Show ad when ready
          showInterstitialAd()
      }

      // Ad receive failed (required)
      func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
          print("Interstitial ad failed to receive: \(errorCode)")
      }

      // Ad impression (optional)
      func onAdImpression(_ ad: AdropInterstitialAd) {
          print("Interstitial ad impression")
      }

      // Ad clicked (optional)
      func onAdClicked(_ ad: AdropInterstitialAd) {
          print("Interstitial ad clicked")
      }

      // Before showing full screen ad (optional)
      func onAdWillPresentFullScreen(_ ad: AdropInterstitialAd) {
          print("About to show interstitial ad")
      }

      // After showing full screen ad (optional)
      func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
          print("Interstitial ad shown")
      }

      // Before dismissing full screen ad (optional)
      func onAdWillDismissFullScreen(_ ad: AdropInterstitialAd) {
          print("About to dismiss interstitial ad")
      }

      // After dismissing full screen ad (optional)
      func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
          print("Interstitial ad dismissed")
          // Preload next ad
          loadInterstitialAd()
      }

      // Full screen ad show failed (optional)
      func onAdFailedToShowFullScreen(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
          print("Interstitial ad failed to show: \(errorCode)")
      }
  }
  ```

  ```objc Objective-C theme={null}
  #pragma mark - AdropInterstitialAdDelegate

  // Ad received successfully (required)
  - (void)onAdReceived:(AdropInterstitialAd *)ad {
      NSLog(@"Interstitial ad received");
      // Show ad when ready
      [self showInterstitialAd];
  }

  // Ad receive failed (required)
  - (void)onAdFailedToReceive:(AdropInterstitialAd *)ad :(AdropErrorCode)errorCode {
      NSLog(@"Interstitial ad failed to receive: %ld", (long)errorCode);
  }

  // Ad impression (optional)
  - (void)onAdImpression:(AdropInterstitialAd *)ad {
      NSLog(@"Interstitial ad impression");
  }

  // Ad clicked (optional)
  - (void)onAdClicked:(AdropInterstitialAd *)ad {
      NSLog(@"Interstitial ad clicked");
  }

  // Before showing full screen ad (optional)
  - (void)onAdWillPresentFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"About to show interstitial ad");
  }

  // After showing full screen ad (optional)
  - (void)onAdDidPresentFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"Interstitial ad shown");
  }

  // Before dismissing full screen ad (optional)
  - (void)onAdWillDismissFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"About to dismiss interstitial ad");
  }

  // After dismissing full screen ad (optional)
  - (void)onAdDidDismissFullScreen:(AdropInterstitialAd *)ad {
      NSLog(@"Interstitial ad dismissed");
      // Preload next ad
      [self loadInterstitialAd];
  }

  // Full screen ad show failed (optional)
  - (void)onAdFailedToShowFullScreen:(AdropInterstitialAd *)ad :(AdropErrorCode)errorCode {
      NSLog(@"Interstitial ad failed to show: %ld", (long)errorCode);
  }
  ```
</CodeGroup>

***

## SwiftUI Implementation

In SwiftUI, you can use `UIViewControllerRepresentable` or get the rootViewController from UIWindow to display.

### Method 1: ViewModel Pattern

```swift theme={null}
import SwiftUI
import AdropAds

// ViewModel
class InterstitialAdViewModel: NSObject, ObservableObject {
    @Published var isAdReady = false
    @Published var isAdShowing = false

    private var interstitialAd: AdropInterstitialAd?

    init() {
        loadAd()
    }

    func loadAd() {
        interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
        interstitialAd?.delegate = self
        interstitialAd?.load()
    }

    func showAd() {
        guard let interstitialAd = interstitialAd,
              let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
              let rootViewController = windowScene.windows.first?.rootViewController else {
            return
        }

        interstitialAd.show(fromRootViewController: rootViewController)
    }
}

// Delegate
extension InterstitialAdViewModel: AdropInterstitialAdDelegate {
    func onAdReceived(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdReady = true
        }
    }

    func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
        print("Ad receive failed: \(errorCode)")
    }

    func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdShowing = true
        }
    }

    func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
        DispatchQueue.main.async {
            self.isAdShowing = false
            self.isAdReady = false
        }
        // Preload next ad
        loadAd()
    }
}

// View
struct ContentView: View {
    @StateObject private var adViewModel = InterstitialAdViewModel()

    var body: some View {
        VStack {
            Text("Interstitial Ad Example")
                .font(.title)

            Button("Show Interstitial Ad") {
                adViewModel.showAd()
            }
            .disabled(!adViewModel.isAdReady)
            .padding()
        }
    }
}
```

***

## Delegate Methods

### Required Methods

<ParamField body="onAdReceived" type="(AdropInterstitialAd) -> Void">
  Called when ad is received successfully. You can call `show()` at this point to display the ad.
</ParamField>

<ParamField body="onAdFailedToReceive" type="(AdropInterstitialAd, AdropErrorCode) -> Void">
  Called when ad fails to load. You can check the cause of failure through the error code.
</ParamField>

### Optional Methods

<ParamField body="onAdImpression" type="(AdropInterstitialAd) -> Void">
  Called when ad impression is recorded.
</ParamField>

<ParamField body="onAdClicked" type="(AdropInterstitialAd) -> Void">
  Called when user clicks the ad.
</ParamField>

<ParamField body="onAdWillPresentFullScreen" type="(AdropInterstitialAd) -> Void">
  Called just before the interstitial ad is displayed. You can pause animations, etc.
</ParamField>

<ParamField body="onAdDidPresentFullScreen" type="(AdropInterstitialAd) -> Void">
  Called immediately after the interstitial ad is displayed on screen.
</ParamField>

<ParamField body="onAdWillDismissFullScreen" type="(AdropInterstitialAd) -> Void">
  Called just before the interstitial ad is dismissed.
</ParamField>

<ParamField body="onAdDidDismissFullScreen" type="(AdropInterstitialAd) -> Void">
  Called immediately after the interstitial ad is dismissed. Good time to preload the next ad.
</ParamField>

<ParamField body="onAdFailedToShowFullScreen" type="(AdropInterstitialAd, AdropErrorCode) -> Void">
  Called when ad fails to show. You can check the cause of failure through the error code.
</ParamField>

***

## Closure Callbacks

As an alternative to delegates, you can use closure-based callbacks.

```swift theme={null}
let interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")

// Required
interstitialAd.onAdReceived = { ad in
    print("Ad received")
}
interstitialAd.onAdFailedToReceive = { ad, errorCode in
    print("Ad failed: \(errorCode)")
}

// Optional
interstitialAd.onAdImpression = { ad in print("Ad impression") }
interstitialAd.onAdClicked = { ad in print("Ad clicked") }
interstitialAd.onAdWillPresentFullScreen = { ad in print("Ad will present") }
interstitialAd.onAdDidPresentFullScreen = { ad in print("Ad did present") }
interstitialAd.onAdWillDismissFullScreen = { ad in print("Ad will dismiss") }
interstitialAd.onAdDidDismissFullScreen = { ad in print("Ad did dismiss") }
interstitialAd.onAdFailedToShowFullScreen = { ad, errorCode in print("Ad failed to show: \(errorCode)") }
```

<Note>
  If both a delegate and closures are set, both will be called.
</Note>

***

## Best Practices

### 1. Preload Ads

Preload ads before displaying them to improve user experience.

```swift theme={null}
class GameViewController: UIViewController {
    private var interstitialAd: AdropInterstitialAd?
    private var isAdReady = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // Preload when entering screen
        preloadInterstitialAd()
    }

    private func preloadInterstitialAd() {
        interstitialAd = AdropInterstitialAd(unitId: "YOUR_UNIT_ID")
        interstitialAd?.delegate = self
        interstitialAd?.load()
    }

    func onGameLevelComplete() {
        // Show immediately when level completes
        if isAdReady {
            interstitialAd?.show(fromRootViewController: self)
        }
    }
}

extension GameViewController: AdropInterstitialAdDelegate {
    func onAdReceived(_ ad: AdropInterstitialAd) {
        isAdReady = true
    }

    func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
        print("Ad load failed: \(errorCode)")
    }

    func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
        isAdReady = false
        // Preload next ad
        preloadInterstitialAd()
    }
}
```

### 2. Appropriate Display Timing

Display ads at natural transition points in your app.

```swift theme={null}
// Good example: Game level transition
func onLevelComplete() {
    saveProgress()
    showInterstitialAd()
    loadNextLevel()
}

// Good example: Content reading complete
func onArticleFinished() {
    showInterstitialAd()
}

// Bad example: During user action
func onButtonTap() {
    showInterstitialAd() // Disrupts user experience
    performAction()
}
```

### 3. Reload After Dismissal

Preload the next ad after the ad is dismissed.

```swift theme={null}
func onAdDidDismissFullScreen(_ ad: AdropInterstitialAd) {
    // Immediately load next ad
    loadInterstitialAd()
}
```

### 4. Error Handling

Implement error handling for ad load failures.

```swift theme={null}
func onAdFailedToReceive(_ ad: AdropInterstitialAd, _ errorCode: AdropErrorCode) {
    switch errorCode {
    case .ERROR_CODE_NETWORK:
        print("Network error: Retry later")
        retryAfterDelay()
    case .ERROR_CODE_AD_NO_FILL:
        print("No available ads")
        continueWithoutAd()
    default:
        print("Ad load failed: \(errorCode)")
    }
}

private func retryAfterDelay() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
        self.loadInterstitialAd()
    }
}
```

### 5. Frequency Capping

Limit how often ads are displayed to avoid being too intrusive.

```swift theme={null}
class AdFrequencyManager {
    private var lastAdShownTime: Date?
    private let minimumInterval: TimeInterval = 180 // 3 minutes

    func canShowAd() -> Bool {
        guard let lastTime = lastAdShownTime else {
            return true
        }

        return Date().timeIntervalSince(lastTime) >= minimumInterval
    }

    func recordAdShown() {
        lastAdShownTime = Date()
    }
}

// Usage example
let frequencyManager = AdFrequencyManager()

func showInterstitialIfAllowed() {
    guard frequencyManager.canShowAd() else {
        print("Ad display interval too short")
        return
    }

    interstitialAd?.show(fromRootViewController: self)
}

func onAdDidPresentFullScreen(_ ad: AdropInterstitialAd) {
    frequencyManager.recordAdShown()
}
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Rewarded Ads" href="/sdk/ios/rewarded">
    Improve user engagement with rewarded ads
  </Card>

  <Card title="Banner Ads" href="/sdk/ios/banner">
    Implementing banner ads
  </Card>

  <Card title="Targeting Settings" href="/sdk/ios/targeting">
    User attributes and contextual targeting
  </Card>

  <Card title="Reference" href="/sdk/ios/reference">
    API reference documentation
  </Card>
</CardGroup>
