Unity Integration Guide
Integrate AppSpike into your Unity project and serve your first ad in under an hour.
AppSpike sits on top of your existing ad networks and routes every impression to the highest-paying demand source. You keep your current ad network accounts — AppSpike optimizes across all of them.
Prerequisites
- Unity 2021.3 LTS or later
- iOS 13+ / Android API 21+
- An AppSpike account and App ID (sign up)
Step 1: Import the SDK
Download the AppSpike Unity Plugin from the AppSpike dashboard or add it via the Unity Package Manager.
Option A: Unity Package Manager
Open Window > Package Manager, click + > Add package from git URL, and enter:
https://github.com/appspike/unity-sdk.git
Option B: .unitypackage
Download AppSpike.unitypackage from the dashboard and import via Assets > Import Package > Custom Package.
After importing, the AppSpike menu appears under AppSpike > Settings in the Unity menu bar.
Step 2: Configure Your App ID
Open AppSpike > Settings in the Unity menu bar and enter your App ID for each platform:
- Android App ID:
YOUR_APP_ID - iOS App ID:
YOUR_APP_ID
Alternatively, configure via code (see initialization below).
Step 3: Initialize the SDK
Initialize AppSpike as early as possible. Create a persistent GameObject or use your existing game manager:
AdManager.csusing AppSpikeSDK;
public class AdManager : MonoBehaviour
{
void Start()
{
AppSpike.Initialize("YOUR_APP_ID", (result) =>
{
if (result.IsSuccess)
{
Debug.Log($"AppSpike initialized — {result.AdapterCount} adapters loaded");
}
else
{
Debug.LogError($"AppSpike init failed: {result.Error}");
}
});
}
}
Attach this script to a GameObject in your first scene and mark it with DontDestroyOnLoad:
void Awake()
{
DontDestroyOnLoad(gameObject);
}
Step 4: Banner Ads
BannerExample.csusing AppSpikeSDK;
public class BannerExample : MonoBehaviour
{
private BannerAd bannerAd;
void Start()
{
bannerAd = new BannerAd("YOUR_APPSPIKE_PLACEMENT", BannerPosition.Bottom);
bannerAd.OnAdLoaded += () =>
{
Debug.Log("Banner loaded");
};
bannerAd.OnAdFailedToLoad += (error) =>
{
Debug.LogError($"Banner failed: {error}");
};
bannerAd.Load();
}
public void ShowBanner()
{
bannerAd.Show();
}
public void HideBanner()
{
bannerAd.Hide();
}
void OnDestroy()
{
bannerAd?.Destroy();
}
}
BannerPosition options: Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight.
Step 5: Interstitial Ads
InterstitialExample.csusing AppSpikeSDK;
public class InterstitialExample : MonoBehaviour
{
private InterstitialAd interstitialAd;
void Start()
{
LoadInterstitial();
}
private void LoadInterstitial()
{
AppSpike.LoadInterstitialAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess)
{
interstitialAd = result.Ad;
}
else
{
Debug.LogError($"Interstitial failed to load: {result.Error}");
}
});
}
// Call this at a natural break point (e.g., between levels)
public void ShowInterstitial()
{
if (interstitialAd != null)
{
interstitialAd.Show(new InterstitialAd.ShowCallbacks
{
OnAdDismissed = () =>
{
interstitialAd = null;
LoadInterstitial(); // Pre-load the next one
},
OnAdFailedToShow = (error) =>
{
Debug.LogError($"Interstitial failed to show: {error}");
}
});
}
else
{
Debug.Log("Interstitial not ready yet");
}
}
}
Step 6: Rewarded Ads
RewardedExample.csusing AppSpikeSDK;
public class RewardedExample : MonoBehaviour
{
private RewardedAd rewardedAd;
void Start()
{
LoadRewarded();
}
private void LoadRewarded()
{
AppSpike.LoadRewardedVideoAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess)
{
rewardedAd = result.Ad;
}
else
{
Debug.LogError($"Rewarded ad failed to load: {result.Error}");
}
});
}
// Call this when the user opts in (e.g., "Watch ad for 50 coins")
public void ShowRewarded()
{
if (rewardedAd != null)
{
rewardedAd.Show(new RewardedAd.ShowCallbacks
{
OnUserEarnedReward = (reward) =>
{
Debug.Log($"User earned: {reward.Amount} {reward.Type}");
GrantReward(reward.Amount);
},
OnAdDismissed = () =>
{
rewardedAd = null;
LoadRewarded();
},
OnAdFailedToShow = (error) =>
{
Debug.LogError($"Rewarded ad failed to show: {error}");
}
});
}
else
{
Debug.Log("Rewarded ad not ready yet");
}
}
public bool IsRewardedReady()
{
return rewardedAd != null;
}
private void GrantReward(int amount)
{
// Your reward logic here
}
}
Step 7: App Open Ads
App open ads display when users return to your game. Use OnApplicationPause to trigger them:
using AppSpikeSDK;
public class AppOpenAdManager : MonoBehaviour
{
private AppOpenAd appOpenAd;
void Start()
{
DontDestroyOnLoad(gameObject);
LoadAppOpenAd();
}
private void LoadAppOpenAd()
{
AppSpike.LoadAppOpenAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess)
{
appOpenAd = result.Ad;
}
else
{
Debug.LogError($"App open ad failed to load: {result.Error}");
}
});
}
void OnApplicationPause(bool paused)
{
if (!paused && appOpenAd != null)
{
appOpenAd.Show(new AppOpenAd.ShowCallbacks
{
OnAdDismissed = () =>
{
appOpenAd = null;
LoadAppOpenAd();
},
OnAdFailedToShow = (error) =>
{
Debug.LogError($"App open ad failed to show: {error}");
}
});
}
}
}
Step 8: Rewarded Interstitial Ads
RewardedInterstitialExample.csusing AppSpikeSDK;
public class RewardedInterstitialExample : MonoBehaviour
{
private RewardedInterstitialAd rewardedInterstitialAd;
void Start()
{
LoadRewardedInterstitial();
}
private void LoadRewardedInterstitial()
{
AppSpike.LoadRewardedInterstitialAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess)
{
rewardedInterstitialAd = result.Ad;
}
else
{
Debug.LogError($"Rewarded interstitial failed to load: {result.Error}");
}
});
}
public void ShowRewardedInterstitial()
{
if (rewardedInterstitialAd != null)
{
rewardedInterstitialAd.Show(new RewardedInterstitialAd.ShowCallbacks
{
OnUserEarnedReward = (reward) =>
{
Debug.Log($"User earned: {reward.Amount} {reward.Type}");
GrantReward(reward.Amount);
},
OnAdDismissed = () =>
{
rewardedInterstitialAd = null;
LoadRewardedInterstitial();
},
OnAdFailedToShow = (error) =>
{
Debug.LogError($"Rewarded interstitial failed to show: {error}");
}
});
}
else
{
Debug.Log("Rewarded interstitial not ready yet");
}
}
private void GrantReward(int amount)
{
// Your reward logic here
}
}
Centralized Ad Manager Pattern
For production games, manage all ads from a single singleton:
GameAdManager.csusing AppSpikeSDK;
using UnityEngine;
public class GameAdManager : MonoBehaviour
{
public static GameAdManager Instance { get; private set; }
private InterstitialAd interstitialAd;
private RewardedAd rewardedAd;
private BannerAd bannerAd;
void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
void Start()
{
AppSpike.Initialize("YOUR_APP_ID", (result) =>
{
if (result.IsSuccess)
{
LoadInterstitial();
LoadRewarded();
SetupBanner();
}
});
}
// ── Banner ──
private void SetupBanner()
{
bannerAd = new BannerAd("YOUR_APPSPIKE_PLACEMENT", BannerPosition.Bottom);
bannerAd.Load();
}
public void ShowBanner() => bannerAd?.Show();
public void HideBanner() => bannerAd?.Hide();
// ── Interstitial ──
private void LoadInterstitial()
{
AppSpike.LoadInterstitialAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess) interstitialAd = result.Ad;
});
}
public void ShowInterstitial(System.Action onComplete = null)
{
if (interstitialAd == null) { onComplete?.Invoke(); return; }
interstitialAd.Show(new InterstitialAd.ShowCallbacks
{
OnAdDismissed = () =>
{
interstitialAd = null;
LoadInterstitial();
onComplete?.Invoke();
},
OnAdFailedToShow = (_) =>
{
onComplete?.Invoke();
}
});
}
// ── Rewarded ──
private void LoadRewarded()
{
AppSpike.LoadRewardedVideoAd("YOUR_APPSPIKE_PLACEMENT", (result) =>
{
if (result.IsSuccess) rewardedAd = result.Ad;
});
}
public bool IsRewardedReady => rewardedAd != null;
public void ShowRewarded(System.Action<int> onReward, System.Action onFail = null)
{
if (rewardedAd == null) { onFail?.Invoke(); return; }
rewardedAd.Show(new RewardedAd.ShowCallbacks
{
OnUserEarnedReward = (reward) => onReward?.Invoke(reward.Amount),
OnAdDismissed = () =>
{
rewardedAd = null;
LoadRewarded();
},
OnAdFailedToShow = (_) => onFail?.Invoke()
});
}
}
Usage from any script:
Usage Example// Show interstitial between levels
GameAdManager.Instance.ShowInterstitial(() =>
{
SceneManager.LoadScene("Level2");
});
// Show rewarded ad for coins
if (GameAdManager.Instance.IsRewardedReady)
{
GameAdManager.Instance.ShowRewarded(
onReward: (amount) => PlayerData.AddCoins(amount),
onFail: () => Debug.Log("Rewarded ad not available")
);
}
Testing
Enable test mode during development:
AppSpike.Initialize("YOUR_APP_ID", testMode: true, callback: (result) =>
{
// Test ads will always fill and never charge
});
Open the ad inspector from the Unity Editor or at runtime:
AppSpike.OpenAdInspector();
The ad inspector shows:
- Which adapters are initialized
- Bid responses per demand source
- Fill rates and latency per network
- Which network won each impression
Platform-Specific Setup
Android
Add the AppSpike Maven repository. In Assets/Plugins/Android/mainTemplate.gradle or via the settings in AppSpike > Settings:
repositories {
maven { url 'https://sdk.appspike.dev/android' }
}
iOS
AppSpike's iOS dependencies are managed via CocoaPods. After building for iOS, run:
Terminalcd Build/iOS
pod install
Or enable AppSpike > Settings > Auto-resolve iOS dependencies to handle this automatically.
Add the NSUserTrackingUsageDescription key to your Info.plist for ATT compliance:
<key>NSUserTrackingUsageDescription</key>
<string>This allows us to show you more relevant ads.</string>
Best Practices
- Pre-load interstitials and rewarded ads as early as possible, then show them at natural break points. Never interrupt the player mid-action.
- Always reload after dismissal. Each ad object is single-use — load the next one in the
OnAdDismissedcallback. - Use
DontDestroyOnLoadon your ad manager GameObject so it persists across scene loads. - Ship with at least 3 ad network adapters. More demand sources means higher competition and higher eCPMs.
- Use test mode during development. Live impressions from test devices waste ad budget and can flag your account.
- Don't gate core gameplay behind rewarded ads. Use them for optional bonuses (extra lives, cosmetics, currency).
- Handle scene transitions. Destroy banner ads before loading new scenes if the banner shouldn't persist.