Interactive ad creative requirements

Follow these guidelines to help ensure that your HTML assets pass the ironSource QA.

General requirements 

  • Loading of the creative should be < 10 seconds.
  • Сreatives should be responsive to any type of interaction according to gameplay/tutorial 
  • ironSource’s ad unit info button and X-button should work according to its purpose
  • Users should be able to get to store from the creative
  • If your creative includes sound:
    • All mute buttons (mechanical/in-game) should work according to its purpose
    • Sound/sound effects should be disabled when the creative is taken to the background mode
    • Sound/sound effects should be disabled before the creative is launched

UI/UX requirements 

  • All gameplay buttons should be clearly visible
  • Any text (disclaimers, texts of the buttons, tutorials) should be clearly visible and readable, and should be in the screen area
  • Don’t include any X-buttons as ironSource provides a built in X-button
  • Creatives should fill the entire screen in all orientations that it will run on 
  • Any creative elements that leads  the user to a store, should not be out of the screen area

Network requirements

  • Ad must support DAPI protocol
  • Ad must include within <head> the DAPI script from the implementation step from DAPI protocol
  • Avoid using window.onload since its override the behavior of the DAPI initialization script, instead use window.addEventListener 
  • Clicks leading to the store page (Google Play Store, Apple App Store) must use dapi.openStoreUrl() (without parameters)
  • Ad must embed all assets and files (JS/CSS/Images) in base64 in a single inline HTML file
  • The HTML file must embed all assets and files (JS/CSS/Images/etc.) in Base64
  • Maximum accepted file size is 5MB
  • Network requests should be absolute URLs instead of relative URLs and HTTPS instead of HTTP
  • Ad should support both landscape and portrait orientations.
  • ironSource will render the timer and the close button. Do not add your own
  • Gameplay of the creative should not include any auto redirects to the store without any user interaction. Delayed redirects to the store after the last user’s action with a delay of more than 7 seconds are also not allowed
  • The ad design should take into account ironSource UI elements located 30X30 pixels from each corner. Example:

Content review


Any creative submitted may be subject to a content review, in accordance with our internal policies and discretion. We may approve, remove or restrict ads from the ironSource network at our sole discretion. Your ads need to comply with the policies and standards of the applicable platform and app stores (e.g. iOS and Android).

Your creative should be appropriate for the content/age rating of your title in app stores.

DAPI specifications

DAPI overview

A DAPI ad is a single HTML file that must support the DAPI Protocol. DAPI protocol is a set of functions(resize,getDeviceData etc) and events (adResized,viewableChange etc.) that help integrate any ad in order to be used in the ironSource network.

ironSource DAPI integration

In order to implement DAPI in your creative, you need to add a specific header and then use DAPI functions and events in a particular order. Make sure that you’ve added your own code where necessary. 


Setup guide

Playable and interactive ads run inside the ironSource SDK via iFrame. Implement the dapi.js inside your HTML code to communicate with our SDK (necessary to receive essential information like screen size, ad viewability, send click events, etc.).

Implementation

Step 1: Add the following code in the <head> tag:

< script >
	function getScript(e, i) {
		var n = document.createElement("script");
		n.type = "text/javascript", n.async = !0, i && (n.onload = i), n.src = e, document.head.appendChild(n)
	}
function parseMessage(e) {
	var i = e.data,
		n = i.indexOf(DOLLAR_PREFIX + RECEIVE_MSG_PREFIX);
	if (-1 !== n) {
		var t = i.slice(n + 2);
		return getMessageParams(t)
	}
	return {}
}
function getMessageParams(e) {
	var i, n = [],
		t = e.split("/"),
		a = t.length;
	if (-1 === e.indexOf(RECEIVE_MSG_PREFIX)) {
		if (a >= 2 && a % 2 === 0)
			for (i = 0; a > i; i += 2) n[t[i]] = t.length < i + 1 ? null : decodeURIComponent(t[i + 1])
	} else {
		var o = e.split(RECEIVE_MSG_PREFIX);
		void 0 !== o[1] && (n = JSON && JSON.parse(o[1]))
	}
	return n
}
function getDapi(e) {
	var i = parseMessage(e);
	if (!i || i.name === GET_DAPI_URL_MSG_NAME) {
		var n = i.data;
		getScript(n, onDapiReceived)
	}
}
function invokeDapiListeners() {
	for (var e in dapiEventsPool) dapiEventsPool.hasOwnProperty(e) && dapi.addEventListener(e, dapiEventsPool[e])
}
function onDapiReceived() {
	dapi = window.dapi, window.removeEventListener("message", getDapi), invokeDapiListeners()
}
function init() {
	window.dapi.isDemoDapi && (window.parent.postMessage(DOLLAR_PREFIX + SEND_MSG_PREFIX + JSON.stringify({
		state: "getDapiUrl"
	}), "*"), window.addEventListener("message", getDapi, !1))
}
var DOLLAR_PREFIX = "$$",
	RECEIVE_MSG_PREFIX = "DAPI_SERVICE:",
	SEND_MSG_PREFIX = "DAPI_AD:",
	GET_DAPI_URL_MSG_NAME = "connection.getDapiUrl",
	dapiEventsPool = {},
	dapi = window.dapi || {
		isReady: function() {
			return !1
		},
		addEventListener: function(e, i) {
			dapiEventsPool[e] = i
		},
		removeEventListener: function(e) {
			delete dapiEventsPool[e]
		},
		isDemoDapi: !0
	};
init(); </script>

Step 2: Add the code below to know when the DAPI is ready to use

//LOAD the game, but do not start it until the ad is visible

window.addEventListener("load", function(){
  (dapi.isReady()) ? onReadyCallback() : dapi.addEventListener("ready", onReadyCallback); 
   //here you can put other code that not related to presenting any media information - do not play any audio/video/images at this moment
     //use this to prepare your creative to be shown(i.e. do necessary calculations or pre-loads)
});
function onReadyCallback(){
	//no need to listen to this event anymore
	dapi.removeEventListener("ready", onReadyCallback);
      let isAudioEnabled = !!dapi.getAudioVolume();
	if(dapi.isViewable()){
		adVisibleCallback({isViewable: true});
	}
	
      dapi.addEventListener("viewableChange", adVisibleCallback); //this event is used to know when the ad was visible/hidden
	dapi.addEventListener("adResized", adResizeCallback); //this event is used recalculate ad UI items(mostly upon rotation)
      dapi.addEventListener("audioVolumeChange",         audioVolumeChangeCallback); //this event is used to get info about any volume state change
}
function startGame() {
    //start your game here
    var screenSize = dapi.getScreenSize();
    //(add your own code here)
}
function pauseGame() {
    //pause your game here(add your own code here)
}
function adVisibleCallback(event){
	console.log("isViewable " + event.isViewable);
	if (event.isViewable){
		screenSize = dapi.getScreenSize();
		//START or RESUME the ad (add your own code here)
            event.startGame(); //example of function that can be called to start game
	} else {
		//PAUSE the ad and MUTE sounds or DO nothing if creative hasn’t been launched yet (add your own code here)
            event.pauseGame(); //example of function that can be called to pause game
	}
}
function adResizeCallback(event){
	screenSize = event;
	console.log("ad was resized width " + event.width + " height " + event.height);
}
//When user clicks on the download button - use openStoreUrl function
function userClickedDownloadButton(event){
	dapi.openStoreUrl();
}
function audioVolumeChangeCallback(volume){
	let isAudioEnabled = !!volume;
	if (isAudioEnabled){
		//START or turn on the sound(add your own code here)
	} else {
		//PAUSE the turn off the sound(add your own code here)
	}
}

Step 3: Implement the dapi.js API – Methods (if needed)

dapi.isReady

Description: Checks if the dapi is ready or not (if not, you shouldn’t use the dapi methods to play and run playable or interactive ads)

Pass params: None

Return value: Boolean (if ready – will return true, if not ready – false)

dapi.isViewable

Description:  Returns true if the ad is currently viewable (for example, if the user presses the home button, the ad is not viewable)

Pass params: none

Return value: boolean (if viewable – will return true, if not – false)

dapi.getScreenSize

Description: Returns the exact screen size

Pass params: none

Return value: object (for example: {width: 200, height: 400})

 dapi.openStoreUrl

Description: Call this method to direct a user to the app store

 when a user clicks on the “Install” or “Download” button. This method also tracks and registers a click with a tracking solution

Pass params: callback [function] optional, params [object] optional

Return value: none

dapi.getAudioVolume

Overview: Returns the current status of the device audio

Pass params: none

Return value: int (example 0,100) – 0=mute, 100=sound on

dapi.js API – Events and Listeners

dapi.addEventListener

Description: Add event listeners (see list of listeners below)

Pass params: eventName [string] mandatory, callback [function] mandatory

 Return value: none

dapi.removeEventListener

Description: Remove event listeners (see list of listeners below)

Pass params: eventName [string] mandatory, callback [function] mandatory

Return value: none

Events

Add listener to these events:

  • ready – listen to this event to determine when dapi.js is ready and available for use
  • viewableChange – listen to this event to know when the ad was visible/hidden
  • adResized – listen to this event to recalculate ad UI items
  • audioVolumeChange – listen to this event in order to be informed of any volume state change (from mute to sound on and vice versa)
    dapi.js API – Notes
    • Listeners – you can add event listeners even before window.onload
    • viewableChange – use this event to know when the ad is actually shown in order to start/pause the game
      • You should load all the assets in the background before the ad is shown, but start the game only when the ad is visible 
      • When the ad isn’t visible (user clicked on the home button/closed the ad), you should pause the game and mute the sound
    • adResized – use this event to know when the screen was resized (e.g Landscape to Portrait)
    • dapi.getScreenSize()– this will return {width: 0, height: 0} while the ad is in the background or hidden. You should use it only when the ad is visible

    HTML Example

    Use this HTML as an example for a good DAPI implementation:
    view-source:https://static.ssacdn.com/demand-creatives/assets/htmls/file-1683279877451.html