La API de Ad Placement está diseñada para admitir a los desarrolladores de AdSense y AdMob que utilizan anuncios intersticiales y recompensados en juegos HTML5 en la Web o dentro de aplicaciones. En este ejemplo, se muestra cómo integrar la API de Ad Placement en un juego y usarla para colocar un anuncio intersticial.
Requisitos previos
Antes de comenzar, necesitarás lo siguiente:
- Crea dos archivos vacíos en el mismo directorio:
- index.html
- game.js
- Instala Python de forma local o usa un servidor web para probar tu implementación
Código de muestra de la app
Los publicadores de AdMob pueden descargar código de apps de ejemplo para comprender mejor cómo se puede integrar la API en un juego para aplicaciones.
Descarga el código de muestra de la app
1. Inicia un servidor de desarrollo
Dado que la API de Ads Placement carga dependencias a través del mismo protocolo que la página en la que se carga, debes usar un servidor web para probar tu app. Puedes usar el servidor integrado de Python para crear un entorno de desarrollo local.
Abre la terminal.
Ve al directorio que contiene tu archivo index.html y, luego, ejecuta el siguiente comando:
python -m http.server 8000
En un navegador web, ve a
localhost:8000
.
También puedes usar cualquier otro servidor web, como el servidor HTTP de Apache.
2. Crea un juego en HTML5
Modifica index.html
para crear un elemento de lienzo HTML5 y un botón para activar el juego. Luego, agrega la etiqueta de secuencia de comandos necesaria para cargar el archivo game.js
.
index.html
<!doctype html>
<html lang="en">
<head>
<title>Ad Placement API HTML5 demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<canvas id="gameContainer" height="300px" width="300px"></canvas>
<br>
<button id="playButton">Play</button>
<button style="display:none" id="headsButton">Heads</button>
<button style="display:none" id="tailsButton">Tails</button>
<script src="game.js"></script>
</body>
</html>
Modifica game.js para jugar a un juego de lanzamiento de monedas cuando se haga clic en el botón "Jugar".
game.js
// Create a coin flip game
class Game {
constructor() {
// Define variables
this.score = 0;
this.choice = '';
this.canvas = document.getElementById('gameContainer').getContext('2d');
this.canvas.font = '24px Arial';
this.playButton = document.getElementById('playButton');
this.headsButton = document.getElementById('headsButton');
this.tailsButton = document.getElementById('tailsButton');
// On click listeners for the game's buttons.
this.playButton.addEventListener('click', () => {
this.erase();
this.play();
});
this.headsButton.addEventListener('click', () => {
this.choice = 'Heads';
this.flipCoin();
});
this.tailsButton.addEventListener('click', () => {
this.choice = 'Tails';
this.flipCoin();
});
this.erase();
}
// Start the game
play() {
this.score = 0;
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('Heads or Tails?', 66, 150);
this.playButton.style.display = 'none';
this.headsButton.style.display = 'inline-block';
this.tailsButton.style.display = 'inline-block';
}
// Flip the coin
flipCoin() {
this.headsButton.disabled = true;
this.tailsButton.disabled = true;
this.erase();
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('Flipping coin . . .', 60, 150);
setTimeout(() => { this.coinLanded() }, 2000);
}
// Logic for when the coin lands
coinLanded() {
this.headsButton.disabled = false;
this.tailsButton.disabled = false;
let sideUp;
if(Math.random() < 0.5) {
sideUp = 'Heads';
} else {
sideUp = 'Tails';
}
if (sideUp === this.choice ) {
this.win(sideUp);
} else {
this.lose(sideUp);
}
}
// Guess the flip correctly
win(sideUp) {
this.erase();
this.score += 1;
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('It was ' + sideUp + '!', 66, 150);
this.canvas.fillText('Guess again', 70, 200);
}
// Guess the flip incorrectly
lose(sideUp) {
this.erase();
this.canvas.fillText('Sorry, it was ' + sideUp, 50, 100);
this.canvas.fillText('Your score was ' + this.score, 50, 150);
this.canvas.fillText('Want to play again?', 45, 200);
this.playButton.style.display = 'inline-block';
this.headsButton.style.display = 'none';
this.tailsButton.style.display = 'none';
}
// Erase the canvas
erase() {
this.canvas.fillStyle = '#ADD8E6';
this.canvas.fillRect(0, 0, 300, 300);
this.canvas.fillStyle = '#000000';
}
}
const game = new Game();
Después de completar este paso, cuando abras index.html
en tu navegador (a través de tu servidor de desarrollo), deberías poder ver el lienzo del juego y el botón "Jugar".
Si haces clic en Jugar, debería comenzar el juego de lanzamiento de monedas.
3. Importa la API de Ad Placement
A continuación, agrega la API de Ad Placement a tu juego insertando una etiqueta de secuencia de comandos en index.html
, antes de la etiqueta de game.js
.
La etiqueta de secuencia de comandos puede tomar varios parámetros. Usaremos los siguientes parámetros para especificar el código de propiedad de AdSense y habilitar el modo de prueba:
data-ad-client=<AdSense property code>
Es el código de propiedad de AdSense. Esto siempre es necesario, incluso para los juegos que se ejecutarán dentro de las apps.data-adbreak-test="on"
Habilita el modo de prueba. Quita esto para los juegos una vez que se publiquen para los jugadores.
Configura el código de AdSense y activa el modo de prueba
La funcionalidad de la API de Ad Placement se incluye en el código de AdSense. Para activarlo, primero debes agregar el código de AdSense y un pequeño fragmento de secuencia de comandos que inicialice sus dos funciones clave: adBreak()
y adConfig()
.
index.html (web)
[...]
<canvas id="gameContainer" height="300px" width="300px"></canvas>
<br>
<button id="playButton">Play</button>
<button style="display:none" id="headsButton">Heads</button>
<button style="display:none" id="tailsButton">Tails</button>
<script async
data-adbreak-test="on"
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-123456789"
crossorigin="anonymous">
</script>
<script>
window.adsbygoogle = window.adsbygoogle || [];
const adBreak = adConfig = function(o) {adsbygoogle.push(o);}
</script>
<script src="game.js"></script>
</body>
</html>
Cómo incorporar tu juego (opcional)
Si quieres incorporar un juego en otras páginas dentro de un iframe y la etiqueta adsbygoogle
está en la página HTML del juego, asegúrate de agregar allow='autoplay'
al elemento iframe. Esta es una práctica recomendada y es necesaria para que ciertos anuncios sean aptos para tu juego.
<head>
<!-- The adsbygoogle tag is not here -->
</head>
<body>
<iframe src="https://www.my-game.com" title="My game" allow="autoplay">
<!-- The game is loaded here and contains the adsbygoogle tag -->
</iframe>
</body>
Compatibilidad con aplicaciones para dispositivos móviles
Un juego H5 se puede ejecutar en un navegador web normal, en un WebView
o en una pestaña personalizada de Chrome dentro de una app. La API de Ad Placement puede detectar en qué entorno se ejecuta tu juego y dirigir las solicitudes de anuncios de forma adecuada. Si tu juego se ejecuta en un navegador web normal, las solicitudes de anuncios se tratan como solicitudes normales de AdSense. Si la API de Ad Placement detecta un entorno en la aplicación, se comunica con el SDK de anuncios de Google para dispositivos móviles, si está presente, para solicitar y mostrar anuncios de AdMob.
Esta función es compatible con las apps para Android que se vincularon con el SDK de anuncios de Google para dispositivos móviles. Para habilitarlo, debes registrar el WebView
que mostrará tu juego con el SDK de anuncios de Google para dispositivos móviles y, luego, configurar los bloques de anuncios de AdMob y pasarlos como parámetros adicionales a la etiqueta de AdSense. Cuando tu juego se ejecute en una app adecuada, la API de Ad Placement usará estas unidades de anuncios para mostrar anuncios.
Para habilitar la compatibilidad con dispositivos móviles, debes especificar los siguientes parámetros de etiquetas adicionales:
data-admob-interstitial-slot=<AdMob slot ID>
Es el ID de una unidad de anuncios intersticiales de AdMob que configuraste anteriormente.data-admob-rewarded-slot=<AdMob slot ID>
Es el ID de una unidad de anuncios recompensados de AdMob.
Tu código de propiedad de AdSense siempre debe pasarse con el parámetro data-ad-client
, y se debe especificar al menos uno de los parámetros data-admob-interstitial-slot
o data-admob-rewarded-slot
. Ambos parámetros se deben especificar si tu juego usa ambos formatos.
De manera opcional, también puedes especificar el parámetro de etiqueta data-admob-ads-only=on
para indicar que tu juego solo debe mostrar anuncios de AdMob y no recurrir a AdSense en los casos en que el juego se ejecute en un entorno que no admita solicitudes de AdMob (p.ej., entornos que no son de aplicaciones o aplicaciones sin el SDK de anuncios de Google para dispositivos móviles configurado).
Importante: Cuando diseñes tu juego para que se pueda incorporar dentro de una app de la que eres propietario o si celebras un acuerdo de porcentaje de ingresos con el propietario de la app, la única manera de hacerlo de forma que cumpla con las políticas y tenga un alto rendimiento es mediante esta asistencia de AdMob.
Primero, registra el WebView
que mostrará tu juego con el SDK de anuncios de Google para dispositivos móviles:
MainActivity.java (app)
La configuración predeterminada de WebView
no está optimizada para los anuncios. Usa las APIs de WebSettings
para configurar tu WebView
para lo siguiente:
- JavaScript
- Acceso al almacenamiento local
Reproducción automática de videos
Java
import android.webkit.CookieManager;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
// Let the web view accept third-party cookies.
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);
// Let the web view use JavaScript.
webView.getSettings().setJavaScriptEnabled(true);
// Let the web view access local storage.
webView.getSettings().setDomStorageEnabled(true);
// Let HTML videos play automatically.
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
// Set the H5AdsWebViewClient.
h5AdsWebViewClient = new H5AdsWebViewClient(this, webView);
webView.setWebViewClient(h5AdsWebViewClient);
h5AdsWebViewClient.setDelegateWebViewClient(pubWebViewClient);
// Register the web view.
MobileAds.registerWebView(webView);
}
}
Kotlin
import android.webkit.CookieManager
import android.webkit.WebView
class MainActivity : AppCompatActivity() {
lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.webview)
// Let the web view accept third-party cookies.
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true)
// Let the web view use JavaScript.
webView.settings.javaScriptEnabled = true
// Let the web view access local storage.
webView.settings.domStorageEnabled = true
// Let HTML videos play automatically.
webView.settings.mediaPlaybackRequiresUserGesture = false
// Set the H5AdsWebViewClient.
val h5AdsWebViewClient = H5AdsWebViewClient(this, webView)
webView.webViewClient = h5AdsWebViewClient
h5AdsWebViewClient.delegateWebViewClient = pubWebViewClient
// Register the web view.
MobileAds.registerWebView(webView)
}
}
A continuación, pasa las unidades de anuncios de AdMob (una para los anuncios intersticiales y otra para los anuncios recompensados) de la siguiente manera:
index.html (app)
[...]
<canvas id="gameContainer" height="300px" width="300px"></canvas>
<br>
<button id="playButton">Play</button>
<button style="display:none" id="headsButton">Heads</button>
<button style="display:none" id="tailsButton">Tails</button>
<script async
data-admob-interstitial-slot="ca-app-pub-0987654321/1234567890"
data-admob-rewarded-slot="ca-app-pub-0987654321/0987654321"
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-123456789"
crossorigin="anonymous">
</script>
<script>
window.adsbygoogle = window.adsbygoogle || [];
const adBreak = adConfig = function(o) {adsbygoogle.push(o);}
</script>
<script src="game.js"></script>
</body>
</html>
4. Llama a adConfig()
La llamada adConfig()
comunica la configuración actual del juego a la API de Ad Placement. Luego, la API puede usar esta información para filtrar los tipos de anuncios que solicita, de modo que sean adecuados para el juego (por ejemplo, anuncios de video que requieren sonido, si el sonido está habilitado).
Se debe realizar una llamada a adConfig()
cada vez que cambie esta configuración, por ejemplo, cuando un usuario silencia o reactiva el sonido del juego. Realiza una llamada a adConfig()
en el constructor del juego y, luego, agrega un botón para silenciar y reactivar el sonido del juego que realice una llamada adicional a adConfig()
.
game.js
class Game {
constructor() {
// Define variables
this.score = 0;
this.choice = '';
this.muted = false;
this.canvas = document.getElementById('gameContainer').getContext('2d');
this.canvas.font = '24px Arial';
this.playButton = document.getElementById('playButton');
this.headsButton = document.getElementById('headsButton');
this.tailsButton = document.getElementById('tailsButton');
this.muteButton = document.getElementById('muteButton');
adConfig({
sound: 'on',
});
// On click listeners for the game's buttons.
this.playButton.addEventListener('click', () => {
this.erase();
this.play();
});
this.headsButton.addEventListener('click', () => {
this.choice = 'Heads';
this.flipCoin();
});
this.tailsButton.addEventListener('click', () => {
this.choice = 'Tails';
this.flipCoin();
});
this.muteButton.addEventListener('click', () => {
var soundString = this.muted ? 'on' : 'off';
this.muteButton.innerHTML = this.muted ? 'Mute sound' : 'Un-mute sound';
this.muted = !this.muted;
adConfig({
sound: soundString,
});
});
this.erase();
[...]
Ahora, agrega el botón de silencio a tu archivo HTML.
index.html
[...]
<canvas id="gameContainer" height="300px" width="300px"></canvas>
<br>
<button id="playButton">Play</button>
<button style="display:none" id="headsButton">Heads</button>
<button style="display:none" id="tailsButton">Tails</button>
<button id="muteButton">Mute sound</button>
<script async
data-adbreak-test="on"
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-123456789"
crossorigin="anonymous">
</script>
[...]
5. Llama a adBreak()
cuando finalice el juego
La llamada adBreak()
define una posición del anuncio y toma el objeto llamado configuración de la posición que especifica todo lo que se requiere para mostrar un anuncio en este punto del juego. Para admitir diferentes tipos de anuncios, deberás inicializar diferentes subconjuntos de la configuración de la posición.
La llamada adBreak()
define una posición en la que se podría mostrar un anuncio o, en otras palabras, una oportunidad para mostrar un anuncio. La publicación real de un anuncio dependerá de varios factores:
- Es el tipo de posición del anuncio que declaraste.
- Si hubo interacciones adecuadas del usuario antes de la colocación del anuncio
- Indica si existe un anuncio adecuado para el reproductor actual, que cumpla con las siguientes condiciones:
- Es relevante para ellos.
- Es coherente con su configuración de privacidad y consentimiento de datos.
- Es la cantidad de anuncios que vio el usuario recientemente.
- La configuración de controles que estableciste para este juego como una de las siguientes opciones:
- Sugerencias en la etiqueta
- En AdSense (nota: Los controles disponibles en AdSense evolucionarán con el tiempo)
Agrega código para que se muestre un anuncio intersticial cuando se reinicie el juego: realiza una llamada a adBreak()
dentro de la función play()
, que se ejecuta solo después de que se haya jugado el juego una vez.
Se debe llamar a adBreak()
como parte de una acción del usuario, como hacer clic en el botón "Reproducir"; de lo contrario, la API no podrá solicitar ni mostrar anuncios.
Crea funciones para que se llamen antes y después de la pausa publicitaria, que luego usarás en la configuración de la posición adBreak()
. Es importante tener en cuenta que solo se llamará a las funciones beforeAd
y afterAd
si se encuentra un anuncio adecuado.
game.js
class Game {
constructor() {
// Define variables
this.score = 0;
this.choice = '';
this.muted = false;
this.shouldShowAdOnPlay = false;
[...]
// Start the game
play() {
if (this.shouldShowAdOnPlay) {
this.shouldShowAdOnPlay = false;
adBreak({
type: 'next', // ad shows at start of next level
name: 'restart-game',
beforeAd: () => { this.disableButtons(); }, // You may also want to mute the game's sound.
afterAd: () => { this.enableButtons(); }, // resume the game flow.
});
}
this.score = 0;
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('Heads or Tails?', 66, 150);
this.playButton.style.display = 'none'
this.headsButton.style.display = 'inline-block'
this.tailsButton.style.display = 'inline-block'
}
[...]
// Guess the flip incorrectly
lose(sideUp) {
this.erase()
this.canvas.fillText('Sorry, it was ' + sideUp, 50, 100);
this.canvas.fillText('Your score was ' + this.score, 50, 150);
this.canvas.fillText('Want to play again?', 45, 200);
this.playButton.style.display = 'inline-block'
this.headsButton.style.display = 'none'
this.tailsButton.style.display = 'none'
this.shouldShowAdOnPlay = true;
}
[...]
// Erase the canvas
erase() {
this.canvas.fillStyle = '#ADD8E6';
this.canvas.fillRect(0, 0, 300, 300);
this.canvas.fillStyle = '#000000';
}
enableButtons() {
this.playButton.disabled = false;
this.headsButton.disabled = false;
this.tailsButton.disabled = false;
}
disableButtons() {
this.playButton.disabled = true;
this.headsButton.disabled = true;
this.tailsButton.disabled = true;
}
}
const game = new Game();
6. Llama a adBreak()
para solicitar un anuncio recompensado
Agrega código para que se muestre un anuncio recompensado cuando finalice el juego, pero el usuario quiera revivir su puntuación existente en lugar de comenzar de nuevo. Realiza una llamada a adBreak()
dentro de la función lose()
y verifica si hay un anuncio recompensado disponible. Si es así, muéstrale al usuario un mensaje en el que se le pregunte si quiere la recompensa (es decir, la reactivación en este caso) y, cuando acepte mirar el anuncio, llama al showAdFn()
correspondiente. Puedes configurar qué hacer si el usuario mira o salta los anuncios recompensados con las devoluciones de llamada adViewed
y adDismissed
.
Se debe llamar a un adBreak()
nuevo cada vez que haya una oportunidad de mostrar un anuncio recompensado. Esto garantiza que el anuncio se actualice si el anuncio anterior venció o no estaba disponible.
Se debe llamar a showAdFn()
como parte de una acción directa del usuario para mirar un anuncio. De lo contrario, es posible que el anuncio no se muestre.
Crea funciones para que se llamen antes y después de la pausa publicitaria, que luego usarás en la configuración de la posición adBreak()
. Es importante tener en cuenta que las funciones beforeReward
, adViewed
, adDismissed
, beforeAd
y afterAd
solo se llamarán si se encuentra un anuncio adecuado.
game.js
class Game {
constructor() {
// Define variables
this.score = 0;
this.choice = '';
this.muted = false;
this.shouldShowAdOnPlay = false;
this.showRewardedAdFn = null;
this.canvas = document.getElementById('gameContainer').getContext('2d');
this.canvas.font = '24px Arial';
this.playButton = document.getElementById('playButton');
this.headsButton = document.getElementById('headsButton');
this.tailsButton = document.getElementById('tailsButton');
this.muteButton = document.getElementById('muteButton');
this.continueButton = document.getElementById('continueButton');
adConfig({
sound: 'on',
});
// On click listeners for the game's buttons.
this.playButton.addEventListener('click', () => {
this.erase();
this.play();
});
this.headsButton.addEventListener('click', () => {
this.choice = 'Heads';
this.flipCoin();
});
this.tailsButton.addEventListener('click', () => {
this.choice = 'Tails';
this.flipCoin();
});
this.muteButton.addEventListener('click', () => {
var soundString = this.muted ? 'on' : 'off';
this.muteButton.innerHTML = this.muted ? 'Mute sound' : 'Un-mute sound';
this.muted = !this.muted;
adConfig({
sound: soundString,
});
});
this.continueButton.addEventListener('click', () => {
if (this.showRewardedAdFn) {
this.showRewardedAdFn();
}
});
this.erase();
}
// Start the game
play() {
if (this.shouldShowAdOnPlay) {
this.shouldShowAdOnPlay = false;
adBreak({
type: 'next', // ad shows at start of next level
name: 'restart-game',
beforeAd: () => { this.disableButtons(); }, // You may also want to mute the game's sound.
afterAd: () => { this.enableButtons(); }, // resume the game flow.
});
}
this.score = 0;
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('Heads or Tails?', 66, 150);
this.playButton.style.display = 'none';
this.continueButton.style.display = 'none';
this.headsButton.style.display = 'inline-block';
this.tailsButton.style.display = 'inline-block';
}
[...]
// Guess the flip incorrectly
lose(sideUp) {
this.erase()
this.canvas.fillText('Sorry, it was ' + sideUp, 50, 100);
this.canvas.fillText('Your score was ' + this.score, 50, 150);
this.canvas.fillText('Want to play again?', 45, 200);
this.playButton.style.display = 'inline-block'
this.headsButton.style.display = 'none'
this.tailsButton.style.display = 'none'
this.shouldShowAdOnPlay = true;
adBreak({
type: 'reward', // rewarded ad
name: 'reward-continue',
beforeReward: (showAdFn) => {
this.showRewardedAdFn = () => { showAdFn(); };
// Rewarded ad available - prompt user for a rewarded ad
this.continueButton.style.display = 'inline-block';
},
beforeAd: () => { this.disableButtons(); }, // You may also want to mute the game's sound.
adDismissed: () => {
this.continueButton.style.display = 'none'; // Hide the reward button and continue lose flow.
},
adViewed: () => { this.continueGame(); }, // Reward granted - continue game at current score.
afterAd: () => { this.enableButtons(); }, // Resume the game flow.
});
}
// Continue gameplay at current score
continueGame() {
this.erase();
this.canvas.fillText('Score: ' + this.score, 8, 26);
this.canvas.fillText('Heads or Tails?', 66, 150);
this.playButton.style.display = 'none';
this.continueButton.style.display = 'none';
this.headsButton.style.display = 'inline-block';
this.tailsButton.style.display = 'inline-block';
}
[...]
}
const game = new Game();
Ahora, agrega el botón de continuar a tu archivo HTML.
index.html
[...]
<canvas id="gameContainer" height="300px" width="300px"></canvas>
<br>
<button id="playButton">Play</button>
<button style="display:none" id="headsButton">Heads</button>
<button style="display:none" id="tailsButton">Tails</button>
<button style="display:none" id="continueButton">Watch Ad to continue?</button>
<button id="muteButton">Mute sound</button>
<script async
data-adbreak-test="on"
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-123456789"
crossorigin="anonymous">
</script>
[...]
La app de lanzamiento de moneda ahora está creando posiciones para mostrar anuncios.
Tu propia app puede tener otros lugares adecuados para los anuncios, además de cuando finaliza el juego. Llamar a adBreak()
en esos lugares debería ser similar a este ejemplo.
Cómo desactivar las pruebas para las apps en producción
Antes de lanzar tu app, es importante que quites o comentes la línea data-adbreak-test="on"
en index.html
, ya que este código activa la configuración de prueba en producción.