Banner
Banner ads are classic static banners, usually located at the bottom or top of the screen. Appodeal supports traditional 320x50 banners, 728x90 tablet banners and smart banners that adjust to the size and orientation of the device.
You can use our demo app as a reference project.
Demo App
Fixed Positioned Banner
Display Banner At The Bottom Of The Screen
Banner is a singleton now, if you are using bannerTop
or bannerBottom
on different controllers, the SDK will use the same banner instance.
Banner ads are refreshed every 15 seconds automatically by default. To display a banner, you need to call the following code:
- Swift
- Objective-C
Appodeal.showAd(.bannerBottom, rootViewController: self)
[Appodeal showAd:AppodealShowStyleBannerBottom rootViewController:self];
Display Banner At The Top Of The Screen
- Swift
- Objective-C
Appodeal.showAd(.bannerTop, rootViewController: self)
[Appodeal showAd:AppodealShowStyleBannerTop rootViewController:self];
Display Banner At The Left Or Right Corner Of The Screen
If your app uses landscape interface orientation you can show Appodeal Banner at the left or right corner. The banner will have the offset according to the safe area layout guide.
Disable banner smart sizing if you use AppodealShowStyleBannerLeft or AppodealShowStyleBannerRight
- Swift
- Objective-C
// Overrides default rotation angles
// Appodeal.setBannerLeftRotationAngleDegrees(90, rightRotationAngleDegrees: 180)
Appodeal.showAd(.bannerLeft, forPlacement: placement, rootViewController: self)
// Appodeal.showAd(.bannerRight, forPlacement: placement, rootViewController: self)
// Overrides default rotation angles
// [Appodeal setBannerLeftRotationAngleDegrees:90 rightRotationAngleDegrees:180];
[Appodeal showAd: AppodealShowStyleBannerLeft forPlacement: placement rootViewController: self];
// [Appodeal showAd: AppodealShowStyleBannerRight forPlacement: placement rootViewController: self];
Checking If Ad Is Loaded
You can check if the ad has been loaded before showing it. This method returns a boolean value indicating whether or not the banner has been loaded.
- Swift
- Objective-C
Appodeal.isReadyForShow(with: .bannerTop)
[Appodeal isReadyForShowWithStyle: AppodealShowStyleBannerTop];
We recommend you to check ad caching before trying to show it.
Callbacks
Callbacks are used to track different lifecycle events of an ad, e.g., when a banner has successfully loaded or is about to appear. To get them, you need to set the delegate as follows:
- Swift
- Objective-C
//set delegate
Appodeal.setBannerDelegate(self)
//set delegate
[Appodeal setBannerDelegate:self];
Usually, the class that implements banners is also the delegate class.
That's why the delegate property can be set to self
.
Now you can use the following callback methods:
- Swift
- Objective-C
// banner was loaded (precache flag shows if the loaded ad is precache)
func bannerDidLoadAdIsPrecache(_ precache: Bool) {}
// banner was shown
func bannerDidShow() {}
// banner failed to load
func bannerDidFailToLoadAd() {}
// banner was clicked
func bannerDidClick() {}
// banner did expire and could not be shown
func bannerDidExpired() {}
// banner was loaded (precache flag shows if the loaded ad is precache)
- (void)bannerDidLoadAdIsPrecache:(BOOL)precache {}
// banner was shown
- (void)bannerDidShow {}
// banner failed to load
- (void)bannerDidFailToLoadAd {}
// banner was clicked
- (void)bannerDidClick {}
// banner did expire and could not be shown
- (void)bannerDidExpired {}
All callbacks are called on the main thread.
If automatic caching is ON for the Banner ad type, do not show the
banner in the bannerDidLoadAdIsPrecache
callback. The banner will be
refreshed automatically after the first show.
Hide
To remove the banner from your view hierarchy:
- Swift
- Objective-C
Appodeal.hideBanner()
[Appodeal hideBanner];
Custom Positioned Banner
Display Banner In Programmatically Created View
You can also add the Appodeal banner to your view hierarchy manually.
For example:
- Swift
- Objective-C
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let banner = Appodeal.banner() {
self.view.addSubview(banner)
banner.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 50)
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view addSubview:[Appodeal banner]];
[Appodeal banner].frame = CGRectMake(0, 0, self.view.bounds.size.width, 50);
}
Custom BannerView
must be on the top of the hierarchy and mustn't be
overlapped by other views.
Advanced
Placements
Appodeal SDK allows you to tag each impression with different placement. To be able to use placements, you need to create them in Appodeal Dashboard. Read more about placements.
- Swift
- Objective-C
Appodeal.showAd(.bannerTop, forPlacement: placement, rootViewController: self)
[Appodeal showAd:AppodealShowStyleBannerTop forPlacement:placement rootViewController:self];
If the loaded ad can't be shown in a specific placement, nothing will be shown. If auto caching is enabled, the SDK will start to cache another ad, which can affect display rate. To save the loaded ad for future use (for instance, for another placement) check if the ad can be shown before calling show method:
- Swift
- Objective-C
Appodeal.canShow(.bannerTop, forPlacement: placement)
[Appodeal canShow:AppodealAdTypeBannerTop forPlacement:placement];
You can configure your impression logic for each placement.
If you have no placements or call Appodeal.show with a placement that does not exist, the impression will be tagged with 'default' placement with corresponding settings applied.
Placement settings affect ONLY ad presentation, not loading or caching.
Check If Banner Is Initialized
- Swift
- Objective-C
Appodeal.isInitialized(for: .banner)
[Appodeal isInitalizedForAdType: AppodealAdTypeBanner];
Returns true
if banner was initialized.
Check If Autocache Is Enabled
- Swift
- Objective-C
Appodeal.isAutocacheEnabled(.banner)
[Appodeal isAutocacheEnabled: AppodealAdTypeBanner];
Returns true
if autocache is enabled for banner.
Advanced BannerView Integration
If basic integration is not appropriate for you due to the complex views
hierarchy of your app, you can use AppodealBannerView UIView
subclass
to integrate banners.
- Swift
- Objective-C
import UIKit
import Appodeal
class YourViewController : UIViewController, AppodealBannerViewDelegate {
override func viewDidLoad () {
super.viewDidLoad()
// required: init ad banner
var bannerView: AppodealBannerView!
bannerView.init(size: bannerSize, rootViewController: self);
// optional: set delegate
bannerView.setDelegate(self);
// required: add banner to superview and call -loadAd to start banner loading
self.view addSubview(bannerView);
bannerView.loadAd();
}
// optional: implement any of AppodealBannerViewDelegate methods
func bannerViewDidLoadAd(_ bannerView: APDBannerView, isPrecache precache: Bool) {
NSLog("bannerView was loaded")
}
func bannerView(_ bannerView: APDBannerView, didFailToLoadAdWithError error: Error) {
NSLog("bannerView failed to load");
}
func bannerViewDidInteract(_ bannerView: APDBannerView) {
NSLog("bannerView was clicked")
}
func bannerViewDidShow(_ bannerView: APDBannerView) {
NSLog("bannerView was shown")
}
func bannerViewExpired(_ bannerView: APDBannerView) {
NSLog("bannerView did expire and could not be shown")
}
}
#import "YourViewController.h"
#import <Appodeal/Appodeal.h>
@interface YourViewController () <AppodealBannerViewDelegate>
@end
@implementation YourViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// required: init ad banner
AppodealBannerView *bannerView = [[AppodealBannerView alloc] initWithSize:kAppodealUnitSize_320x50 rootViewController:self];
// optional: set delegate
bannerView.delegate = self;
// required: add banner to superview and call -loadAd to start banner loading
[self.view addSubview:bannerView];
[bannerView loadAd];
}
// optional: implement any of AppodealBannerViewDelegate methods
- (void)bannerViewDidLoadAd:(APDBannerView *)bannerView isPrecache:(BOOL)precache{
NSLog(@"Banner %@ did load!", bannerView);
}
- (void)bannerViewDidInteract:(APDBannerView *)bannerView {
NSLog(@"Banner %@ did interact", bannerView);
}
- (void)bannerView:(APDBannerView *)bannerView didFailToLoadAdWithError:(NSError *)error {
NSLog(@"Banner %@ did fail with error: %@", bannerView, error);
}
- (void)bannerViewDidShow:(APDBannerView *)bannerView {
NSLog(@"Banner %@ did show ad ", bannerView);
}
- (void)bannerViewExpired:(APDBannerView *)bannerView {
NSLog(@"Banner %@ expired", bannerView);
}
@end
To provide better user expirience we recommend to use single banner instance for all you screens where banner is shown.
There are several examples how to properly pass banner instance
between screens using UIStoryboardSegue
and
in-code navigation through UINavigationController
.
Storyboard based application example.
- Create auxiliary protocol that will layout banner view in View Controller's view. In this example we will layout at the bottom of screen.
import Foundation
import UIKit
import Appodeal
protocol BannerContainableController: UIViewController {
var bannerContainerView: UIView! { get }
}
extension BannerContainableController {
func layoutBannerView(_ bannerView: APDBannerView) {
bannerView.removeFromSuperview()
bannerView.rootViewController = self
bannerContainerView.addSubview(bannerView)
NSLayoutConstraint.activate([
bannerView.topAnchor.constraint(equalTo: bannerContainerView.topAnchor),
bannerView.bottomAnchor.constraint(equalTo: bannerContainerView.bottomAnchor),
bannerView.leftAnchor.constraint(equalTo: bannerContainerView.leftAnchor),
bannerView.rightAnchor.constraint(equalTo: bannerContainerView.rightAnchor),
])
}
}
This protocol will be used in both ParentViewController
and
ChildViewController
to layout banner view.
- Create new seque in storyboard with identifier:
ShowChildViewController
- Override
prepare(for segue:, sender:)
method inParentViewController
and pass banner instance toChildViewController
.
import UIKit
import Appodeal
class ParentViewController: UIViewController, BannerContainableController {
@IBOutlet weak var bannerContainerView: UIView!
private lazy var bannerView = APDBannerView(size: kAPDAdSize320x50)
override func viewDidLoad() {
super.viewDidLoad()
// Load banner and it to the view in hierarchy
bannerView.loadAd()
bannerView.translatesAutoresizingMaskIntoConstraints = false
layoutBannerView(bannerView)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard
segue.identifier == "ShowChildViewController",
let childViewController = segue.destination as? ChildViewController
else { return }
childViewController.onDismiss = { [weak self] in
guard let self else { return }
self.layoutBannerView(self.bannerView)
}
childViewController.bannerView = bannerView
}
}
- When user returns to
ParentViewController
we need to pass back banner view. To achieve this we will useonDismiss
callback.
import Foundation
import UIKit
import Appodeal
class ChildViewController: UIViewController, BannerContainableController {
@IBOutlet weak var bannerContainerView: UIView!
weak var bannerView: APDBannerView?
var onDismiss: (() -> ())?
override func viewDidLoad() {
super.viewDidLoad()
guard let bannerView = bannerView else { return }
layoutBannerView(bannerView)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
onDismiss?()
}
}
UINavigationController based application example.
-
Create auxiliary protocol that will layout banner view in View Controller's view. We will use the same implementation from the previous storyboard example.
-
In
ParentViewController
create new instance ofChildViewController
and pass banner instance to it.
import UIKit
import Appodeal
class ParentViewController: UIViewController, BannerContainableController {
private lazy var bannerView = APDBannerView(size: kAPDAdSize320x50)
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Root View Controller"
bannerView.translatesAutoresizingMaskIntoConstraints = false
bannerView.rootViewController = self
bannerView.loadAd()
layoutBannerView(bannerView)
setupNavigationButton()
}
func setupNavigationButton() {
var configuration = UIButton.Configuration.filled()
configuration.titlePadding = 16
configuration.imagePadding = 16
let button = UIButton(configuration: configuration)
button.setImage(UIImage(systemName: "chevron.right"), for: .normal)
button.setTitle("Go To The Next View Controller", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(navigateToChildrenViewController), for: .touchUpInside)
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.heightAnchor.constraint(equalToConstant: 44)
])
}
@objc func navigateToChildrenViewController() {
let destinationViewController = ChildViewController()
destinationViewController.layoutBannerView(bannerView)
destinationViewController.onDismiss = { [weak self] in
guard let self = self else { return }
self.layoutBannerView(self.bannerView)
}
navigationController?.pushViewController(destinationViewController, animated: true)
}
}
- In
ChildViewController
we will use the same approach to pass back banner view on dismiss using closure.
import UIKit
class ChildViewController: UIViewController, BannerContainableController {
var onDismiss: (() -> ())?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
onDismiss?()
}
}
BannerView in SwifUI based application
As for UIKit based application for SwiftUI we recommend to use single banner instance for all you screens where banner is shown.
To achieve this behaviour you need to implement several auxiliary classes.
- Create
APDBannerViewController
that will be using for banner view layout and controlling of a view lifecycle
import UIKit
import Appodeal
final class APDBannerViewController: UIViewController {
weak var bannerView: APDBannerView?
var onDismiss: (() -> ())?
override func viewDidLoad() {
super.viewDidLoad()
layoutBannerView()
}
deinit {
onDismiss?()
}
func layoutBannerView() {
guard let bannerView = bannerView else { return }
bannerView.removeFromSuperview()
bannerView.rootViewController = self
view.addSubview(bannerView)
NSLayoutConstraint.activate([
bannerView.topAnchor.constraint(equalTo: view.topAnchor),
bannerView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
bannerView.leftAnchor.constraint(equalTo: view.leftAnchor),
bannerView.rightAnchor.constraint(equalTo: view.rightAnchor),
])
}
}
- Create
BannerView
- a view that will implementUIViewControllerRepresentable
protocol and will be used in SwiftUI views hierarchy. Also we need to implement customCoordinator
(singleton in this case) that usesNSHashTable
to store to manageAPDBannerViewController
instances.
import SwiftUI
struct BannerView: UIViewControllerRepresentable {
typealias UIViewControllerType = APDBannerViewController
func makeUIViewController(context: Context) -> APDBannerViewController {
let controller = APDBannerViewController()
controller.bannerView = context.coordinator.bannerView
controller.onDismiss = context.coordinator.dismiss
context.coordinator.store(controller)
return controller
}
func updateUIViewController(
_ uiViewController: APDBannerViewController,
context: Context
) {}
func makeCoordinator() -> Coordinator {
return .shared
}
final class Coordinator {
static let shared = Coordinator()
private lazy var storage = NSHashTable<APDBannerViewController>(options: .weakMemory)
lazy var bannerView: APDBannerView = {
let bannerView = APDBannerView(size: kAPDAdSize320x50)
bannerView.translatesAutoresizingMaskIntoConstraints = false
bannerView.loadAd()
return bannerView
}()
func store(_ controller: APDBannerViewController) {
storage.add(controller)
}
func dismiss() {
let previousController = storage.allObjects.last
previousController?.bannerView = bannerView
previousController?.layoutBannerView()
}
}
}
- Now we can use
BannerView
in SwiftUI views hierarchy.
BannerView is requred to have frame with fixex height.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
BannerView()
.frame(height: 50)
.frame(maxWidth: .infinity)
.background(Color(uiColor: .secondarySystemFill))
Spacer()
NavigationLink(
destination: {
ChildView()
},
label: {
HStack {
Image(systemName: "chevron.right")
Text("Go To The Next View")
}
.foregroundColor(.white)
.padding()
.background(RoundedRectangle(cornerRadius: 8).fill(Color.blue))
}
)
}
.navigationTitle("Root View")
}
}
}
struct ChildView: View {
var body: some View {
NavigationStack {
VStack {
Spacer()
BannerView()
.frame(height: 50)
.frame(maxWidth: .infinity)
.background(Color(uiColor: .secondarySystemFill))
}
.navigationTitle("Child View")
}
}
}
Enable Smart Banners
Smart banners are banner ads which automatically fit the screen/container size. Using them helps to deal with increasing fragmentation of the screen sizes on different devices. To enable them, use the following method:
- Swift
- Objective-C
//for top/bottom banners allows banner view to resize automatically to fit device screen
Appodeal.setSmartBannersEnabled(true)
//for banner view allows banner view to resize automatically to fit device screen
bannerView.usesSmartSizing = true
//for top/bottom banners allows banner view to resize automatically to fit device screen
[Appodeal setSmartBannersEnabled:YES];
//for banner view allows banner view to resize automatically to fit device screen
bannerView.usesSmartSizing = YES;
Change Banner Background
This method allows to create a grey background for banner ads:
- Swift
- Objective-C
//for top/bottom banners
Appodeal.setBannerBackgroundVisible(true)
//for bannerView
bannerView.backgroundVisible = true
//for top/bottom banners
[Appodeal setBannerBackgroundVisible: YES];
//for bannerView
[bannerView setBannerBackgroundVisible: YES];
Enable Banner Refresh Animation
- Swift
- Objective-C
//for top/bottom banners
Appodeal.setBannerAnimationEnabled(true)
//for bannerView
bannerView.bannerAnimationEnabled = true
//for top/bottom banners
[Appodeal setBannerAnimationEnabled:YES];
//for bannerView
[bannerView setBannerAnimationEnabled:YES];
Get Predicted eCPM
This method returns the expected eCPM for the cached ad. The amount is calculated based on historical data for the current ad unit.
- Swift
- Objective-C
Appodeal.predictedEcpm(for: .banner)
[Appodeal predictedEcpmForAdType: AppodealAdTypeBanner];
Check Viewability
You can always check in logs if show was tracked and your ad is visible.
You will see the following log if show was tracked successfully.
[Appodeal *.*.*] [debug] [impression] Impression <APDImpression: 0x600002953b10> succesfully tracked