SDK Docs
Drop the Appaloo Android SDK into your app and serve your ads with a few lines of code.
Drop the Appaloo iOS SDK into your app and serve your ads with a few lines of code.
Installation
Add the Appaloo SDK to your Android project from our Maven repository. The SDK targets Android API 30+.
settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://download.appaloo.io/appaloo-sdk/android") }
}
}
app/build.gradle.kts
dependencies {
implementation("io.appaloo:sdk:1.0.3")
}
settings.gradle
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://download.appaloo.io/appaloo-sdk/android' }
}
}
app/build.gradle
dependencies {
implementation 'io.appaloo:sdk:1.0.3'
}
Initialization
Construct an AppalooClient with your ad's UUID. When integrating multiple ads, a client can be created for each ad. It's a lightweight object.
import com.appaloo.AppalooClient
private val appaloo = AppalooClient(
adId = "{adID}",
)
import com.appaloo.AppalooClient;
private final AppalooClient appaloo = new AppalooClient("{adID}");
Interstitial Ads
Interstitial ads are full-screen ads that can serve as a natural break between screens, or as a standalone ad triggered by user action.
Users can dismiss these ads after a 15-second countdown or, for video ads, when the video ends.
import com.appaloo.AppalooClient
import com.appaloo.AdDetails
import com.appaloo.InterstitialCallbacks
class MainActivity : AppCompatActivity() {
private val appaloo = AppalooClient("{adID}")
private fun showAd() {
appaloo.loadInterstitial(this, object : InterstitialCallbacks {
override fun onAdLoaded(adDetails: AdDetails) {
Log.d("Appaloo", "Showing ad for ${adDetails.appName}")
}
override fun onAdLoadFailed(errorCode: Int, message: String) {
Log.w("Appaloo", "Ad failed: $errorCode - $message")
}
})
}
}
import com.appaloo.AppalooClient;
import com.appaloo.AdDetails;
import com.appaloo.InterstitialCallbacks;
public class MainActivity extends AppCompatActivity {
private final AppalooClient appaloo =
new AppalooClient("{adID}", "https://appaloo.io");
private void showAd() {
appaloo.loadInterstitial(this, new InterstitialCallbacks() {
@Override
public void onAdLoaded(AdDetails adDetails) {
Log.d("Appaloo", "Showing ad for " + adDetails.getAppName());
}
@Override
public void onAdLoadFailed(int errorCode, String message) {
Log.w("Appaloo", "Ad failed: " + errorCode + " - " + message);
}
});
}
}
Rewarded Ads
Rewarded ads are video ads that reward the user for watching the entire ad. They are typically used to incentivize users to complete a task or engage with the app.
Same flow as loadInterstitial, but the SDK invokes onAdFinished only after the user has fully viewed the ad. Grant your reward inside this callback.
import com.appaloo.AppalooClient
import com.appaloo.AdDetails
import com.appaloo.RewardedCallbacks
class GameActivity : AppCompatActivity() {
private val appaloo = AppalooClient("{adID}")
private fun grantBonusLife() {
appaloo.loadRewarded(this, object : RewardedCallbacks {
override fun onAdLoaded(adDetails: AdDetails) {
// Ad is on screen; do not credit yet.
}
override fun onAdFinished(adDetails: AdDetails) {
// User finished watching: credit the reward here.
player.lives += 1
}
override fun onAdLoadFailed(errorCode: Int, message: String) {
Log.w("Appaloo", "Reward unavailable ($errorCode)")
}
})
}
}
import com.appaloo.AppalooClient;
import com.appaloo.AdDetails;
import com.appaloo.RewardedCallbacks;
public class GameActivity extends AppCompatActivity {
private final AppalooClient appaloo =
new AppalooClient("{adID}", "https://appaloo.io");
private void grantBonusLife() {
appaloo.loadRewarded(this, new RewardedCallbacks() {
@Override
public void onAdLoaded(AdDetails adDetails) {
// Ad is on screen; do not credit yet.
}
@Override
public void onAdFinished(AdDetails adDetails) {
// User finished watching: credit the reward here.
player.lives += 1;
}
@Override
public void onAdLoadFailed(int errorCode, String message) {
Log.w("Appaloo", "Reward unavailable (" + errorCode + ")");
}
});
}
}
Important: only credit the reward inside onAdFinished. onAdLoaded fires as soon as the ad is rendered, before the user has watched it.
Inline Ads
Inline ads are small ads that embed in your own layout. They may be used within a news feed, directory, photo reel, and more.
import com.appaloo.AppalooClient
import android.view.ViewGroup
class FeedActivity : AppCompatActivity() {
private val appaloo = AppalooClient("{adID}")
private fun addInlineAd(container: ViewGroup) {
val adView = appaloo.loadInline(this)
container.addView(adView)
}
}
import com.appaloo.AppalooClient;
import android.view.View;
import android.view.ViewGroup;
public class FeedActivity extends AppCompatActivity {
private final AppalooClient appaloo = new AppalooClient("{adID}");
private void addInlineAd(ViewGroup container) {
View adView = appaloo.loadInline(this);
container.addView(adView);
}
}
In Jetpack Compose, wrap it in an AndroidView:
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.appaloo.AdDetails
import com.appaloo.AppalooClient
import com.appaloo.InlineCallbacks
@Composable
fun AppalooInlineAd(modifier: Modifier = Modifier) {
val appaloo = remember { AppalooClient("{adID}") }
var hasAd by remember { mutableStateOf(true) }
if (hasAd) {
AndroidView(
modifier = modifier.fillMaxWidth().height(275.dp),
factory = { ctx ->
appaloo.loadInline(ctx, object : InlineCallbacks {
override fun onAdLoaded(adDetails: AdDetails) {}
override fun onAdLoadFailed(errorCode: Int, message: String) {
hasAd = false
}
})
},
)
}
}
@Composable
fun Feed() {
LazyColumn {
item { Text("A post") }
item { AppalooInlineAd() }
item { Text("Another post") }
}
}
Banner Ads
Banner ads are a full-width, compact anchored strip. loadBanner returns a View you add wherever you want it, but would typically be anchored to the bottom of the screen. It fills itself in when an ad is served and collapses to zero height if none is available.
import com.appaloo.AppalooClient
import com.appaloo.AdDetails
import com.appaloo.BannerCallbacks
import android.view.ViewGroup
class MainActivity : AppCompatActivity() {
private val appaloo = AppalooClient("{adID}")
private fun addBanner(container: ViewGroup) {
val adView = appaloo.loadBanner(this, object : BannerCallbacks {
override fun onAdLoaded(adDetails: AdDetails) {
Log.d("Appaloo", "Banner for ${adDetails.appName}")
}
override fun onAdLoadFailed(errorCode: Int, message: String) {
Log.w("Appaloo", "Banner failed: $errorCode - $message")
}
})
container.addView(adView)
}
}
import com.appaloo.AppalooClient;
import com.appaloo.AdDetails;
import com.appaloo.BannerCallbacks;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends AppCompatActivity {
private final AppalooClient appaloo = new AppalooClient("{adID}");
private void addBanner(ViewGroup container) {
View adView = appaloo.loadBanner(this, new BannerCallbacks() {
@Override
public void onAdLoaded(AdDetails adDetails) {
Log.d("Appaloo", "Banner for " + adDetails.getAppName());
}
@Override
public void onAdLoadFailed(int errorCode, String message) {
Log.w("Appaloo", "Banner failed: " + errorCode + " - " + message);
}
});
container.addView(adView);
}
}
In Jetpack Compose, wrap it in an AndroidView:
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.appaloo.AdDetails
import com.appaloo.AppalooClient
import com.appaloo.BannerCallbacks
@Composable
fun AppalooBannerAd(modifier: Modifier = Modifier) {
val appaloo = remember { AppalooClient("{adID}") }
var hasAd by remember { mutableStateOf(true) }
var hasLoadedAd by remember { mutableStateOf(false) }
if (hasAd) {
AndroidView(
modifier = modifier.fillMaxWidth().height(64.dp),
factory = { ctx ->
appaloo.loadBanner(ctx, object : BannerCallbacks {
override fun onAdLoaded(adDetails: AdDetails) { hasLoadedAd = true }
override fun onAdLoadFailed(errorCode: Int, message: String) {
// Keep the current banner if an automatic refresh fails.
if (!hasLoadedAd) hasAd = false
}
})
},
)
}
}
@Composable
fun HomeScreen() {
Column {
// your app content
Spacer(Modifier.weight(1f))
AppalooBannerAd()
}
}
App Open Ads
App Open ads are brief full-screen ads suitable for app launch or return-to-foreground events.
import com.appaloo.AppalooClient
import com.appaloo.AdDetails
import com.appaloo.InterstitialCallbacks
class MainActivity : AppCompatActivity() {
private val appaloo = AppalooClient("{adID}")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
appaloo.loadAppOpen(this, object : InterstitialCallbacks {
override fun onAdLoaded(adDetails: AdDetails) {
Log.d("Appaloo", "App Open ad for ${adDetails.appName}")
}
override fun onAdLoadFailed(errorCode: Int, message: String) {
Log.w("Appaloo", "App Open failed: $errorCode - $message")
}
})
}
}
import com.appaloo.AppalooClient;
import com.appaloo.AdDetails;
import com.appaloo.InterstitialCallbacks;
public class MainActivity extends AppCompatActivity {
private final AppalooClient appaloo = new AppalooClient("{adID}");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// A brief full-screen ad for launch / return-to-foreground that
// auto-dismisses after ~5 seconds. Reuses InterstitialCallbacks.
appaloo.loadAppOpen(this, new InterstitialCallbacks() {
@Override
public void onAdLoaded(AdDetails adDetails) {
Log.d("Appaloo", "App Open ad for " + adDetails.getAppName());
}
@Override
public void onAdLoadFailed(int errorCode, String message) {
Log.w("Appaloo", "App Open failed: " + errorCode + " - " + message);
}
});
}
}
Data Safety
The SDK collects no advertising ID and no device identifiers. The only data it reports is which ads a user views or clicks, which keeps your Google Play Data Safety form short.
What to declare
Declare ad view and click events under App activity (App interactions): collected, encrypted in transit, and not linked to a persistent identifier. Pick App functionality and/or Advertising as the purpose to match how you describe Appaloo.
What the SDK does not collect
No Google Advertising ID (AAID), no ANDROID_ID, no device info, and no location. The SDK requests only the INTERNET permission. Do not add the AD_ID permission on its behalf.
Installation
The Appaloo SDK ships as a prebuilt XCFramework served straight from our CDN. It targets iOS 15+ and includes no additional dependencies.
Xcode (Add Local package)
Drop this one-file Swift package into your project, then in Xcode choose File → Add Package Dependencies → Add Local… and select the folder. Xcode downloads and verifies the binary from the CDN.
mkdir AppalooSDK && curl -fsSL \
https://download.appaloo.io/appaloo-sdk/ios/AppalooSDK/Package.swift \
-o AppalooSDK/Package.swift
Package.swift
Or, if your app is itself a Swift package, declare the binary target directly:
targets: [
.binaryTarget(
name: "AppalooSDK",
url: "https://download.appaloo.io/appaloo-sdk/ios/AppalooSDK-1.0.4.xcframework.zip",
checksum: "3aae03b7fb81068b71c4d45d3c302d32d6668308adb38060ac0498d4c2613ae0"
),
.target(name: "MyApp", dependencies: ["AppalooSDK"]),
]
Initialization
Construct an AppalooClient with your ad's UUID. When integrating multiple ads, a client can be created for each ad. It's a lightweight object.
import AppalooSDK
private let appaloo = AppalooClient(adId: "{adID}")
Interstitial Ads
Interstitial ads are full-screen ads that can serve as a natural break between screens, or as a standalone ad triggered by user action.
Users can dismiss these ads after a 15-second countdown or, for video ads, when the video ends.
import UIKit
import AppalooSDK
final class MainViewController: UIViewController, InterstitialCallbacks {
private let appaloo = AppalooClient(adId: "{adID}")
private func showAd() {
appaloo.loadInterstitial(from: self, callbacks: self)
}
func onAdLoaded(adDetails: AdDetails) {
print("Showing ad for \(adDetails.appName)")
}
func onAdLoadFailed(errorCode: Int, message: String) {
print("Ad failed: \(errorCode) - \(message)")
}
}
InterstitialCallbacks
public protocol InterstitialCallbacks: AnyObject {
func onAdLoaded(adDetails: AdDetails)
func onAdLoadFailed(errorCode: Int, message: String)
}
Rewarded Ads
Rewarded ads are video ads that reward the user for watching the entire ad. They are typically used to incentivize users to complete a task or engage with the app.
Same flow as loadInterstitial, but the SDK invokes onAdFinished only after the user has fully viewed the ad. Grant your reward inside this callback.
import UIKit
import AppalooSDK
final class GameViewController: UIViewController, RewardedCallbacks {
private let appaloo = AppalooClient(adId: "{adID}")
private func grantBonusLife() {
appaloo.loadRewarded(from: self, callbacks: self)
}
func onAdLoaded(adDetails: AdDetails) {
// Ad is on screen; do not credit yet.
}
func onAdFinished(adDetails: AdDetails) {
// User finished watching: credit the reward here.
player.lives += 1
}
func onAdLoadFailed(errorCode: Int, message: String) {
print("Reward unavailable (\(errorCode))")
}
}
RewardedCallbacks
public protocol RewardedCallbacks: AnyObject {
func onAdLoaded(adDetails: AdDetails)
func onAdFinished(adDetails: AdDetails)
func onAdLoadFailed(errorCode: Int, message: String)
}
Important: only credit the reward inside onAdFinished. onAdLoaded fires as soon as the ad is rendered, before the user has watched it.
Inline Ads
Inline ads are small ads that embed in your own layout. They may be used within a news feed, directory, photo reel, and more.
import UIKit
import AppalooSDK
final class FeedViewController: UIViewController {
private let appaloo = AppalooClient(adId: "{adID}")
private func addInlineAd(to stack: UIStackView) {
// Returns a 100%-wide, ~275pt-tall card that fills itself in once an ad is
// served (and collapses if none is available). Tapping it expands the ad.
let adView = appaloo.loadInline()
stack.addArrangedSubview(adView)
}
}
In SwiftUI, wrap it in a UIViewRepresentable:
import SwiftUI
import AppalooSDK
// Wrap the inline view for SwiftUI.
struct AppalooInlineAd: UIViewRepresentable {
let client: AppalooClient
func makeUIView(context: Context) -> AppalooInlineAdView { client.loadInline() }
func updateUIView(_ view: AppalooInlineAdView, context: Context) {}
}
struct FeedView: View {
let appaloo = AppalooClient(adId: "{adID}")
var body: some View {
List {
Text("A post")
AppalooInlineAd(client: appaloo).frame(height: 275)
Text("Another post")
}
}
}
Banner Ads
Banner ads are a full-width, compact anchored strip. loadBanner returns an AppalooBannerAdView you add wherever you want it, but would typically be anchored to the bottom of the screen. It fills itself in when an ad is served and collapses to zero height if none is available.
import UIKit
import AppalooSDK
final class MainViewController: UIViewController, BannerCallbacks {
private let appaloo = AppalooClient(adId: "{adID}")
private func addBanner(to container: UIView) {
let adView = appaloo.loadBanner(callbacks: self)
adView.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(adView)
NSLayoutConstraint.activate([
adView.leadingAnchor.constraint(equalTo: container.leadingAnchor),
adView.trailingAnchor.constraint(equalTo: container.trailingAnchor),
adView.bottomAnchor.constraint(equalTo: container.safeAreaLayoutGuide.bottomAnchor),
])
}
func onAdLoaded(adDetails: AdDetails) {
print("Banner for \(adDetails.appName)")
}
func onAdLoadFailed(errorCode: Int, message: String) {
print("Banner failed: \(errorCode) - \(message)")
}
}
In SwiftUI, wrap it in a UIViewRepresentable:
import SwiftUI
import AppalooSDK
// Wrap the banner view for SwiftUI.
struct AppalooBannerAd: UIViewRepresentable {
let client: AppalooClient
func makeUIView(context: Context) -> AppalooBannerAdView { client.loadBanner() }
func updateUIView(_ view: AppalooBannerAdView, context: Context) {}
}
struct ContentView: View {
let appaloo = AppalooClient(adId: "{adID}")
var body: some View {
VStack {
Text("My app content")
Spacer()
AppalooBannerAd(client: appaloo).frame(height: 64)
}
}
}
App Open Ads
App Open ads are brief full-screen ads suitable for app launch or return-to-foreground events.
import UIKit
import AppalooSDK
final class AppCoordinator: InterstitialCallbacks {
private let appaloo = AppalooClient(adId: "{adID}")
func showAppOpenAd(from presenter: UIViewController) {
appaloo.loadAppOpen(from: presenter, callbacks: self)
}
func onAdLoaded(adDetails: AdDetails) {
print("App Open ad for \(adDetails.appName)")
}
func onAdLoadFailed(errorCode: Int, message: String) {
print("App Open failed: \(errorCode) - \(message)")
}
}
Data Safety
The SDK collects no IDFA and no device identifiers. The only data it reports is which ads a user views or clicks, and because it carries no cross-app identifier it does not require an App Tracking Transparency prompt.
App Privacy nutrition label
Declare Advertising Data under Data Not Linked to You, marked Not Used for Tracking. That is the full extent of what the SDK reports.
Français
Español
Deutsch