Wrapping library around AppLovin and Sourcepoint SDK to simplify the integration of consents and ads and not waste time debugging
For any questions regarding the integration, slack @Loic Saillant, Sarra Srairi or Gautier Gédoux
- Run
pod repo update
thenpod install
in your terminal - Ad the ad-review file at the root of the project and run
ruby AppLovinQualityServiceSetup-ios.rb
in your terminal - Set any developper team in the build setting
- Run the app
- copy/paste the Podfile or the element in it at the root of your app folder and change the Target name inside it by your app name
- Add the Common, Ads and Privacy folder to your project
- Run
pod repo update
thenpod install
in your terminal - Update the
Config.swift
file with the proper credential present in this file
Note: If you want to make things faster for this part you can just:
- Copy/paste the info.plist file of the sample app into your app
- Override the
GADApplicationIdentifier
key with the credential from this doc - Ad the ad-review file at the root of the project and run
ruby AppLovinQualityServiceSetup-ios.rb
in your terminal - And everything should work magically
Here is the complete and standard installation
- Add SDK dependencies (see Installation section above)
- Add the dependency for each network in your app
- Check this doc for each network
- To see if you need additional steps see this
- You will Generate all required SKAdNetwork keys for your info.plist file
here
- Bigo requires extra parameters when fetching an ad, see this
AppHarbr
is an ad moderation provider. It is compatible with all major ad networks but it's mandatory to follow this documentation to ensure you have compatible versions for your adapters.- Note: by calling
ALSdk.shared().showMediationDebugger()
you can launch the mediation debugger and check that every integration is working properly (and enable test mode to test a specific network)
- Configure the ad review plugin by following the steps here
To display the ad properly in your app see the next section
Ask for consent in you AppDelegate.swift
file in the didFinishLaunchingWithOptions
method
PrivacyManager.shared.configure { analyticsEnabled, adsEnabled, doNotSellEnabled in
if analyticsEnabled {
//TODO: configure analytics
} else {
//TODO: stop analytics
}
if adsEnabled {
AdInitializer.launchAdsSDK(
hasUserConsent: PrivacyManager.shared.hasUserConsent,
doNotSell: doNotSellEnabled,
isAgeRestrictedUser: PrivacyManager.shared.isAgeRestrictedUser
)
} else {
AdInitializer.resetAdsSDK()
}
}
You will also need to ad a CTA in the settings view to display consent and allowing him to opt out
PrivacyManager.shared.loadAndDisplayConsentUI()
Please make sure the CTA is visible only when necessary by calling the following method
PrivacyManager.shared.canShowPrivacyPopup()
Once the Ads are properly initialized (you should see a lot of stuff in the logs) you can start the implementation in the feed
- The main class to display and load ads is called the
AdCoordinator
it's should be the only class your app will interract with - The
AdCoordinator
"dataSource" is composed of indexes, it gives you an index were you should display an ad and not an ad directly because ads can change at any time - Once you're ready to diplay an ad it give you a
UIView
containing the methodAdCoordinator.shared.getAdView(for: index)
- Everytime the feed get a full refresh, you should call
AdCoordinator.shared.reload()
- The
AdCoordinator
can handle low amount of post in the feed by adding a callback at the feed initiation
AdCoordinator.shared.firstAdLoadedCallback = {
guard AdCoordinator.shared.shouldDisplayFooterAd(forDataSize: [YOUR DATA SIZE]) else { return }
//RELOAD THE FEED
}
- In order for the
AdCoordinator
to load and index ads dynamically you should call it on every cell display, see the following example:
func didDisplay(item: FeedItem) {
Task {
guard let index = feedItems.firstIndex(where: { $0.id == item.id }) else { return }
let adIndex = min(index + AdConfig.fetchOffset, feedItems.count) //We need to add an offset in order to not disturb the view generation
let surroundingIds = [feedItems[safe: adIndex-1], feedItems[safe: adIndex+1]].compactMap { $0?.id } //this is used for Google Ad Mob integration
guard AdCoordinator.shared.isAdAvailable(for: adIndex, surroundingIds: surroundingIds) else { return }
//RELOAD YOUR DATA
}
}
- When loading your data source, you should Use the
AdCoordinator
to insert "Ad items" in the data source
private func handleLoad() {
feedItems = prefilledItems
AdCoordinator.shared.allAdIndexes.forEach { index in
guard index < feedItems.count else { return }
self.feedItems.insert(FeedItem(id: "ad-\(index)", content: FeedItemContent.adIndex(index)), at: index)
}
}
- Finally in order to display a view you should make a UIViewRepresentable class and call the
AdCoordinator
getAdView
methods
struct AdView: UIViewRepresentable {
let adIndex: Int
func makeUIView(context: Context) -> UIView {
return AdCoordinator.shared.getAdView(for: adIndex)
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
- Bonus: you can add analytics automaticaly by adding amplitude directly in the
AdAnalytics.swift
file
func send(params: [String: Any]) {
//TODO: amplitude.track(eventType: rawValue ,eventProperties: params)
print("📊 \(rawValue), adUnit \(params["adUnitIdentifier"] ?? "unknown")")
}
- To test a specific network:
- you might need to change your location with a VPN
- some free VPN won't work, NordVPN seems to work
- the location will depend of the network (some networks only serve in a few countries)
- If loading ads starts to get slow or you get a lot of no-fill, try to reset your advertising ID