# IMA SDK for Video Players: Complete Integration Guide for Web, Android, and iOS

> Master the Google IMA SDK for video players. Integrate ads seamlessly on web, Android, and iOS with our comprehensive guide covering initialization, requests, playback, and cleanup.

- Repository: [Google/skills](https://github.com/google/skills)
- Tags: getting-started
- Published: 2026-08-15

---

**The Google IMA SDK provides a client-side solution for loading and playing video ads across six lifecycle stages: SDK import, initialization, ad request, load handling, playback events, and cleanup.**

The **IMA SDK for video players** enables developers to monetize content with interactive media ads across multiple platforms. According to the `google/skills` repository, the SDK supports web browsers, Android devices, iOS/tvOS systems, and connected TVs through a unified architecture adapted to each native environment.

## IMA SDK Lifecycle Overview

The SDK follows a consistent six-stage workflow regardless of platform. Understanding these stages ensures reliable ad delivery and prevents memory leaks.

### Stage 1: Import the SDK

Load the JavaScript library from the Google CDN to make the `google.ima` namespace available.

```html
<script src="https://imasdk.googleapis.com/js/sdkloader/ima3.js"></script>

```

Mobile platforms use package managers: Gradle for Android (`com.google.ads.interactivemedia:interactivemedia:3.31.0`), CocoaPods/SPM for iOS.

### Stage 2: Initialization

Configure global settings via `google.ima.settings` **before** creating containers. This sets locale, VPAID mode, and other preferences that apply to all ad requests.

Key objects created:
- **AdDisplayContainer**: Binds an HTML element for ads to your content video
- **AdsLoader**: Handles the ad-request lifecycle

### Stage 3: Ad Request

Construct an `AdsRequest`, set the ad tag URL, and declare playback capabilities:

```typescript
const request = new google.ima.AdsRequest();
request.adTagUrl = 'https://example.com/adtag.xml';
request.setAdWillAutoPlay(true);
request.setAdWillPlayMuted(false);
adsLoader.requestAds(request);

```

### Stage 4: Ad Load Success or Failure

Listen for `AdsManagerLoadedEvent` (success) and `AdErrorEvent` (failure). On success, retrieve the `AdsManager`, initialize with player dimensions, and start playback.

### Stage 5: Ad Playback Events

The `AdsManager` emits critical events including `CONTENT_PAUSE_REQUESTED` and `CONTENT_RESUME_REQUESTED`. Hook these to synchronize your content player with ad playback.

### Stage 6: Cleanup

Always destroy resources to prevent memory leaks:

```typescript
adsManager?.destroy();
adsLoader.contentComplete();
adDisplayContainer.destroy();

```

## Web Integration (HTML5 TypeScript)

The web implementation relies on [`SKILL.md`](https://github.com/google/skills/blob/main/SKILL.md) and [`ima-sdk-web-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-web-guide.md) in the `google/skills` repository for best practices.

### HTML Structure

```html
<div id="playerContainer" style="position:relative;width:640px;height:360px;">
  <video id="contentVideo" style="width:100%;height:100%;"></video>
  <div id="adContainer"
       style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;"></div>
</div>

```

### Complete TypeScript Implementation

```typescript
let adsLoader: google.ima.AdsLoader;
let adDisplayContainer: google.ima.AdDisplayContainer;
let adsManager: google.ima.AdsManager | null = null;

// Configure global settings early
google.ima.settings.setLocale('en');
google.ima.settings.setVpaidMode(google.ima.ImaSdkSettings.VpaidMode.ENABLED);

// Create UI containers
const adDiv = document.getElementById('adContainer') as HTMLElement;
const video = document.getElementById('contentVideo') as HTMLVideoElement;
adDisplayContainer = new google.ima.AdDisplayContainer(adDiv, video);
adsLoader = new google.ima.AdsLoader(adDisplayContainer);

// Hook loader events
adsLoader.addEventListener(
  google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,
  onAdsManagerLoaded
);
adsLoader.addEventListener(
  google.ima.AdErrorEvent.Type.AD_ERROR,
  onAdError
);

function requestAd(adTagUrl: string, autoPlay: boolean, muted: boolean) {
  adDisplayContainer.initialize();  // Must follow user gesture
  const request = new google.ima.AdsRequest();
  request.adTagUrl = adTagUrl;
  request.setAdWillAutoPlay(autoPlay);
  request.setAdWillPlayMuted(muted);
  adsLoader.requestAds(request);
}

function onAdsManagerLoaded(e: google.ima.AdsManagerLoadedEvent) {
  const renderingSettings = new google.ima.AdsRenderingSettings();
  adsManager = e.getAdsManager(video, renderingSettings);
  
  adsManager.addEventListener(
    google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED,
    () => video.pause()
  );
  adsManager.addEventListener(
    google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED,
    () => video.play()
  );
  adsManager.addEventListener(
    google.ima.AdErrorEvent.Type.AD_ERROR,
    onAdError
  );

  try {
    adsManager.init(640, 360, google.ima.ViewMode.NORMAL);
    adsManager.start();
  } catch (err) {
    onAdError(err);
  }
}

function onAdError(event: any) {
  console.error('IMA error:', event);
  cleanupAds();
  video.play();
}

function cleanupAds() {
  adsManager?.destroy();
  adsManager = null;
  adsLoader.contentComplete();
  adDisplayContainer.destroy();
}

```

## Android Integration (Kotlin)

Android implementations use the [`ima-sdk-android-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-android-guide.md) reference. The Kotlin API mirrors the web lifecycle with native Android patterns.

```kotlin
// Gradle dependency
implementation("com.google.ads.interactivemedia:interactivemedia:3.31.0")

// Activity implementation
private lateinit var adDisplayContainer: AdDisplayContainer
private lateinit var adsLoader: AdsLoader
private var adsManager: AdsManager? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    IMASdkFactory.getInstance().settings.locale = "en"
    IMASdkFactory.getInstance().settings.vpaidMode = IMASettings.VpaidMode.ENABLED

    val adContainer = findViewById<FrameLayout>(R.id.adContainer)
    val videoView = findViewById<VideoView>(R.id.contentVideo)
    adDisplayContainer = AdDisplayContainer(adContainer, videoView)
    adsLoader = AdsLoader(this, adDisplayContainer)

    adsLoader.addAdsLoadedListener { manager -> onAdsManagerLoaded(manager) }
    adsLoader.addAdErrorListener { error -> onAdError(error) }
}

private fun requestAd(adTagUrl: String) {
    val request = AdsRequest().apply {
        this.adTagUrl = adTagUrl
        setAdWillAutoPlay(true)
        setAdWillPlayMuted(false)
    }
    adsLoader.requestAds(request)
}

private fun onAdsManagerLoaded(manager: AdsManager) {
    adsManager = manager
    manager.addAdEventListener { event ->
        when (event.type) {
            AdEvent.Type.CONTENT_PAUSE_REQUESTED -> videoView.pause()
            AdEvent.Type.CONTENT_RESUME_REQUESTED -> videoView.start()
        }
    }
    manager.addAdErrorListener { error -> onAdError(error) }
    manager.init(640, 360, ViewMode.NORMAL)
    manager.start()
}

private fun onAdError(error: AdError) {
    Log.e("IMA", "Error: ${error.message}")
    adsManager?.destroy()
    adsLoader.contentComplete()
    videoView.start()
}

```

## iOS Integration (Swift)

iOS developers reference [`ima-sdk-ios-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-ios-guide.md) and [`ima-sdk-tvos-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-tvos-guide.md) for platform-specific guidance. The Swift implementation uses delegate patterns familiar to iOS developers.

```swift
import GoogleInteractiveMediaAds

class PlayerViewController: UIViewController {
    private var adDisplayContainer: IMAAdDisplayContainer!
    private var adsLoader: IMAAdsLoader!
    private var adsManager: IMAAdsManager?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        IMASettings.shared().locale = "en"
        IMASettings.shared().vpaidMode = .enabled

        let adContainer = UIView(frame: view.bounds)
        view.addSubview(adContainer)
        
        let contentPlayer = AVPlayerViewController()
        addChild(contentPlayer)
        view.addSubview(contentPlayer.view)

        adDisplayContainer = IMAAdDisplayContainer(
            adContainer: adContainer,
            companionSlots: nil
        )
        adsLoader = IMAAdsLoader(settings: IMASettings.shared())
        adsLoader.delegate = self
    }

    func requestAd(tagUrl: String) {
        let request = IMAAdsRequest(
            adTagUrl: tagUrl,
            adDisplayContainer: adDisplayContainer,
            contentPlayhead: nil,
            userContext: nil
        )
        request.adWillAutoPlay = true
        request.adWillPlayMuted = false
        adsLoader.requestAds(with: request)
    }
}

extension PlayerViewController: IMAAdsLoaderDelegate {
    func adsLoader(_ loader: IMAAdsLoader, didReceive adsLoadedData: IMAAdsLoadedData) {
        adsManager = adsLoadedData.adsManager
        adsManager?.delegate = self
        adsManager?.initialize(with: IMAAdsRenderingSettings())
        adsManager?.start()
    }

    func adsLoader(_ loader: IMAAdsLoader, didFailWithErrorData errorData: IMAAdLoadingErrorData) {
        print("IMA load error: \(errorData.adError.message)")
    }
}

extension PlayerViewController: IMAAdsManagerDelegate {
    func adsManager(_ manager: IMAAdsManager, didReceive event: IMAAdEvent) {
        switch event.type {
        case .contentPauseRequested:
            // Pause content player
            break
        case .contentResumeRequested:
            // Resume content player
            break
        default:
            break
        }
    }

    func adsManager(_ manager: IMAAdsManager, didReceive error: IMAAdError) {
        print("IMA playback error: \(error.message)")
        manager.destroy()
    }
}

```

## Platform-Specific Reference Files

The `google/skills` repository organizes IMA SDK documentation by platform:

| Platform | Reference File | Purpose |
|----------|---------------|---------|
| Web | [`ima-sdk-web-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-web-guide.md) | HTML5/JS integration, lifecycle events |
| Android | [`ima-sdk-android-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-android-guide.md) | Kotlin/Java implementation patterns |
| iOS | [`ima-sdk-ios-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-ios-guide.md) | Swift/Objective-C integration |
| tvOS | [`ima-sdk-tvos-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-tvos-guide.md) | Apple TV-specific considerations |
| Special | [`ima-sdk-web-iframe-mode.md`](https://github.com/google/skills/blob/main/ima-sdk-web-iframe-mode.md) | AMP and iframe environments |
| Special | [`ima-sdk-web-mobile-safari.md`](https://github.com/google/skills/blob/main/ima-sdk-web-mobile-safari.md) | Autoplay and muted policy handling |

## Critical Implementation Details

### User Gesture Requirements

Call `adDisplayContainer.initialize()` only after a user interaction. This satisfies browser autoplay policies and mobile Safari restrictions documented in [`ima-sdk-web-mobile-safari.md`](https://github.com/google/skills/blob/main/ima-sdk-web-mobile-safari.md).

### Error Handling Strategy

Distinguish between **non-fatal** `LOG` events (diagnostics only) and **fatal** `AD_ERROR` events (require cleanup and content fallback). Always implement both `AdErrorEvent` listeners on `AdsLoader` and `AdsManager`.

### Memory Management

Nullify references after `destroy()` calls:

```typescript
adsManager.destroy();
adsManager = null;  // Prevent stale reference usage

```

## Summary

- **Import early**: Load the SDK and configure `google.ima.settings` before creating containers
- **Initialize after gesture**: `AdDisplayContainer.initialize()` requires user interaction on web
- **Request with context**: Set `adWillAutoPlay` and `adWillPlayMuted` accurately for optimal ad selection
- **Listen comprehensively**: Handle both `AdsManagerLoadedEvent` and `AdErrorEvent` on the loader
- **Synchronize playback**: Respond to `CONTENT_PAUSE_REQUESTED` and `CONTENT_RESUME_REQUESTED` to coordinate ad and content playback
- **Destroy completely**: Call `destroy()` on all three main objects (`AdsManager`, `AdsLoader.contentComplete()`, `AdDisplayContainer`) to prevent memory leaks

## Frequently Asked Questions

### What is the minimum IMA SDK version for modern mobile browsers?

The `google/skills` repository does not specify minimum versions in the analyzed files. However, the Android example uses version `3.31.0` as a current stable reference point. Check the [official IMA SDK release notes](https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/history) for deprecation schedules and feature availability.

### Why does my ad fail to load on mobile Safari?

Mobile Safari enforces strict autoplay and muted policies. The [`ima-sdk-web-mobile-safari.md`](https://github.com/google/skills/blob/main/ima-sdk-web-mobile-safari.md) file documents that you must call `adDisplayContainer.initialize()` within a user gesture handler, and accurately declare `setAdWillPlayMuted(true)` when appropriate. Incorrect capability reporting causes silent failures.

### How do I implement IMA SDK in a React or Angular application?

The web integration patterns in [`ima-sdk-web-guide.md`](https://github.com/google/skills/blob/main/ima-sdk-web-guide.md) apply directly to framework implementations. Create the `AdDisplayContainer` and `AdsLoader` in a component's initialization lifecycle, store references in instance variables or refs, and call `destroy()` in cleanup handlers (`useEffect` return or `ngOnDestroy`).

### Can I use the IMA SDK within an iframe or AMP page?

Yes. The [`ima-sdk-web-iframe-mode.md`](https://github.com/google/skills/blob/main/ima-sdk-web-iframe-mode.md) file provides specific guidance for constrained environments where the standard integration pattern is restricted. This includes message-passing configurations and reduced API surface areas for AMP compatibility.