Interstitial Ads
Interstitial ads are full-screen advertisements shown between natural breaks in your game, such as between levels or after game over.
Overview
Use Cases:
- Between game levels
- Game over screen
- Main menu transitions
- Pause screen returns
Characteristics:
- Full-screen overlay
- User must close to continue
- High engagement rate
- Display or video format
Basic Usage
Display Interstitial (GPT)
sdk.createInterstitial({
placement: 'level_complete',
onComplete: () => {
// Ad closed - continue game
loadNextLevel();
},
onError: (error) => {
console.warn('Interstitial error:', error);
loadNextLevel(); // Continue anyway
}
});
Video Interstitial (IMA)
sdk.showInterstitialVideo({
placement: 'game_over',
onComplete: () => {
showMainMenu();
}
}, 'https://pubads.g.doubleclick.net/gampad/ads?...');
Configuration Options
InterstitialConfig Interface
interface InterstitialConfig {
/** Placement identifier for reporting (required) */
placement: string;
/** Ad unit path (optional - uses default if not provided) */
adUnitPath?: string;
/** Custom targeting (optional) */
targeting?: Record<string, string | string[]>;
/** Callbacks */
onLoad?: () => void;
onError?: (error: Error) => void;
onComplete?: () => void;
onImpression?: () => void;
onClose?: () => void;
}
Complete Examples
Example 1: Level Transition
// Game code
class Game {
async onLevelComplete(levelNumber) {
// Show completion screen
this.showLevelCompleteScreen(levelNumber);
// Show interstitial ad
await sdk.createInterstitial({
placement: `level_${levelNumber}_complete`,
targeting: {
level: levelNumber.toString(),
difficulty: this.difficulty
},
onComplete: () => {
// Ad finished - load next level
this.loadLevel(levelNumber + 1);
},
onError: (error) => {
// Ad failed - continue to next level anyway
console.warn('Interstitial failed:', error);
this.loadLevel(levelNumber + 1);
}
});
}
}
Example 2: Game Over
class Game {
async onGameOver(score) {
// Show game over screen
this.showGameOverScreen(score);
// Show interstitial after 2 seconds
setTimeout(async () => {
await sdk.createInterstitial({
placement: 'game_over',
targeting: {
score: score.toString(),
session_length: this.getSessionLength()
},
onComplete: () => {
// Show main menu
this.showMainMenu();
}
});
}, 2000);
}
}
Example 3: Pause Menu Exit
class PauseMenu {
async onExitToMenu() {
// User wants to exit to main menu
const confirmed = await this.showConfirmDialog(
'Exit to main menu?'
);
if (confirmed) {
// Show interstitial before returning to menu
await sdk.createInterstitial({
placement: 'pause_exit',
onComplete: () => {
this.exitToMainMenu();
},
onError: () => {
// Still exit even if ad fails
this.exitToMainMenu();
}
});
}
}
}
Frequency Capping
Avoid showing interstitials too frequently:
class AdManager {
constructor() {
this.lastInterstitialTime = 0;
this.minInterstitialInterval = 180000; // 3 minutes
}
async showInterstitial(placement) {
const now = Date.now();
const timeSinceLastAd = now - this.lastInterstitialTime;
// Check if enough time has passed
if (timeSinceLastAd < this.minInterstitialInterval) {
console.log('Interstitial skipped - too soon');
return false;
}
// Show the ad
try {
await sdk.createInterstitial({
placement,
onComplete: () => {
this.lastInterstitialTime = Date.now();
}
});
return true;
} catch (error) {
console.warn('Interstitial error:', error);
return false;
}
}
}
// Usage
const adManager = new AdManager();
// Level complete
if (await adManager.showInterstitial('level_complete')) {
console.log('Showed interstitial');
}
Video Interstitials
Basic Video Ad
sdk.showInterstitialVideo({
placement: 'level_complete_video',
onComplete: () => {
console.log('Video completed');
loadNextLevel();
},
onError: (error) => {
console.warn('Video error:', error);
loadNextLevel();
}
}, 'https://pubads.g.doubleclick.net/gampad/ads?iu=/YOUR_AD_UNIT&...');
Custom VAST Tag
const vastTag = [
'https://pubads.g.doubleclick.net/gampad/ads',
'?iu=/21775744923/getjar_interstitial',
'&description_url=' + encodeURIComponent(window.location.href),
'&tfcd=0',
'&npa=0',
'&sz=640x480',
'&gdfp_req=1',
'&output=vast',
'&unviewed_position_start=1',
'&env=vp',
'&impl=s',
'&correlator=' + Date.now()
].join('');
sdk.showInterstitialVideo({
placement: 'custom_video',
onComplete: () => console.log('Done')
}, vastTag);
Best Practices
1. Timing
Show interstitials at natural breaks:
// ✅ Good - natural break points
onLevelComplete() → Show interstitial
onGameOver() → Show interstitial
onPauseExit() → Show interstitial
// ❌ Bad - interrupts gameplay
onPlayerDeath() → Don't interrupt mid-game
onMenuOpen() → Don't interrupt navigation
onButtonClick() → Too frequent
2. Fallback Logic
Always provide fallback when ad fails:
async function showInterstitialWithFallback() {
try {
await sdk.createInterstitial({
placement: 'level_complete',
onComplete: () => continueGame(),
onError: () => continueGame() // Fallback
});
} catch (error) {
// SDK error - still continue
continueGame();
}
}
3. User Experience
Prepare the user for an ad:
async function showLevelCompleteAd() {
// 1. Show completion screen
showLevelCompleteScreen();
// 2. Wait a moment (let user see score)
await delay(2000);
// 3. Show loading indicator
showLoadingIndicator();
// 4. Show ad
await sdk.createInterstitial({
placement: 'level_complete',
onComplete: hideLoadingIndicator
});
// 5. Continue to next level
loadNextLevel();
}
4. Frequency
Limit interstitial frequency:
// Recommended intervals
const INTERSTITIAL_COOLDOWN = {
level_complete: 180000, // 3 minutes
game_over: 120000, // 2 minutes
pause_exit: 300000 // 5 minutes
};
Advanced Features
Progressive Cooldown
Increase cooldown based on ad count:
class AdFrequency {
constructor() {
this.adCount = 0;
this.baseCooldown = 120000; // 2 minutes
}
getCooldown() {
// Increase cooldown after each ad
return this.baseCooldown + (this.adCount * 60000);
}
async showAd(placement) {
const cooldown = this.getCooldown();
if (this.canShowAd(cooldown)) {
await sdk.createInterstitial({
placement,
onComplete: () => {
this.adCount++;
this.lastAdTime = Date.now();
}
});
}
}
}
A/B Testing
Test different interstitial strategies:
class InterstitialABTest {
constructor() {
// Assign user to test group
this.testGroup = Math.random() < 0.5 ? 'A' : 'B';
}
shouldShowInterstitial(levelNumber) {
if (this.testGroup === 'A') {
// Group A: Every level
return true;
} else {
// Group B: Every other level
return levelNumber % 2 === 0;
}
}
async maybeShowInterstitial(levelNumber) {
if (this.shouldShowInterstitial(levelNumber)) {
await sdk.createInterstitial({
placement: `level_${levelNumber}_complete`,
targeting: {
ab_test_group: this.testGroup
}
});
}
}
}
Conditional Display
Show based on user segments:
async function showInterstitialIfEligible() {
const user = getCurrentUser();
// Skip for premium users
if (user.isPremium) {
console.log('Premium user - skipping ad');
return;
}
// Skip for new users (first 3 sessions)
if (user.sessionCount < 3) {
console.log('New user - skipping ad');
return;
}
// Show interstitial
await sdk.createInterstitial({
placement: 'level_complete',
targeting: {
user_type: user.type,
session_count: user.sessionCount.toString()
}
});
}
Troubleshooting
Ad Not Showing
Problem: Interstitial doesn't appear
Solutions:
-
Check SDK is initialized:
if (!sdk.isReady()) {
await sdk.init({ ... });
} -
Verify no ad blocker is active
-
Check browser console for errors
-
Ensure sufficient time between ads
Ad Blocks Gameplay
Problem: Game frozen after interstitial
Solutions:
-
Always use
onCompletecallback:sdk.createInterstitial({
placement: 'level_complete',
onComplete: () => {
resumeGame(); // Critical!
}
}); -
Add timeout fallback:
const timeout = setTimeout(() => {
console.warn('Interstitial timeout');
resumeGame();
}, 30000); // 30 second fallback
sdk.createInterstitial({
placement: 'level_complete',
onComplete: () => {
clearTimeout(timeout);
resumeGame();
}
});
Too Many Ads
Problem: Users see too many interstitials
Solution: Implement frequency capping:
class AdCapper {
constructor() {
this.adTimes = [];
this.maxAdsPerHour = 4;
}
canShowAd() {
const now = Date.now();
const oneHourAgo = now - 3600000;
// Remove ads older than 1 hour
this.adTimes = this.adTimes.filter(time => time > oneHourAgo);
// Check if under limit
return this.adTimes.length < this.maxAdsPerHour;
}
recordAd() {
this.adTimes.push(Date.now());
}
async maybeShowInterstitial(placement) {
if (!this.canShowAd()) {
console.log('Ad frequency limit reached');
return false;
}
await sdk.createInterstitial({
placement,
onComplete: () => {
this.recordAd();
}
});
return true;
}
}
Testing
Development Testing
// Test mode - shows test ads frequently
await sdk.init({
environment: 'development'
});
sdk.createInterstitial({
placement: 'test_interstitial'
});
Production Testing
// Test in production with debug logging
sdk.createInterstitial({
placement: 'level_complete',
onLoad: () => console.log('[TEST] Interstitial loaded'),
onImpression: () => console.log('[TEST] Interstitial shown'),
onClose: () => console.log('[TEST] Interstitial closed'),
onComplete: () => console.log('[TEST] Interstitial complete'),
onError: (error) => console.error('[TEST] Interstitial error:', error)
});
Analytics
Track interstitial performance:
const analytics = {
shown: 0,
completed: 0,
errors: 0
};
sdk.createInterstitial({
placement: 'level_complete',
onLoad: () => {
analytics.shown++;
console.log(`Interstitials shown: ${analytics.shown}`);
},
onComplete: () => {
analytics.completed++;
console.log(`Completion rate: ${(analytics.completed / analytics.shown * 100).toFixed(1)}%`);
},
onError: (error) => {
analytics.errors++;
console.error(`Error rate: ${(analytics.errors / analytics.shown * 100).toFixed(1)}%`);
}
});
Related Documentation
- Banner Ads - Fixed-position ads
- Rewarded Ads - Ads with in-game rewards
- Video Ads - IMA video integration
Support
Need help with interstitial ads? Contact: support@getjar.com