In This Article
Mobile apps present a unique challenge for rich media advertising. Unlike web browsers, where ads run in a relatively standardized environment with access to the DOM and JavaScript APIs, mobile app ads live inside a WebView controlled by the app's ad SDK. Without a common interface standard, every ad SDK implemented ad rendering differently, forcing creative developers to build separate versions for each SDK. MRAID (Mobile Rich Media Ad Interface Definitions) solves this by defining a standardized JavaScript API that ad creatives can use to interact with the host app's SDK.
What Is MRAID?
MRAID is an IAB Tech Lab specification that defines a JavaScript bridge between rich media ad creatives and the mobile app SDK that renders them. When an MRAID-compliant ad is loaded inside an app, the SDK injects a JavaScript API into the WebView. The ad creative can then call MRAID methods to request actions like expanding to fullscreen, resizing, opening a URL, or detecting viewability—all without needing to know which SDK is hosting it.
The Problem MRAID Solves
Before MRAID, a creative agency building an expandable banner ad for mobile apps had to:
- Build separate creative versions for each ad SDK (MoPub, AdMob, ironSource, etc.)
- Learn each SDK's proprietary JavaScript API for expansion, resize, and other interactions
- Maintain multiple creative codebases, each with different testing requirements
- Debug rendering issues that varied across SDK implementations
MRAID eliminates this fragmentation by providing a single, universal API that all compliant SDKs support.
Version History
| Version | Year | Key Additions |
|---|---|---|
| MRAID 1.0 | 2011 | Initial specification. Basic expand, close, resize, and open actions. State management (loading, default, expanded, hidden). |
| MRAID 2.0 | 2014 | Two-part expand (expand to custom size). SetOrientationProperties. Supports custom close regions. Screen size reporting. |
| MRAID 3.0 | 2018 | Native-style ad support. Viewability measurement API (exposureChange). Improved audio state tracking. Enhanced error handling. getLocation method. |
The MRAID JavaScript API
MRAID defines a JavaScript object (mraid) that the host SDK injects into the ad's WebView. The ad creative checks for MRAID readiness, registers event listeners, and then calls MRAID methods as needed.
Initialization Pattern
// Standard MRAID initialization pattern
(function() {
if (typeof mraid === 'undefined') {
// MRAID not available - fallback to non-MRAID behavior
console.log('MRAID not available');
return;
}
// Wait for MRAID to be ready
mraid.addEventListener('ready', function() {
console.log('MRAID is ready, version:', mraid.getVersion());
console.log('Current state:', mraid.getState());
console.log('Screen size:', JSON.stringify(mraid.getScreenSize()));
// Set up event listeners
mraid.addEventListener('stateChange', onStateChange);
mraid.addEventListener('viewableChange', onViewableChange);
mraid.addEventListener('sizeChange', onSizeChange);
// Start the ad
initAd();
});
function onStateChange(state) {
console.log('State changed to:', state);
if (state === 'expanded') {
// Load expanded creative
} else if (state === 'default') {
// Return to default view
}
}
function onViewableChange(viewable) {
console.log('Viewable:', viewable);
if (viewable) {
// Start animations, video, etc.
} else {
// Pause animations, mute audio
}
}
})();
Core Methods
| Method | Description |
|---|---|
mraid.getVersion() | Returns the MRAID version supported by the SDK (e.g., "3.0") |
mraid.getState() | Returns current ad state: "loading", "default", "expanded", "resized", or "hidden" |
mraid.expand([url]) | Expands the ad to fullscreen or a larger overlay. Optionally loads a new URL in the expanded view. |
mraid.close() | Closes the expanded/resized ad and returns to the default state or removes the ad entirely. |
mraid.resize(width, height) | Resizes the ad container to the specified dimensions (MRAID 2.0+). |
mraid.open(url) | Opens a URL in the device's browser or an in-app browser. |
mraid.getScreenSize() | Returns the screen dimensions in density-independent pixels. |
mraid.getMaxSize() | Returns the maximum size the ad can expand to. |
mraid.getDefaultPosition() | Returns the default position and size of the ad container. |
mraid.getCurrentPosition() | Returns the current position and size (may differ if resized). |
mraid.isViewable() | Returns whether the ad is currently viewable on screen. |
mraid.setOrientationProperties(...) | Controls allowed device orientations during expanded state. |
mraid.playVideo(url) | Opens the device's native video player with the specified URL. |
mraid.storePicture(url) | Saves an image to the device's photo gallery (requires user permission). |
mraid.supports(feature) | Checks if the SDK supports a specific feature (sms, tel, calendar, storePicture, inlineVideo). |
MRAID 3.0: Viewability and Native-Style Ads
Exposure Change Events
MRAID 3.0 introduced the exposureChange event, which provides granular viewability data to the ad creative. Unlike the simple boolean isViewable() method, exposureChange reports the exact percentage of the ad that is visible, along with information about which portions are obscured:
mraid.addEventListener('exposureChange', function(exposure) {
console.log('Exposed percentage:', exposure.exposedPercentage);
console.log('Visible viewport:', JSON.stringify(exposure.visibleRectangle));
// exposure.exposedPercentage: 0-100
// exposure.visibleRectangle: {x, y, width, height}
// exposure.reasons: array of reasons for partial visibility
// - "adFullyOccluded" (another view covers the ad)
// - "adPartiallyOccluded"
// - "screenOff" (device screen is off)
// - "minimized" (app is backgrounded)
// - "back" (ad is behind another screen)
if (exposure.exposedPercentage >= 50) {
// Ad meets standard viewability criteria
startTracking();
}
});
Audio State Tracking
MRAID 3.0 added the audioVolumeChange event, enabling video ads to respond to audio state changes. This is particularly important for autoplay video ads, which should mute when the device is in silent mode:
mraid.addEventListener('audioVolumeChange', function(volume) {
// volume: 0 (muted) to 1.0 (full volume)
// -1 indicates volume could not be determined
if (volume === 0) {
videoElement.muted = true;
showCaptions(true);
} else {
videoElement.muted = false;
videoElement.volume = volume;
showCaptions(false);
}
});
Native-Style Ads
MRAID 3.0 introduced support for native-style ads—ads that render using the app's native UI components rather than a WebView. This enables ad formats that blend seamlessly with the app's content, improving user experience and engagement. The SDK provides the ad creative with content data (headline, body text, images, CTA) through the MRAID API, and the creative can render this content using platform-native UI elements.
State Machine
MRAID defines a clear state machine that governs the ad's lifecycle. Understanding state transitions is critical for both creative developers and SDK implementors:
| State | Description | Transitions To |
|---|---|---|
| loading | The ad is being loaded into the WebView | default |
| default | The ad is displayed at its original size | expanded, resized, hidden |
| expanded | The ad has expanded to a larger overlay | default (on close) |
| resized | The ad has been resized to custom dimensions | default (on close) |
| hidden | The ad is not visible (e.g., interstitial dismissed) | default |
Creatives must always check their current state before calling action methods. Calling expand() from a non-default state will throw an error. Similarly, calling close() from the default state will remove the ad entirely, while calling it from expanded or resized state will return to default.
Implementation Guide for SDK Developers
WebView Setup
The SDK must inject the MRAID JavaScript bridge into the WebView before the ad creative's JavaScript executes. This is typically done by loading the MRAID library script before the ad's HTML content:
// Android (Kotlin) - Injecting MRAID into WebView
webView.addJavascriptInterface(
MraidBridge(this), "mraid"
)
// Load MRAID library first, then the ad creative
webView.loadUrl("javascript:mraidInit();")
class MraidBridge(private val adController: AdController) {
@JavascriptInterface
fun getVersion(): String = "3.0"
@JavascriptInterface
fun getState(): String = adController.currentState.name
@JavascriptInterface
fun expand(url: String?) {
adController.expandAd(url)
}
@JavascriptInterface
fun close() {
adController.closeAd()
}
@JavascriptInterface
fun isViewable(): Boolean {
return adController.checkViewability()
}
}
Viewability Calculation
Implementing accurate viewability measurement is one of the most complex aspects of MRAID SDK development. The SDK must continuously monitor:
- Whether the ad view is attached to the window hierarchy
- Whether any portion of the ad is occluded by other views
- Whether the device screen is on and the app is in the foreground
- The exact pixel area of the ad that is visible on screen
On Android, this requires using View.getLocationOnScreen(), View.getGlobalVisibleRect(), and checking the view hierarchy for overlapping views. On iOS, the equivalent functionality uses UIView.convertRect:toView: and the layer presentation tree.
Error Handling
The SDK should fire the error event when MRAID operations fail, providing both a human-readable message and an error code:
// MRAID error codes
const MRAID_ERROR_CODES = {
UNKNOWN: 1,
UNSUPPORTED: 2,
NATIVE: 3,
AD: 4,
TRANSPORT: 5
};
// Fire error event
function fireError(message, code) {
webView.evaluateJavascript(
"window.dispatchEvent(new CustomEvent('mraid:error', " +
"{detail: {message: '$message', action: '$code'}}))"
);
}
Testing and Validation
The IAB Tech Lab provides MRAID testing tools and reference implementations to help both creative developers and SDK implementors validate their work:
- MRAID test pages: Sample HTML creatives that exercise every MRAID method and event, enabling SDK developers to verify their implementation.
- Creative testing tools: Web-based validators that check MRAID creatives for common issues like missing ready event handlers, incorrect state transitions, or unsupported feature calls.
- SDK certification: The IAB offers a certification program where SDKs can demonstrate MRAID compliance through standardized test suites.
Challenges and Considerations
- WebView differences: Android's WebView and iOS's WKWebView have different JavaScript execution engines, CSS rendering, and performance characteristics. Creatives that work perfectly on one platform may exhibit issues on the other.
- SDK implementation variance: While MRAID defines a standard API, SDK implementations vary in their interpretation of edge cases. Creative developers should test across multiple SDKs.
- Performance overhead: The JavaScript bridge between native code and WebView adds latency to MRAID method calls. Creatives that make frequent calls (e.g., continuous position polling) may experience performance degradation.
- Privacy concerns: Methods like
getLocation()andstorePicture()require user permission and must comply with platform privacy policies (iOS App Tracking Transparency, Android permissions).
MRAID in the Broader Standards Ecosystem
MRAID works alongside other IAB standards in the mobile advertising stack. In a typical mobile ad transaction: OpenRTB delivers the bid request and response, the creative is served as an MRAID-compliant HTML page rendered in a WebView, viewability is measured through both MRAID's built-in viewability API and the OM SDK for standardized third-party verification, and the publisher's app-ads.txt file authorizes the selling entity. Understanding how MRAID fits into this ecosystem helps developers build ad experiences that work reliably across the full programmatic supply chain.