네이티브 광고
네이티브 형태 소개
- 광고 뷰를 미디에이션 SDK가 구현해주는 타 광고 형태와 달리 네이티브 광고 형태는 구성 요소들을 전달받아 앱에서 직접 광고 뷰를 구현합니다.
- UI/UX 기반으로 레이아웃을 직접 구현하므로써 위화감을 적게 만들 수 있다는 것이 가장 큰 특징입니다. 단, 유저가 광고가 아닌 컨텐츠로써 착각하는 경우를 방지하기 위해 광고 표시와 함께 최소한의 차별성은 부여해야합니다.
네이티브 광고 단위 설정
note
대시보드에서 발급받은 ad unit ID
를 사용하여 광고 단위를 설정하세요.
static let middleSize = DaroMAdViewUnit(
adUnitID: "...",
name: "...", // Optional
format: .native,
refreshTimeInterval: 10
)
네이티브 광고 구현
DaroMNativeAdContentView
을 상속하는 뷰를 구현 합니다. 아래는 샘플코드입니다.
DaroMNativeAdContentContainerView.swift
public final class DaroMNativeAdContentContainerView: DaroMNativeAdContentView {
// MARK: title
public override var titleLabel: UILabel? {
get { internalTitleLabel }
set { super.titleLabel = newValue }
}
var internalTitleLabel: UILabel = {
let label = UILabel()
label.text = ""
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .systemFont(ofSize: 14, weight: .bold)
label.tag = 1001
return label
}()
// MARK: - Advertiser
public override var advertiserLabel: UILabel? {
get { internalAdvertiserLabel }
set { super.advertiserLabel = newValue }
}
var internalAdvertiserLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .systemFont(ofSize: 10, weight: .medium)
label.tag = 1002
return label
}()
// MARK: - body
public override var bodyLabel: UILabel? {
get { internalBodyLabel }
set { super.bodyLabel = newValue }
}
var internalBodyLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.font = .systemFont(ofSize: 12, weight: .medium)
label.tag = 1003
return label
}()
// MARK: icon
public override var iconImageView: UIImageView? {
get { internalIconImageView }
set { super.iconImageView = newValue }
}
var internalIconImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.tag = 1004
return imageView
}()
// MARK: - options content view
public override var optionsContentView: UIView? {
get { internalOptionsContentView }
set { super.optionsContentView = newValue }
}
var internalOptionsContentView: UIView = {
let view = UIView()
view.tag = 1005
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// MARK: - media content view
public override var mediaContentView: UIView? {
get { internalMediaContentView }
set { super.mediaContentView = newValue }
}
var internalMediaContentView: UIView = {
let view = UIView()
view.tag = 1006
view.alpha = 0.1
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// MARK: - cta
public override var callToActionButton: UIButton? {
get { internalCallToActionButton }
set { super.callToActionButton = newValue }
}
var internalCallToActionButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.clipsToBounds = true
button.titleLabel?.font = .systemFont(ofSize: 12, weight: .bold)
button.setTitleColor(.label, for: .normal)
button.backgroundColor = UIColor.systemGray3
button.layer.cornerRadius = 4
button.tag = 1007
return button
}()
// MARK: - star rating content
public override var starRatingContentView: UIView? {
get { internalStarRatingContentView }
set { super.starRatingContentView = newValue }
}
var internalStarRatingContentView: UIView = {
let view = UIView()
view.tag = 1008
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// MARK: - initializers
required init() {
super.init()
layout()
let binder = DaroMNativeAdViewBinder.init { builder in
builder.titleLabelTag = 1001
builder.advertiserLabelTag = 1002
builder.bodyLabelTag = 1003
builder.iconImageViewTag = 1004
builder.optionsContentViewTag = 1005
builder.mediaContentViewTag = 1006
builder.callToActionButtonTag = 1007
builder.starRatingContentViewTag = 1008
}
self.bindViews(with: binder)
translatesAutoresizingMaskIntoConstraints = false
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func layout() {
internalMediaContentView.translatesAutoresizingMaskIntoConstraints = false
internalIconImageView.translatesAutoresizingMaskIntoConstraints = false
internalTitleLabel.translatesAutoresizingMaskIntoConstraints = false
internalAdvertiserLabel.translatesAutoresizingMaskIntoConstraints = false
internalBodyLabel.translatesAutoresizingMaskIntoConstraints = false
internalCallToActionButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(internalMediaContentView)
NSLayoutConstraint.activate([
internalMediaContentView.topAnchor.constraint(equalTo: self.topAnchor),
internalMediaContentView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
internalMediaContentView.leftAnchor.constraint(equalTo: self.leftAnchor),
internalMediaContentView.rightAnchor.constraint(equalTo: self.rightAnchor),
])
addSubview(internalIconImageView)
NSLayoutConstraint.activate([
internalIconImageView.topAnchor.constraint(equalTo: self.topAnchor),
internalIconImageView.leftAnchor.constraint(equalTo: self.leftAnchor),
internalIconImageView.widthAnchor.constraint(equalToConstant: 32),
internalIconImageView.heightAnchor.constraint(equalToConstant: 32),
])
addSubview(internalTitleLabel)
NSLayoutConstraint.activate([
internalTitleLabel.topAnchor.constraint(equalTo: self.topAnchor),
internalTitleLabel.leftAnchor.constraint(equalTo: internalIconImageView.rightAnchor, constant: 12),
internalTitleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -12),
])
addSubview(internalAdvertiserLabel)
NSLayoutConstraint.activate([
internalAdvertiserLabel.topAnchor.constraint(equalTo: internalTitleLabel.bottomAnchor),
internalAdvertiserLabel.leftAnchor.constraint(equalTo: internalIconImageView.rightAnchor, constant: 12),
internalAdvertiserLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -12),
])
addSubview(internalBodyLabel)
NSLayoutConstraint.activate([
internalBodyLabel.topAnchor.constraint(equalTo: internalIconImageView.bottomAnchor, constant: 12),
internalBodyLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 12),
internalBodyLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -12),
])
addSubview(internalCallToActionButton)
NSLayoutConstraint.activate([
internalCallToActionButton.topAnchor.constraint(greaterThanOrEqualTo: internalBodyLabel.bottomAnchor, constant: 10),
internalCallToActionButton.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20),
internalCallToActionButton.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -20),
internalCallToActionButton.bottomAnchor.constraint(equalTo: self.bottomAnchor),
internalCallToActionButton.centerXAnchor.constraint(equalTo: self.centerXAnchor),
])
}
}
광고를 보여줄 화면에서 네이티브 광고 뷰를 선언합니다.
var nativeAdView = DaroMNativeAdView(
nativeAdContentViewType: DaroMNativeAdContentContainerView.self,
adUnit: .middleSize
)
...
// 광고 레이아웃 설정
// 아래는 샘플 코드 입니다
addSubview(nativeAdView)
NSLayoutConstraint.activate([
nativeAdView.leftAnchor.constraint(equalTo: leftAnchor),
nativeAdView.rightAnchor.constraint(equalTo: rightAnchor),
nativeAdView.topAnchor.constraint(equalTo: topAnchor),
nativeAdView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
...
nativeAdView.delegate = self
nativeAdView.impressionDelegate = self
nativeAdView.loadAd()
...
extension ExampleVC: DaroMAdImpressionDelegate {
public func didRecordImpression(for ad: DaroMAd) { }
}
extension ExampleVC: DaroMNativeAdDelegate {
public func didLoadNativeAd(_ ad: DaroMAd) { }
public func didFailToLoadNativeAd(_ adUnitIdentifier: String, error: DaroMError) { }
public func didClickNativeAd(_ ad: DaroMAd) {
public func didExpireNativeAd(_ ad: DaroMAd) { }
}
네이티브 광고 라인 템플릿
템플릿 뷰 선언
// 높이는 36 ~ 40 정도로 잡으시면 됩니다
let lineNativeBannerView = DaroMAdLineNativeBannerView(adUnit: .middleSize)