본문으로 건너뛰기

네이티브 광고

네이티브 형태 소개

native ad example
  • 광고 뷰를 미디에이션 SDK가 구현해주는 타 광고 형태와 달리 네이티브 광고 형태는 구성 요소들을 전달받아 앱에서 직접 광고 뷰를 구현합니다.
  • UI/UX 기반으로 레이아웃을 직접 구현하므로써 위화감을 적게 만들 수 있다는 것이 가장 큰 특징입니다. 단, 유저가 광고가 아닌 컨텐츠로써 착각하는 경우를 방지하기 위해 광고 표시와 함께 최소한의 차별성은 부여해야합니다.

광고 단위 설정

대시보드에서 발급받은 ad unit ID를 사용하여 광고 단위를 설정하세요.

extension DaroNativeAdUnit {
static let native = DaroNativeAdUnit(
id: "...",
name: "...",
refreshTimeInterval: 10
)
}

구현

  1. DaroNativeAdContentView 를 상속하는 뷰를 구현합니다. 원하는 뷰의 구조에 따라 특정 뷰들은 사용하지 않아도 됩니다.
  • 예를들어 starRatingLabel 이나, storeLabel 등은 네이티브 광고 템플릿에 따라 사용하지 않아도 됩니다.
DaroNativeAdContentView 샘플 코드

final class DaroExampleNativeAdContentView: DaroNativeAdContentView {

var containerView = UIView()

/// IconView
var iconImageView: UIImageView = {
let view = UIImageView()
view.contentMode = .scaleAspectFill
view.layer.cornerRadius = 4
view.clipsToBounds = true
view.isHidden = true
return view
}()

/// Headline
var headlineLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 15, weight: .bold)
label.textColor = UIColor.white
label.numberOfLines = 2
return label
}()

/// Advertiser View
var advertiserLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 12, weight: .regular)
label.numberOfLines = 2
label.textColor = UIColor.white
return label
}()

/// Star Rating
var starRatingLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 12, weight: .regular)
label.numberOfLines = 2
label.textColor = UIColor.white
return label
}()

/// Media View
var mediaView = DaroMediaView()

/// Call to Action
var callToActionButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.isUserInteractionEnabled = false
button.clipsToBounds = true
button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
button.setTitleColor(.label, for: .normal)
button.backgroundColor = UIColor.systemGray3
button.layer.cornerRadius = 4
return button
}()

/// Body
var bodyLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 15, weight: .regular)
label.numberOfLines = 2
label.textColor = UIColor.white
return label
}()

/// Store View
var storeLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 12, weight: .regular)
label.numberOfLines = 2
label.textColor = UIColor.white
return label
}()

/// Price View
var priceLabel: UILabel = {
let label = UILabel()
label.isUserInteractionEnabled = false
label.clipsToBounds = true
label.font = .systemFont(ofSize: 12, weight: .regular)
label.numberOfLines = 2
label.textColor = UIColor.white
return label
}()

required init() {
super.init()
layout()

bindViews(
headlineLabel: headlineLabel,
callToActionButton: callToActionButton,
iconImageView: iconImageView,
bodyLabel: bodyLabel,
storeLabel: storeLabel,
priceLabel: priceLabel,
starRating: starRatingLabel,
advertiserLabel: advertiserLabel,
mediaView: mediaView
)

activateLayout()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func layout() {
translatesAutoresizingMaskIntoConstraints = false
let blurEffect = UIBlurEffect(style: .systemMaterialDark)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.translatesAutoresizingMaskIntoConstraints = false
blurView.isUserInteractionEnabled = false
containerView.addSubview(blurView)
blurView.anchorToSuperview()
containerView.clipsToBounds = true
containerView.isUserInteractionEnabled = false

addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.anchorToSuperview()

[
mediaView,
iconImageView,
headlineLabel,
advertiserLabel,
starRatingLabel,
bodyLabel,
storeLabel,
priceLabel,
callToActionButton,
]
.forEach {
$0.removeFromSuperview()
containerView.addSubview($0)
$0.translatesAutoresizingMaskIntoConstraints = false
}

activateLayout()
}

func activateLayout() {
NSLayoutConstraint.activate([
iconImageView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 10),
iconImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 10),
iconImageView.heightAnchor.constraint(equalToConstant: 70),
iconImageView.widthAnchor.constraint(equalToConstant: 70),

headlineLabel.topAnchor.constraint(equalTo: iconImageView.topAnchor),
headlineLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 10),
headlineLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: -10),

starRatingLabel.topAnchor.constraint(equalTo: headlineLabel.bottomAnchor, constant: 8),
starRatingLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 10),

advertiserLabel.bottomAnchor.constraint(equalTo: iconImageView.bottomAnchor),
advertiserLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 10),

bodyLabel.topAnchor.constraint(equalTo: iconImageView.bottomAnchor, constant: 10),
bodyLabel.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 10),
bodyLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: -10),

priceLabel.centerYAnchor.constraint(equalTo: storeLabel.centerYAnchor),
priceLabel.rightAnchor.constraint(equalTo: storeLabel.leftAnchor, constant: -10),

callToActionButton.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -10),
callToActionButton.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 20),
callToActionButton.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: -20),

storeLabel.bottomAnchor.constraint(equalTo: callToActionButton.topAnchor, constant: -10),
storeLabel.rightAnchor.constraint(equalTo: callToActionButton.rightAnchor),

mediaView.heightAnchor.constraint(equalTo: containerView.heightAnchor),
mediaView.widthAnchor.constraint(equalTo: containerView.widthAnchor),
mediaView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
mediaView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
])
}
}

  1. DaroNativeAdView 를 초기화 할때 DaroNativeAdContentView 를 전달합니다.
DaroNativeAdView 샘플 코드
public final class DaroExampleNativeAdView: UIView {

var nativeAdView: DaroNativeAdView

public init(adUnit: DaroNativeAdUnit) {
nativeAdView = DaroNativeAdView(
adUnit: adUnit,
nativeAdContentViewType: DaroLargeNativeAdContentView.self
)
super.init(frame: .zero)
layout()
nativeAdView.delegate = self
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError()
}

public func loadAd() {
nativeAdView.loadAd()
}

private func layout() {
translatesAutoresizingMaskIntoConstraints = false
nativeAdView.removeFromSuperview()
addSubview(nativeAdView)
nativeAdView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
nativeAdView.leftAnchor.constraint(equalTo: leftAnchor),
nativeAdView.rightAnchor.constraint(equalTo: rightAnchor),
nativeAdView.topAnchor.constraint(equalTo: topAnchor),
nativeAdView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}
}


extension DaroExampleNativeAdView: DaroNativeAdDelegate {
public func nativeAdDidRecordClick(_ nativeAd: DaroNativeAd) { }
public func nativeAdDidRecordImpression(_ nativeAd: DaroNativeAd) { }
public func nativeAdDidRecordSwipeGestureClick(_ nativeAd: DaroNativeAd) { }
public func nativeAdDidDismissScreen(_ nativeAd: DaroNativeAd) { }
public func nativeAdWillDismissScreen(_ nativeAd: DaroNativeAd) { }
public func nativeAdWillPresentScreen(_ nativeAd: DaroNativeAd) { }
public func nativeAdWillPresentScreen(_ nativeAd: DaroNativeAd) { }
}

네이티브 광고 템플릿

  • 두 가지 템플릿을 제공합니다.

Large 타입

  • 모든 하위 뷰가 다 들어간 크기의 네이티브 광고 입니다.
let largeNativeAdView = DaroLargeNativeAdView(adUnit: adUnit)
largeNativeAdView.loadAd()
  • 샘플 이미지
native ad example

Text 타입

  • GNB 하단 등 텍스트 형태만 보여줄 때 사용할 수 있습니다.
let lineNativeAdView = DaroLineNativeAdView(adUnit: adUnit)
lineNativeAdView.loadAd()
  • 샘플 이미지
native ad example