How to add Google AdMob ad banner to SwiftUI with Apple Tracking Transparency (ATT) framework
Apps > ADD APP
Ad units > Add ad unit > Banner
App ID: ca-app-pub-1111222233334444~1234567890
Ad unit ID: ca-app-pub-1111222233334444/9876543210
XCode
XCode > File > Add Package Dependencies
Add Package: swift-package-manager-google-mobile-ads
(Google Mobile Ads SDK)
You should be able to see the added packages in:
Navigator under "Package Dependencies" e.g.
> 📦 GoogleMobileAds 11.8.0
> 📦 GoogleUserMessagingPlatform 2.5.0
If you can't see "Package Dependenceis" in the Navigator, try restarting the XCode
Project -> Targets -> General tap -> "Frameworks, Libraries, and Embedded Content"
🏛️ GoogleMobileAds
Add below to the Info.plist
Add Key: "GADApplicationIdentifier"
Value: "ca-app-pub-1111222233334444~1234567890"
How to add to the Info.plist
:
Select project in the Navigation -> Targets > Info > Custom macOS Application Target Properties: Hover over pre-existing Keys and click (+) -> fill in the Key and Value pair.
This will create Info
on the Navigator if not already exists. This can be seen as Info.plist
in the Finder.
If Info exists on the Navigator: right click -> Open As -> Source Code; add to the XML file.
< dict >
< key >GADApplicationIdentifier</ key >
< string >ca-app-pub-1639129328565259~1986806680</ string >
...
</ dict >
Swift files
File contents to be updated as my code evolves
MainApp.swift
Get the testDeviceIdentifiers
from the warnings: XCode -> Debug Area -> Console.
// MainApp.swift
import SwiftUI
import GoogleMobileAds
@main
struct MainApp : App {
@UIApplicationDelegateAdaptor (AppDelegate. self ) var appDelegate
private let testDeviceIdentifiers = [ "..." ]
init () {
GADMobileAds. sharedInstance (). start ( completionHandler : nil )
GADMobileAds. sharedInstance ().requestConfiguration.testDeviceIdentifiers = self .testDeviceIdentifiers
}
var body: some Scene {
WindowGroup {
ContentView ()
}
}
}
AdBannerView.swift
// AdBannerView.swift
import SwiftUI
import GoogleMobileAds
import AppTrackingTransparency
let AD_UNIT_ID = "ca-app-pub-1111222233334444/9876543210"
struct AdBannerViewWrapper : View {
@Environment (\.scenePhase) private var scenePhase
@State private var shouldReload = false
@State private var adHeight: CGFloat = 50
var body: some View {
VStack ( spacing : 0 ) {
Rectangle ()
. fill (.gray. opacity ( 0.1 ))
. frame ( height : 8 )
AdBannerView ( shouldReload : $shouldReload)
. frame ( height : adHeight)
. background (.gray. opacity ( 0.1 ))
}
. onAppear {
Task {
if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
await ATTrackingManager. requestTrackingAuthorization ()
}
}
adHeight = GADPortraitAnchoredAdaptiveBannerAdSizeWithWidth (UIScreen.main.bounds.width). size .height
}
. onChange ( of : scenePhase) {
if scenePhase == .active {
DispatchQueue.main. async {
shouldReload = true
}
}
}
}
}
struct AdBannerView : UIViewRepresentable {
@Binding var shouldReload: Bool
@State private var isTrackingAuthorized = false
func makeUIView ( context : Context) -> GADBannerView {
let adSize = GADPortraitAnchoredAdaptiveBannerAdSizeWithWidth (UIScreen.main.bounds.width)
let bannerView = GADBannerView ( adSize : adSize)
bannerView.adUnitID = AD_UNIT_ID
bannerView.rootViewController = getRootViewController ()
return bannerView
}
func updateUIView ( _ uiView: GADBannerView, context : Context) {
if shouldReload {
Task {
if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
let status = await ATTrackingManager. requestTrackingAuthorization ()
DispatchQueue.main. async {
isTrackingAuthorized = status == .authorized
loadAd ( bannerView : uiView)
shouldReload = false
}
} else {
DispatchQueue.main. async {
isTrackingAuthorized = ATTrackingManager.trackingAuthorizationStatus == .authorized
loadAd ( bannerView : uiView)
shouldReload = false
}
}
}
}
}
private func loadAd ( bannerView : GADBannerView) {
let request = GADRequest ()
if ! isTrackingAuthorized {
let extras = GADExtras ()
extras.additionalParameters = [ "npa" : "1" ]
request. register (extras)
}
bannerView. load (request)
}
private func getRootViewController () -> UIViewController ? {
guard let windowScene = UIApplication.shared.connectedScenes
. first ( where : { $0 .activationState == .foregroundActive}) as? UIWindowScene else {
return nil
}
return windowScene.windows. first ? .rootViewController
}
}
Use in view
AdBannerViewWrapper ()
Make sure Test mode
is displayed in the ad banner. If not (e.g. first time, new install), grab a new testDeviceIdentifiers
.
XCode Console:
<Google> To get test ads on this device, set:
Objective-C
GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"1234" ];
Swift
GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ "1234" ]
Info.plist
XCode Console:
<Google> <Google:HTML> 1 required SKAdNetwork identifier(s) missing from Info.plist. Missing network(s): Verve. See [Enable SKAdNetwork to track conversions] (https://googlemobileadssdk.page.link/enable-skadnetwork).
Add following (copied from the link) to the info.plist
<key>SKAdNetworkItems</key>
<array>
...
</array>
ATT message
<key>NSUserTrackingUsageDescription</key>
<string>This allows us to provide you with a better ads experience.</string>