네이티브 광고

네이티브 광고는 레이아웃을 앱 쪽에서 정의할 수 있는 광고 유형입니다. 이를 통해 앱 디자인 특성을 고려해 광고의 시각적 스타일과 배치를 바꿀 수 있습니다.

네이티브 광고는 광고 경험을 개선합니다. 그 결과 사용자 흥미를 잃지 않으면서 더 많은 광고를 노출할 수 있어 장기적으로 광고 수익을 극대화할 수 있습니다.

광고 렌더링은 네이티브 플랫폼 도구로 수행되어 광고 성능과 품질이 향상됩니다.

외형

이 가이드는 Android 앱에 네이티브 광고를 연동하는 과정을 다룹니다. 코드 예시와 설명 외에도 형식별 권장 사항과 추가 자료 링크를 포함합니다.

사전 요구 사항

  1. 빠른 시작에 설명된 SDK 통합 단계를 따릅니다.
  2. 미리 광고 SDK를 초기화합니다.
  3. Yandex Mobile Ads SDK의 최신 버전을 사용 중인지 확인합니다. 미디에이션을 사용하는 경우 통합 빌드도 최신 버전인지 확인합니다.

구현

네이티브 광고 연동의 주요 단계:

  • NativeAdLoader 광고 로더를 생성하고 설정합니다.
  • 광고 로드 이벤트 리스너를 등록합니다.
  • 광고를 로드합니다.
  • 로드된 광고를 렌더링합니다.

네이티브 광고 연동의 특징

  1. Yandex Mobile Ads SDK 메서드 호출은 모두 메인 스레드에서 수행해야 합니다.

  2. onAdFailedToLoad() 콜백에서 오류가 반환되면 새 광고를 다시 로드하지 마세요. 부득이한 경우 광고 재로드 횟수를 제한하세요. 그러면 제한이 있을 때 끊임없는 실패 요청과 연결 문제를 줄이는 데 도움이 됩니다.

  3. 광고와 상호작용이 이루어지는 화면이 살아 있는 동안 광고와 로더에 대한 강한 참조를 유지하는 것을 권장합니다.

  4. 광고 컨테이너 크기는 광고 콘텐츠를 기준으로 잡는 것이 좋습니다. 광고 로드가 끝나면 모든 에셋을 렌더링해야 합니다. 사용 가능한 광고 에셋 목록은 NativeAd 광고 객체에서 가져올 수 있습니다.

  5. 동영상 광고가 보통 가장 좋은 성과를 냅니다. 동영상 광고를 표시하려면 광고 컨테이너와 MediaView 에셋 크기가 최소 300×160 dp(밀도 무관 픽셀) 이상이어야 합니다.

  6. 가능한 모든 에셋을 담은 레이아웃 사용을 권장합니다. 실무적으로 이런 레이아웃이 전환율이 더 높습니다.

  1. 상단 비클릭 안전 영역의 높이는 80 dp입니다. 해당 영역 안의 컨트롤은 클릭 가능할 수 있습니다.

  2. 시각 요소(에셋)는 닫기 버튼을 포함해 모든 아이콘을 합쳐 최소 32×32 dp 크기여야 합니다.

  3. 에셋 주변 클릭 영역은 최소 64×64 dp여야 합니다. 예를 들어 에셋이 32×32 dp이면 패딩을 두어 전체 클릭 영역이 64×64 dp가 되도록 해야 합니다.

  4. 컨트롤이 지연되어 나타나면 요소가 로드될 때까지 타이머나 진행 표시줄을 표시해야 합니다.

예시

광고 로드

네이티브 광고를 로드하려면 NativeAdLoader 객체를 만듭니다.

광고 요청 매개변수는 NativeAdRequestConfiguration.Builder 클래스 객체로 설정합니다. 요청 매개변수로 광고 유닛 ID, 이미지 로드 방식, 연령·성별 등 노출 관련성을 높일 수 있는 데이터를 넣을 수 있습니다. 자세한 내용은 광고 타기팅을 참고하세요.

로드 결과 알림을 받으려면 NativeAdLoadListener 인스턴스를 만들어 광고 로더의 이벤트 리스너로 지정합니다.

광고를 로드하려면 loadAd() 메서드를 호출합니다.

아래 예시는 Activity에서 네이티브 광고를 로드하는 방법을 보여 줍니다.

class CustomNativeAdActivity : AppCompatActivity(R.layout.activity_custom_native_ad) {

  private val nativeAdView get() = binding.nativeAd.root

  private var nativeAdLoader: NativeAdLoader? = null

  private lateinit var binding: ActivityCustomNativeAdBinding

  override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      binding = ActivityCustomNativeAdBinding.inflate(layoutInflater)
      setContentView(binding.root)

      nativeAdLoader = createNativeAdLoader()
      nativeAdLoader?.loadAd(
          // Methods in the NativeAdRequestConfiguration.Builder class can be used here to specify individual options settings.
          NativeAdRequestConfiguration.Builder("your-ad-unit-id").build())
  }

  private fun createNativeAdLoader(): NativeAdLoader {
      return nativeAdLoader ?: NativeAdLoader(this).apply {
          setNativeAdLoadListener(object : NativeAdLoadListener {
              override fun onAdLoaded(p0: NativeAd) {
                  // The ad was loaded successfully. Now you can show the loaded ad.
              }

              override fun onAdFailedToLoad(p0: AdRequestError) {
                  // Ad failed to load with AdRequestError.
                  // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
              }
          })
      }
  }
}
class CustomNativeAdActivity extends AppCompatActivity {
  private NativeAdView mNativeAdView = mBinding.nativeAd.getRoot();

  @Nullable private NativeAdLoader mNativeAdLoader = null;

  private ActivityCustomNativeAdBinding mBinding;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mBinding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
      setContentView(mBinding.getRoot());

      mNativeAdLoader = createNativeAdLoader();
      if (mNativeAdLoader != null) {
          // Methods in the NativeAdRequestConfiguration.Builder class can be used here to specify individual options settings.
          mNativeAdLoader.loadAd(
                  new NativeAdRequestConfiguration.Builder("your-ad-unit-id").build()
          );
      }
  }

  private NativeAdLoader createNativeAdLoader() {
      if (mNativeAdLoader != null) {
          return mNativeAdLoader;
      }

      final NativeAdLoader newNativeAdLoader = new NativeAdLoader(this);
      newNativeAdLoader.setNativeAdLoadListener(new NativeAdLoadListener() {
          @Override
          public void onAdLoaded(@NonNull final NativeAd nativeAd) {
              // The ad was loaded successfully. Now you can show the loaded ad.
          }

          @Override
          public void onAdFailedToLoad(@NonNull final AdRequestError error) {
              // Ad failed to load with AdRequestError.
              // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
          }
      });
      return newNativeAdLoader;
  }
}

Adfox를 통해 광고를 게재하는 경우 배너 광고 응답 후 NativeAd 또는 BannerAdView 객체에서 AdAttributes 유형의 adAttributes 속성을 사용해 campaignId, bannerId, placeId 데이터에 접근할 수 있습니다.

광고 표시

광고 로드가 끝나면 모든 에셋을 렌더링해야 합니다. 광고에 포함된 에셋 목록은 NativeAd 광고 객체에서 가져올 수 있습니다.

광고 레이아웃을 구성하는 방법은 두 가지입니다.

  • 템플릿 기반 레이아웃.
  • 네이티브 광고 레이아웃 수동 구성.

템플릿 기반 레이아웃

표준 템플릿 레이아웃은 네이티브 광고를 다루는 가장 단순한 방법이며, 기본 형태는 몇 줄의 코드만으로 설정할 수 있습니다.

템플릿에는 필요한 광고 에셋이 모두 들어 있고 상대 배치가 정의되어 있습니다. 지원되는 모든 네이티브 광고 유형과 호환됩니다.

샘플 코드
private fun showAd(nativeAd: NativeAd) {
   nativeAd.setNativeAdEventListener(NativeAdEventLogger())
   binding.nativeBanner.setAd(nativeAd)
}

private inner class NativeAdEventLogger : NativeAdEventListener {
    override fun onAdClicked() {
       // Called when a click is recorded for an ad.
    }

    override fun onLeftApplication() {
        // Called when the user is about to leave the application (e.g., to go to the browser), as a result of clicking on the ad.
    }

    override fun onReturnedToApplication() {
        // Called when the user returns to the application after a click.
    }

    override fun onImpression(data: ImpressionData?) {
        // Called when an impression is recorded for an ad.
    }
}
private void showAd(@NonNull final NativeAd nativeAd) {
    nativeAd.setNativeAdEventListener(new NativeAdEventLogger());
    mBinding.nativeBanner.setAd(nativeAd);
}

private static class NativeAdEventLogger implements NativeAdEventListener {
    @Override
    public void onAdClicked() {
        //  Called when a click is recorded for an ad.
    }

    @Override
    public void onLeftApplication() {
        // Called when the user is about to leave the application (e.g., to go to the browser), as a result of clicking on the ad.
    }

    @Override
    public void onReturnedToApplication() {
        // Called when the user returns to the application after a click.
    }

    @Override
    public void onImpression(@Nullable ImpressionData impressionData) {
        // Called when an impression is recorded for an ad.
    }
}

네이티브 광고 템플릿은 사용자화할 수 있습니다. 자세한 내용은 템플릿으로 레이아웃 설정하기를 참고하세요.

네이티브 광고 레이아웃 수동 구성

템플릿으로는 요구를 충족할 수 없으면 네이티브 광고 레이아웃을 직접 구성할 수 있습니다.

이 방식으로 네이티브 광고용 사용자 정의 레이아웃을 만들고, 에셋끼리의 상대 위치를 정할 수 있습니다. 광고에는 필수·선택 표시 에셋이 모두 포함될 수 있습니다. 전체 목록은 네이티브 광고 에셋을 참고하세요.

Совет

가능한 모든 에셋을 담은 레이아웃 사용을 권장합니다. 실무적으로 이런 레이아웃이 전환율이 더 높습니다.

각 광고 에셋은 NativeAdViewBinder.Builder 인스턴스를 통해 View를 제공합니다. 이 클래스는 인수로 NativeAdView 컨테이너를 받습니다. 모든 광고 에셋을 이 컨테이너의 하위 뷰로 정의하세요.

준비한 광고 레이아웃을 NativeAd 객체에 연결합니다.

샘플 코드
private fun showAd(nativeAd: NativeAd) {
    val nativeAdViewBinder = binding.nativeAd.run {
        NativeAdViewBinder.Builder(nativeAdView)
            .setAgeView(age)
            .setBodyView(body)
            .setCallToActionView(callToAction)
            .setDomainView(domain)
            .setFaviconView(favicon)
            .setFeedbackView(feedback)
            .setIconView(icon)
            .setMediaView(media)
            .setPriceView(price)
            .setRatingView(rating)
            .setReviewCountView(reviewCount)
            .setSponsoredView(sponsored)
            .setTitleView(title)
            .setWarningView(warning)
            .build()
    }

    try {
        nativeAd.bindNativeAd(nativeAdViewBinder)
        nativeAd.setNativeAdEventListener(NativeAdEventLogger())
    } catch (exception: NativeAdException) {
        Logger.error(exception.message.orEmpty())
    }
}

private inner class NativeAdEventLogger : NativeAdEventListener {

    override fun onAdClicked() {
        // Called when a click is recorded for an ad.
    }

    override fun onLeftApplication() {
        // Called when the user is about to leave the application (e.g., to go to the browser), as a result of clicking on the ad.
    }

    override fun onReturnedToApplication() {
        // Called when the user returns to the application after a click.
    }

    override fun onImpression(data: ImpressionData?) {
        // Called when an impression is recorded for an ad.
    }
}
private void showAd(@NonNull final NativeAd nativeAd) {
    final NativeAdViewBinder nativeAdViewBinder = new NativeAdViewBinder.Builder(mNativeAdView)
            .setAgeView(age)
            .setBodyView(body)
            .setCallToActionView(callToAction)
            .setDomainView(domain)
            .setFaviconView(favicon)
            .setFeedbackView(feedback)
            .setIconView(icon)
            .setMediaView(media)
            .setPriceView(price)
            .setRatingView(rating)
            .setReviewCountView(reviewCount)
            .setSponsoredView(sponsored)
            .setTitleView(title)
            .setWarningView(warning)
            .build();
    try {
        nativeAd.bindNativeAd(nativeAdViewBinder);
        nativeAd.setNativeAdEventListener(new CustomNativeAdActivity.NativeAdEventLogger());
    } catch (final NativeAdException exception) {
        Log.e("TAG", exception.getMessage());
    }
}

private class NativeAdEventLogger implements NativeAdEventListener {
    @Override
    public void onAdClicked() {
        // Called when a click is recorded for an ad.
    }

    @Override
    public void onLeftApplication() {
        // Called when the user is about to leave the application (e.g., to go to the browser), as a result of clicking on the ad.
    }

    @Override
    public void onReturnedToApplication() {
        // Called when the user returns to the application after a click.
    }

    @Override
    public void onImpression(@Nullable ImpressionData data) {
        // Called when an impression is recorded for an ad.
    }
}

여러 광고 로드

Yandex Mobile Ads SDK에서는 한 번의 요청으로 여러 광고(최대 9개)를 로드할 수 있습니다.

일괄 광고 요청을 하려면 NativeBulkAdLoader 클래스 인스턴스를 사용합니다. loadAds 메서드의 count 인수로 요청당 가져올 광고 개수를 지정합니다.

샘플 코드
class NativeBulkAdLoaderActivity : AppCompatActivity(R.layout.activity_custom_native_ad) {

    private val nativeAdView get() = binding.nativeAd.root

    private var nativeAdsLoader: NativeBulkAdLoader? = null

    private lateinit var binding: ActivityCustomNativeAdBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityCustomNativeAdBinding.inflate(layoutInflater)
        setContentView(binding.root)

        nativeAdsLoader = createNativeBulkAdLoader()
        // Methods in the NativeAdRequestConfiguration.Builder class can be used here to specify individual options settings.
        val adRequestConfiguration = NativeAdRequestConfiguration.Builder("your-ad-unit-id").build()
        nativeAdsLoader?.loadAds(adRequestConfiguration, 3)
    }

    private fun createNativeBulkAdLoader(): NativeBulkAdLoader {
        return nativeAdsLoader ?: NativeBulkAdLoader(this).apply {
            setNativeBulkAdLoadListener(object : NativeBulkAdLoadListener {
                override fun onAdsLoaded(p0: MutableList<NativeAd>) {
                    // The ads were loaded successfully. Now you can show the loaded ads.
                    for (nativeAd in p0) {
                        showAd(nativeAd)
                    }
                }

                override fun onAdsFailedToLoad(p0: AdRequestError) {
                    // Ad failed to load with AdRequestError.
                    // Attempting to load new ads from the onAdFailedToLoad() method is strongly discouraged.
                }
            })
        }
    }
}
class CustomBulkNativeAdActivity extends AppCompatActivity {
    private NativeAdView mNativeAdView = mBinding.nativeAd.getRoot();

    @Nullable private NativeBulkAdLoader mNativeAdsLoader = null;

    private ActivityCustomNativeAdBinding mBinding;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());

        mNativeAdsLoader = createNativeBulkAdLoader();
        if (mNativeAdsLoader != null) {
            // Methods in the NativeAdRequestConfiguration.Builder class can be used here to specify individual options settings.
            mNativeAdsLoader.loadAds(
                    new NativeAdRequestConfiguration.Builder("your-ad-unit-id").build();
            );
        }
    }

    private NativeBulkAdLoader createNativeBulkAdLoader() {
        if (mNativeAdsLoader != null) {
            return mNativeAdsLoader;
        }

        final NativeBulkAdLoader newNativeBulkAdLoader = new NativeBulkAdLoader(this);

        newNativeBulkAdLoader.setNativeBulkAdLoadListener(new NativeBulkAdLoadListener() {
            @Override
            public void onAdsLoaded(@NonNull final List<NativeAd> list) {
                // The ad was loaded successfully. Now you can show the loaded ad.
            }

            @Override
            public void onAdsFailedToLoad(@NonNull final AdRequestError error) {
                // Ad failed to load with AdRequestError.
                // Attempting to load a new ad from the onAdFailedToLoad() method is strongly discouraged.
            }
        });
        return newNativeBulkAdLoader;
    }
}

Примечание

일괄 광고 요청으로 서로 다른 광고를 여러 개 고를 수 있습니다.

일괄 요청으로 돌아온 광고 배열에는 0개 이상 count 이하의 NativeAd 객체가 들어 있을 수 있습니다. 받은 모든 광고 객체는 앞서 설명한 네이티브 광고 레이아웃 방식으로 각각 독립적으로 표시할 수 있습니다.

네이티브 광고 연동 테스트

광고 테스트용 데모 광고 유닛

테스트 광고로 네이티브 광고 연동과 앱 자체를 점검하세요.

모든 광고 요청에 테스트 광고가 나오도록 데모 광고 게재 ID를 따로 두었습니다. 연동 검증에 활용하세요.

텍스트·이미지 광고용 데모 adUnitId: demo-native-content-yandex.

모바일 앱 광고용 데모 adUnitId: demo-native-app-yandex.

Важно

스토어에 앱을 출시하기 전에 데모 게재 ID를 Yandex Advertising Network 인터페이스에서 발급받은 실제 ID로 반드시 바꾸세요.

광고 연동 테스트

SDK에 내장된 분석기로 네이티브 광고가 올바르게 연동되었는지 확인할 수 있습니다.

이 도구는 네이티브 광고가 제대로 켜져 있는지 검사하고 로그에 상세 보고서를 출력합니다. 보고서를 보려면 Android 앱 디버깅 도구인 Logcat에서 “YandexAds” 키워드로 검색하세요.

adb logcat -v brief '*:S YandexAds'

연동이 성공하면 다음과 같은 메시지가 반환됩니다.

adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type native was integrated successfully

네이티브 광고 연동에 문제가 있으면 상세한 이슈 보고서와 해결 권장 사항을 받을 수 있습니다.

올바른 네이티브 광고 연동 표시기

이 표시기로 네이티브 광고 연동 성공 여부를 확인할 수 있습니다. 실패한 경우 원인을 설명하는 디버그 정보를 볼 수 있습니다.

Примечание

올바른 광고 연동 표시기 켜기/끄기는 디버그 패널에서 할 수 있습니다.

디버그 모드에서 표시기를 켜려면 enableDebugErrorIndicatortrue로 호출하세요.

MobileAds.enableDebugErrorIndicator(true)

연동이 성공하면 디버그 모드에서 광고 위에 연한 녹색 테두리가 나타납니다.

네이티브 광고 통합에 오류가 있으면 디버그 모드에서 광고 위에 표시기가 나타납니다. 표시기를 클릭하면 원인 파악에 도움이 되는 디버그 메시지가 표시됩니다. 표시기를 다시 클릭하면 메시지가 숨겨집니다.

디버그 모드에서 표시기를 끄려면 enableDebugErrorIndicatorfalse로 호출하세요.

MobileAds.enableDebugErrorIndicator(false)

동영상 광고용 하드웨어 가속

앱 화면에서 동영상 광고가 정상 재생되려면 하드웨어 가속이 켜져 있어야 합니다(문서 참고).

기본적으로 하드웨어 가속이 켜져 있습니다. 앱에서 하드웨어 가속을 끈 경우 광고가 게재되는 화면에서는 반드시 켜 두세요.

하드웨어 가속을 켜는 코드
<application android:hardwareAccelerated="true">
    <!-- For activities that use ads, hardwareAcceleration should be true. -->
    <activity android:hardwareAccelerated="true" />
</application>