Skip to main content

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:

  1. Check SDK is initialized:

    if (!sdk.isReady()) {
    await sdk.init({ ... });
    }
  2. Verify no ad blocker is active

  3. Check browser console for errors

  4. Ensure sufficient time between ads


Ad Blocks Gameplay

Problem: Game frozen after interstitial

Solutions:

  1. Always use onComplete callback:

    sdk.createInterstitial({
    placement: 'level_complete',
    onComplete: () => {
    resumeGame(); // Critical!
    }
    });
  2. 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)}%`);
}
});


Support

Need help with interstitial ads? Contact: support@getjar.com