Native ads를 사용하면 앱의 기존 디자인과 일관된 방식으로 앱을 수익화할 수 있습니다. AppLovin MAX SDK를 통해 광고의 개별 에셋에 액세스할 수 있습니다. 이 방식을 통해 앱의 디자인 및 느낌과 일관되도록 광고 레이아웃을 디자인할 수 있습니다. SDK는 자동으로 이미지를 캐싱하고 메트릭을 추적합니다. 개발자는 광고를 표시하는 방법, 시기 및 위치에 집중할 수 있습니다.
AppLovin은 템플릿 연동을 지원 중단했습니다. 템플릿을 통해 앱에 native ads를 연동하는 경우, 해당 광고는 부터 no-fill이 발생하기 시작합니다. AppLovin은 향후 SDK 릴리스에서 템플릿 연동에 대한 지원을 제거할 예정입니다.
커스텀 뷰가 있고 해당 뷰에 native ad 에셋을 수동으로 로드하려는 경우 이 API를 사용하십시오. 이 연동 방법은 크게 세 가지 단계로 구성됩니다.
수동 API를 사용하려면 Create New Ad Unit 화면에서 Manual을 선택하십시오.

커스텀 UI 컴포넌트를 MAX SDK에 바인딩할 수 있습니다. 그런 다음 해당 컴포넌트에 native ad 에셋을 렌더링할 수 있습니다. 아래 예시는 Layout Editor로 생성한 커스텀 뷰와 고유한 뷰 ID를 사용하여 이를 수행하는 방법을 보여줍니다. 프로그래밍 방식으로 뷰를 생성하는 경우에도 이 방법을 사용할 수 있습니다.
AppLovin의 정책을 준수하려면 광고에 개인정보 보호 정보 아이콘이 포함되어야 합니다.
이 아이콘은 중요한 개인정보 처리방침 고지로 연결됩니다.
MaxNativeAdViewBinder.Builder#setOptionsContentViewGroupId(…)를 통해 바인딩할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/icon_image_view"
… />
<LinearLayout
android:id="@+id/ad_options_view"
… />
<TextView
android:id="@+id/title_text_view"
… />
<FrameLayout
android:id="@+id/star_rating_view"
… />
<TextView
android:id="@+id/advertiser_textView"
… />
<TextView
android:id="@+id/body_text_view"
… />
<FrameLayout
android:id="@+id/media_view_container"
… />
<Button
android:id="@+id/cta_button"
… />
</androidx.constraintlayout.widget.ConstraintLayout>
다음으로, MaxNativeAdViewBinder 인스턴스를 사용하여 고유한 뷰 ID로 하위 뷰를 바인딩합니다.
AppLovin은 네트워크가 특정 에셋을 반환할 것을 보장하지 않습니다.
public class ExampleActivity
extends Activity
implements MaxAdRevenueListener
{
⋮
private MaxNativeAdView createNativeAdView()
{
MaxNativeAdViewBinder binder = new MaxNativeAdViewBinder.Builder( R.layout.native_custom_ad_view )
.setTitleTextViewId( R.id.title_text_view )
.setBodyTextViewId( R.id.body_text_view )
.setStarRatingContentViewGroupId( R.id.star_rating_view )
.setAdvertiserTextViewId( R.id.advertiser_textView )
.setIconImageViewId( R.id.icon_image_view )
.setMediaContentViewGroupId( R.id.media_view_container )
.setOptionsContentViewGroupId( R.id.options_view )
.setCallToActionButtonId( R.id.cta_button )
.build();
return new MaxNativeAdView( binder, this );
}
⋮
}
class ExampleActivity : Activity(), MaxAdRevenueListener
{
⋮
private fun createNativeAdView(): MaxNativeAdView
{
val binder: MaxNativeAdViewBinder =
MaxNativeAdViewBinder.Builder(R.layout.native_custom_ad_view)
.setTitleTextViewId(R.id.title_text_view)
.setBodyTextViewId(R.id.body_text_view)
.setStarRatingContentViewGroupId(R.id.star_rating_view )
.setAdvertiserTextViewId(R.id.advertiser_textView)
.setIconImageViewId(R.id.icon_image_view)
.setMediaContentViewGroupId(R.id.media_view_container)
.setOptionsContentViewGroupId(R.id.options_view)
.setCallToActionButtonId(R.id.cta_button)
.build()
return MaxNativeAdView(binder, this)
}
⋮
}
각 네트워크의 가이드를 따르고 필수 광고 에셋을 바인딩하십시오. 그렇지 않으면 네트워크에서 귀하의 impressions를 무효화할 수 있습니다.
사전 렌더링된 native ad를 로드하려면 먼저 Ad Unit ID에 해당하는 MaxNativeAdLoader를 인스턴스화합니다.
그런 다음 해당 loadAd(MaxNativeAdView) 메서드를 호출합니다.
MaxNativeAdLoadListener를 구현하고 설정하여 native ad의 로드 상태가 변경될 때 알림을 받도록 하십시오.
native ad를 로드하려면 먼저 Ad Unit ID에 해당하는 MaxNativeAdLoader를 인스턴스화합니다.
그런 다음 해당 loadAd() 메서드를 호출합니다.
MaxNativeAdLoadListener를 구현하고 설정하여 native ad의 로드 상태가 변경될 때 알림을 받도록 하십시오.
그런 다음 onNativeAdLoaded에서 반환된 MaxAd를 사용하여 광고 뷰를 렌더링합니다.
이는 MaxNativeAdLoader.render(MaxNativeAdView, MaxAd)를 호출하여 수행할 수 있습니다.
Native ads는 4시간의 광고 만료 기간 내에 노출되어야 합니다. 이 기간을 벗어나서 노출되는 광고와 관련된 impressions는 무효화됩니다.
native ad 사용을 중단하는 경우, destroy() 메서드를 호출하여 리소스를 해제하십시오.
그렇지 않으면 시간이 지남에 따라 앱 성능이 저하됩니다.
아래는 native ad를 로드하고 제거하는 방법의 예시입니다.
이는 이전 단계에서 UI 컴포넌트를 바인딩한 후에 수행됩니다.
public class ExampleActivity
extends Activity
implements MaxAdRevenueListener
{
private ViewGroup nativeAdContainerView;
private MaxNativeAdLoader nativeAdLoader;
private MaxAd loadedNativeAd;
⋮
private void createNativeAdLoader()
{
nativeAdLoader = new MaxNativeAdLoader( "«ad-unit-ID»", this );
nativeAdLoader.setRevenueListener( this );
nativeAdLoader.setNativeAdListener( new NativeAdListener() );
}
private void loadNativeAd()
{
nativeAdLoader.loadAd( createNativeAdView() );
}
@Override
public void onAdRevenuePaid(final MaxAd ad) { }
private class NativeAdListener
extends MaxNativeAdListener
{
@Override
public void onNativeAdLoaded(final MaxNativeAdView nativeAdView, final MaxAd nativeAd)
{
// 메모리 누수를 방지하기 위해 기존에 존재하는 native ad를 제거합니다.
if ( loadedNativeAd != null )
{
nativeAdLoader.destroy( loadedNativeAd );
}
// 정리를 위해 광고를 저장합니다.
loadedNativeAd = nativeAd;
nativeAdContainerView.removeAllViews();
nativeAdContainerView.addView( nativeAdView );
}
@Override
public void onNativeAdLoadFailed(final String adUnitId, final MaxError error)
{
// Native ad 로드 실패.
// AppLovin은 최대 지연 시간까지 지연 시간을 기하급수적으로 늘리며 재시도할 것을 권장합니다.
}
@Override
public void onNativeAdClicked(final MaxAd nativeAd) { }
@Override
public void onNativeAdExpired(final MaxAd nativeAd)
{
// Native ad가 만료되었습니다. 이는 4시간 후에 발생할 수 있습니다.
// 다음 광고를 로드합니다.
nativeAdLoader.loadAd( createNativeAdView() );
}
}
@Override
protected void onDestroy()
{
// 메모리 누수를 방지하기 위해 native ad 및 native ad loader를 제거합니다.
if ( loadedNativeAd != null )
{
nativeAdLoader.destroy( loadedNativeAd );
}
nativeAdLoader.destroy();
super.onDestroy();
}
}
class ExampleActivity : Activity(), MaxAdRevenueListener
{
private val nativeAdContainerView: ViewGroup? = null
private var nativeAdLoader: MaxNativeAdLoader? = null
private var loadedNativeAd: MaxAd? = null
⋮
private fun createNativeAdLoader()
{
nativeAdLoader = MaxNativeAdLoader("«ad-unit-ID»", this)
nativeAdLoader?.setRevenueListener(this)
nativeAdLoader?.setNativeAdListener(NativeAdListener())
}
private fun loadNativeAd()
{
nativeAdLoader?.loadAd(createNativeAdView())
}
override fun onAdRevenuePaid(ad: MaxAd) {}
private inner class NativeAdListener : MaxNativeAdListener()
{
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, nativeAd: MaxAd)
{
// 메모리 누수를 방지하기 위해 기존에 존재하는 native ad를 제거합니다.
if (loadedNativeAd != null)
{
nativeAdLoader?.destroy(loadedNativeAd)
}
// 정리를 위해 광고를 저장합니다.
loadedNativeAd = nativeAd
nativeAdContainerView?.removeAllViews()
nativeAdContainerView?.addView(nativeAdView)
}
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError)
{
// Native ad 로드 실패.
// AppLovin은 최대 지연 시간까지 지연 시간을 기하급수적으로 늘리며 재시도할 것을 권장합니다.
}
override fun onNativeAdClicked(nativeAd: MaxAd) {}
override fun onNativeAdExpired(nativeAd: MaxAd)
{
// Native ad가 만료되었습니다. 이는 4시간 후에 발생할 수 있습니다.
// 다음 광고를 로드합니다.
nativeAdLoader?.loadAd(createNativeAdView())
}
}
override fun onDestroy()
{
// 메모리 누수를 방지하기 위해 native ad 및 native ad loader를 제거합니다.
if (loadedNativeAd != null)
{
nativeAdLoader?.destroy(loadedNativeAd)
}
nativeAdLoader?.destroy()
super.onDestroy()
}
}
AppLovin은 앱의 나머지 디자인 컨텍스트에 적합한 만큼 많은 native 요소를 통합할 것을 권장합니다. 여기에는 Title 및 Media View 또는 Icon이 포함될 수 있습니다. 사용자에게 더 많은 정보를 제공하면 사용자가 광고를 클릭할지 여부를 결정하는 데 도움이 됩니다.
AppLovin Exchange 디맨드의 경우, Title, Description 및 CTA에 허용되는 최대 글자 수는 다음과 같습니다.
| 에셋 | 최대 글자 수 |
|---|---|
| Title | 50자 |
| Description | 150자. 149자 뒤에 150번째 글자로 말줄임표(…)를 추가할 수 있습니다. |
| CTA | 15자 |
SDK-mediated networks의 경우, 네트워크가 최대 글자 수를 설정합니다.
다음 코드 스니펫은 native ad의 미디어 콘텐츠 가로세로 비율을 가져오는 방법을 보여줍니다:
@Override
public void onNativeAdLoaded(final MaxNativeAdView adView, final MaxAd ad)
{
MaxNativeAd nativeAd = ad.getNativeAd();
if ( nativeAd != null )
{
float aspectRatio = nativeAd.getMediaContentAspectRatio();
}
}
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
val nativeAd = ad.nativeAd
if (nativeAd != null) {
val aspectRatio = nativeAd.mediaContentAspectRatio
}
}
일부 네트워크는 미디어 콘텐츠 가로세로 비율을 제공하지 않습니다. 해당 네트워크의 경우 값은 0입니다.
광고 대상 앱의 별점에 액세스하여 렌더링할 수 있습니다. 이 값은 사용 가능한 경우 [0.0, 5.0] 범위의 부동 소수점 수입니다.
MAX SDK는 별점 컨테이너로 지정한 컨테이너 뷰에 별을 자동으로 렌더링합니다. 네트워크가 별점을 제공하지 않거나 별점이 < 3인 경우, SDK는 별점 컨테이너 뷰를 채우지 않습니다. 개발자는 이에 따라 레이아웃을 조정해야 합니다.
현재 광고의 별점을 가져오려면:
@Override
public void onNativeAdLoaded(final MaxNativeAdView adView, final MaxAd ad)
{
MaxNativeAd nativeAd = ad.getNativeAd();
if ( nativeAd != null )
{
Double starRating = nativeAd.getStarRating();
if ( starRating == null || starRating < 3 )
{
// 별점을 사용할 수 없거나 3 미만인 경우 - 별점 컨테이너 뷰 숨기기
return;
}
// 별점을 사용할 수 있고 3 이상인 경우 - 별점 컨테이너 뷰 표시
}
}
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
val nativeAd = ad.nativeAd
if (nativeAd != null) {
val starRating = nativeAd.starRating
if (starRating == null || starRating < 3) {
// 별점을 사용할 수 없거나 3 미만인 경우 - 별점 컨테이너 뷰 숨기기
return
}
// 별점을 사용할 수 있고 3 이상인 경우 - 별점 컨테이너 뷰 표시
}
}
Ad Placer는 RecyclerView를 사용하여 기존 콘텐츠 스트림에 native ads를 자동으로 삽입합니다.
이 API를 연동하려면 다음과 같은 상위 단계를 수행하십시오.
이 페이지에서는 아래에서 이러한 단계에 대해 더 자세히 설명합니다.
AppLovin의 정책을 준수하려면 광고에 개인정보 보호 정보 아이콘이 포함되어야 합니다.
이 아이콘은 중요한 개인정보 처리방침 고지로 연결됩니다.
MaxNativeAdViewBinder.Builder#setOptionsContentViewGroupId(…)를 통해 바인딩할 수 있습니다.
Ad placer는 수동 native ad 레이아웃을 지원합니다. 이러한 광고 레이아웃을 구성하는 방법을 알아보려면 이 페이지의 "Manual" 섹션을 참조하십시오. ad placer가 레이아웃을 지원하도록 구성하는 방법을 알아보려면 아래의 광고 렌더링 설정 구성을 참조하십시오.
각 네트워크의 가이드를 따르고 필수 광고 에셋을 바인딩하십시오. 그렇지 않으면 네트워크에서 귀하의 impressions를 무효화할 수 있습니다.
광고 단위 식별자를 사용하여 MaxAdPlacerSettings 객체를 생성합니다.
이 객체는 ad placer를 구성하고 피드 내 광고의 포지셔닝 정보를 제공합니다.
MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "«ad-unit-ID»" );
val settings = MaxAdPlacerSettings("«ad-unit-ID»")
Ad placer는 피드에 광고를 배치합니다. 이는 다음 중 최소 하나를 기반으로 수행됩니다.
MaxAdPlacerSettings를 수정하여 광고 위치를 구성하십시오.
settings.addFixedPosition( 3 );
settings.addFixedPosition( 3 )
settings.resetFixedPositions();
settings.resetFixedPositions()
settings.setRepeatingInterval( 5 );
settings.repeatingInterval = 5
MaxAdPlacerSettings에서 다음 설정을 조정하여 ad placer를 추가로 구성할 수 있습니다.
maxAdCountmaxPreloadedAdCountad placer를 구성할 때 다음 두 가지 옵션 중 하나를 선택하십시오.
RecyclerView를 기반으로 하는 경우 MaxRecyclerAdapter를 사용하십시오.
이 헬퍼 클래스는 기존 어댑터를 래핑합니다.
피드에 광고를 자동으로 렌더링하고 삽입합니다.
getAdPlacer()를 호출하여 기본 ad placer에 액세스할 수 있습니다.MaxAdPlacer를 서브클래싱하거나 직접 사용하는 것을 선호할 수 있습니다.
예를 들어 피드가 다른 커스텀 UI 컴포넌트를 사용하는 경우 이 작업을 수행할 수 있습니다.MaxRecyclerAdapter로 ad placer를 구성하려면 다음 지침을 따르십시오.
MaxRecyclerAdapter를 초기화합니다.adAdapter = new MaxRecyclerAdapter( settings, adapter, this );
adAdapter = MaxRecyclerAdapter(settings, adapter, this)
MaxRecyclerAdapter로 설정합니다.recyclerView.setAdapter( adAdapter );
recyclerView.adapter = adAdapter
notifyItemInserted()notifyItemRemoved()notifyItemsInserted()notifyItemsRemoved()MaxRecyclerAdapter에 등록하십시오.
이렇게 하면 광고 삽입 후 조정된 콘텐츠 항목의 위치를 수신합니다.adAdapter.getOriginalPosition()을 호출하여 이 작업을 수행합니다.loadAds()를 호출하여 광고 로드를 시작합니다.adAdapter.loadAds();
adAdapter.loadAds()
다음 코드는 MaxRecyclerAdapter를 사용하여 리사이클러 뷰에 광고를 로드하는 방법을 보여줍니다.
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate( savedInstanceState );
// 자체 리사이클러 뷰 및 기존 어댑터 생성
⋮
// 광고 어댑터 구성
MaxAdPlacerSettings settings = new MaxAdPlacerSettings( "«ad-unit-ID»" );
settings.setRepeatingInterval( 5 );
adAdapter = new MaxRecyclerAdapter( settings, originalAdapter, this );
// 선택 사항: 리스너 등록
adAdapter.setListener( this );
// 리사이클러 뷰 구성 및 광고 로드
recyclerView.setAdapter( adAdapter );
adAdapter.loadAds();
}
@Override
public void onDestroy()
{
adAdapter.destroy();
super.onDestroy();
}
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
// 자체 리사이클러 뷰 및 기존 어댑터 생성
⋮
// 광고 어댑터 구성
val settings = MaxAdPlacerSettings("«ad-unit-ID»")
settings.repeatingInterval = 5
adAdapter = MaxRecyclerAdapter(settings, originalAdapter, this)
// 선택 사항: 리스너 등록
adAdapter.listener = this
// 리사이클러 뷰 구성 및 광고 로드
recycler.adapter = adAdapter
adAdapter.loadAds()
}
override fun onDestroy()
{
adAdapter.destroy()
super.onDestroy()
}
광고를 로드하기 전에 ad placer에서 setNativeAdViewBinder를 호출하십시오.
항상 광고 크기를 설정하십시오.
이렇게 하면 렌더링이 최적화됩니다.
ad placer는 이벤트 발생 시 알림을 주는 선택적 리스너를 지원합니다.
onAdLoaded()onAdRemoved()onAdClicked()onAdRevenuePaid()