Reusable iOS 16+ Swift Package for AdMob-based ads, designed for reuse across multiple apps.
- Banner ads
- Interstitial ads
- Splash interstitial ads
- Rewarded ads
- App open ads
- Native ads with multiple built-in styles
- Native preload/cache support
- Fallback placements
- Runtime-updatable config
- Pluggable event sink API
- SwiftInjected integration
- Add
AdsKitto your app with Swift Package Manager. AdsKitresolves Google Mobile Ads SDK and SwiftInjected automatically.- In the host app, add
GADApplicationIdentifierand the requiredSKAdNetworkItemstoInfo.plist. - Call
startGoogleMobileAds()once during startup. - Build your
AdsConfiguration, then inject runtime state throughAdsRuntimeContext.
Google quick start: https://developers.google.com/ad-manager/mobile-ads-sdk/ios/quick-start
AdsKit does not bundle mediation adapters. If your host app uses mediation, install and maintain those adapters in the host app.
- Set
GADApplicationIdentifierinInfo.plist. - Add Google
SKAdNetworkItemsentries required by your ad stack. - Call
startGoogleMobileAds()once during app startup. - Pass a valid
topViewControllerProviderintoAdsRuntimeContextso fullscreen formats can present correctly. - Wire
AdsEventSinkinto your analytics layer if you need Firebase, Meta, Adjust, or custom event forwarding. - Keep mediation adapters in the host app. AdsKit only wraps the core Google Mobile Ads SDK.
import AdsKit
let configuration = AdsConfiguration(
slots: [
AdsSlot(
key: "splash_inter",
format: .splashInterstitial,
primaryPlacement: .init(id: "ca-app-pub-3940256099942544/1033173712", isEnabled: true)
),
AdsSlot(
key: "language_native",
format: .native,
primaryPlacement: .init(id: "ca-app-pub-3940256099942544/2247696110", isEnabled: true),
fallbackPlacement: .init(id: "ca-app-pub-3940256099942544/2247696110", isEnabled: true)
),
AdsSlot(
key: "home_banner",
format: .banner,
primaryPlacement: .init(id: "ca-app-pub-3940256099942544/2934735716", isEnabled: true)
)
],
preload: .init(
interstitialKeys: ["splash_inter"],
manual: .init(nativeKeys: ["language_native"])
)
)
let adsManager = AdsKitManager(
configuration: configuration,
runtimeContext: AdsRuntimeContext(
isAdsEnabled: true,
isPremiumUser: false,
isFirstAppOpen: true
),
eventSink: ClosureAdsEventSink { event in
print("[AdsKit event]", event.kind.rawValue, event.slotKey ?? "-")
}
)
adsManager.startGoogleMobileAds()
adsManager.preloadConfiguredSlots()Call manual preloads right before the screen that needs them:
adsManager.preloadManualSlots()
// or target one native slot directly
adsManager.preloadNative(slotKey: "language_native")struct HomeView: View {
@StateObject private var adsManager = makeAdsManager()
var body: some View {
VStack(spacing: 16) {
BannerAdsView(
slotKey: "home_banner",
manager: adsManager
)
NativeAdsView(
slotKey: "language_native",
manager: adsManager,
style: .large()
)
}
}
}final class HomeViewController: UIViewController {
private lazy var adsManager = AdsKitManager(
configuration: makeAdsConfiguration(),
runtimeContext: AdsRuntimeContext(
isAdsEnabled: true,
isPremiumUser: false,
isFirstAppOpen: false,
topViewControllerProvider: { [weak self] in self }
)
)
override func viewDidLoad() {
super.viewDidLoad()
adsManager.startGoogleMobileAds()
adsManager.loadInterstitial(slotKey: "share_inter")
}
@IBAction private func didTapShare() {
adsManager.showInterstitial(slotKey: "share_inter")
}
}For banner/native content on UIKit screens, embed BannerAdsView or NativeAdsView with UIHostingController, or bind NativeAdViewModel into your own UIView container if you need a custom layout.
Use AdsEventSink to forward ad events into Firebase, Meta, Adjust, your own analytics, or logging.
final class AnalyticsSink: AdsEventSink {
func record(_ event: AdsEvent) {
// Map to your analytics pipeline here.
}
}AdsKit includes a Dependency.adsKitManager(...) helper for SwiftInjected. Files that use Dependencies, @Injected, or @InjectedObservable should import both AdsKit and SwiftInjected.
import AdsKit
import SwiftInjected
@MainActor
func setupDependencies() {
let dependencies = Dependencies {
Dependency.adsKitManager(
configuration: makeAdsConfiguration(),
runtimeContext: AdsRuntimeContext(
isAdsEnabled: true,
isPremiumUser: false,
isFirstAppOpen: false
),
eventSink: ClosureAdsEventSink { event in
print("[AdsKit]", event.kind.rawValue, event.slotKey ?? "-")
},
bootstrap: { manager in
manager.startGoogleMobileAds()
manager.preloadConfiguredSlots()
}
)
}
dependencies.build()
}
struct HomeView: View {
@InjectedObservable var adsManager: AdsKitManager
var body: some View {
BannerAdsView(slotKey: "home_banner", manager: adsManager)
}
}An iOS sample app is included at Example/AdsExample. It uses Google test ad-unit IDs and demonstrates banner, native, interstitial, rewarded, and app open flows with the package directly.