메인 콘텐츠로 건너뛰기

네이티브 광고 형태 소개

  • 광고 뷰를 미디에이션 SDK가 구현해주는 타 광고 형태와 달리 네이티브 광고 형태는 구성 요소들을 전달받아 앱에서 직접 광고 뷰를 구현합니다.
  • UI/UX 기반으로 레이아웃을 직접 구현하므로써 위화감을 적게 만들 수 있다는 것이 가장 큰 특징입니다. 단, 유저가 광고가 아닌 컨텐츠로써 착각하는 경우를 방지하기 위해 광고 표시와 함께 최소한의 차별성은 부여해야합니다.
Native Example Elements Ko Pn
네이티브 광고 필수 요소 4가지네이티브 광고는 앱 UI에 맞게 자유롭게 디자인할 수 있지만, 아래의 4가지 필수 요소는 반드시 포함해야 합니다. 이는 사용자가 광고임을 명확히 인지하도록 하고, 광고주가 기대하는 최소한의 광고 효과를 보장하기 위한 광고 정책입니다.
  1. 광고 표기 : 사용자가 광고임을 명확히 인지할 수 있도록 광고 영역에 “AD”, “광고” 등의 표기를 추가해 주세요.
  2. AdChoices 아이콘 : AdChoices 아이콘은 사용자가 광고를 식별하고 제어할 수 있도록 제공되는 아이콘으로, 일반적으로 ’ⓘ’ 모양으로 표시됩니다. 해당 아이콘은 DARO SDK에서 자동으로 삽입되므로 별도 구현은 필요하지 않지만, 다른 UI 요소에 가려지지 않도록 광고 뷰를 구성해 주세요. 광고 소스(디맨드)에 따라 아이콘의 형태나 동작이 다를 수 있습니다.
  3. 광고 제목 (타이틀) : 광고의 제목을 표시해야 합니다.
  4. 클릭 유도 문안(CTA) : “설치”, “열기”, “다운로드” 등의 CTA(Call to Action) 버튼을 반드시 포함해 주세요. 버튼의 크기나 형태는 자유롭게 구성할 수 있으며, 상황에 따라 텍스트 필드로 대체 가능합니다. 광고 소스(디맨드)에서 CTA 문구를 제공하므로, 특정 문구를 고정할 필요는 없습니다.

네이티브 뷰 컴포넌트 생성하기

  • Non-Reward
  • Reward
import { NativeAdView, TitleView, AdvertiserView, BodyView, CallToActionView, IconView, OptionsView, MediaView, StarRatingView } from 'react-native-daro';
import type { AdInfo, AdLoadFailedInfo, NativeAdViewHandler } from 'react-native-daro';
import { useRef, useState } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
// import문은 위의 탭 참조
import { NativeAdView, TitleView, AdvertiserView, BodyView, CallToActionView, IconView, OptionsView, MediaView, StarRatingView } from 'react-native-daro-m';
import type { AdInfo, AdLoadFailedInfo, NativeAdViewHandler } from 'react-native-daro-m';
import { AppButton } from './components/AppButton';

type Props = {
  adUnitId: string;
  isInitialized: boolean;
  log: (str: string) => void;
  isNativeAdShowing: boolean;
  setIsNativeAdShowing: (showing: boolean) => void;
};

const NATIVE_AD_MEDIAVIEW_WIDTH = 340;
const NATIVE_AD_MEDIAVIEW_HEIGHT = 200;

export const NativeAdViewExample = ({ adUnitId, isInitialized, log, isNativeAdShowing, setIsNativeAdShowing }: Props) => {
  const [isNativeAdLoading, setIsNativeAdLoading] = useState(false);

  // Ref for NativeAdView
  const nativeAdViewRef = useRef<NativeAdViewHandler>(null);

  return (
    <>
      <AppButton
        style={styles.button}
        title={isNativeAdShowing ? 'Hide Native Ad' : 'Show Native Ad'}
        enabled={isInitialized}
        onPress={() => {
          setIsNativeAdShowing(!isNativeAdShowing);
        }}
      />

      {isNativeAdShowing && (
        <View style={styles.container}>
          <NativeAdView
            adUnitId={adUnitId}
            ref={nativeAdViewRef}
            style={styles.nativeAd}
            onAdLoaded={(adInfo: AdInfo) => {
              log('Native ad loaded from ' + adInfo);
              setIsNativeAdLoading(false);
            }}
            onAdLoadFailed={(errorInfo: AdLoadFailedInfo) => {
              log('Native ad failed to load with error code ' + errorInfo.code + ' and message: ' + errorInfo.message);
              setIsNativeAdLoading(false);
            }}
            onAdClicked={(adInfo: AdInfo) => {
              log('Native ad clicked on ' + adInfo.adUnitId);
            }}
            onAdImpressionRecorded={(adInfo: AdInfo) => {
              log('Native ad impression recorded');
            }}
          >
            <View style={styles.assetContainer}>
              <View style={styles.assetUpperContainer}>
                <IconView style={styles.icon} />
                <View style={styles.assetTitleContainer}>
                  <TitleView style={styles.title} />
                </View>
              </View>
              <BodyView style={styles.body} />
              <MediaView style={{ ...styles.mediaView }} />
              <CallToActionView style={styles.callToAction} />
            </View>
          </NativeAdView>
          <AppButton
            style={styles.button}
            title={'RELOAD'}
            enabled={!isNativeAdLoading}
            onPress={() => {
              setIsNativeAdLoading(true);
              nativeAdViewRef.current?.loadAd();
            }}
          />
          <AppButton
            style={styles.button}
            title={'CLOSE'}
            enabled={!isNativeAdLoading}
            onPress={() => {
              setIsNativeAdShowing(!isNativeAdShowing);
            }}
          />
        </View>
      )}
    </>
  );
};

const styles = StyleSheet.create({
  button: {
    margin: 5,
    backgroundColor: '#0583aa',
  },
  container: {
    position: 'absolute', // must have a view behind for touch event propagation
    top: '30%',
    width: '100%',
    padding: 10,
    backgroundColor: '#0583aa',
    zIndex: 1,
    elevation: Platform.OS === 'android' ? 1 : 0,
  },
  nativeAd: {
    padding: 10,
    width: '100%',
    backgroundColor: '#EFEFEF',
  },
  icon: {
    width: 48,
    height: 48,
  },
  title: {
    width: 260,
    fontSize: 16,
    textAlign: 'left',
    fontWeight: 'bold',
    color: 'black',
  },
  body: {
    padding: 8,
    fontSize: 14,
    textAlign: 'center',
    textAlignVertical: 'center',
  },
  mediaView: {
    alignSelf: 'center',
    width: NATIVE_AD_MEDIAVIEW_WIDTH,
    height: NATIVE_AD_MEDIAVIEW_HEIGHT,
    maxWidth: NATIVE_AD_MEDIAVIEW_WIDTH,
    maxHeight: NATIVE_AD_MEDIAVIEW_HEIGHT,
    zIndex: 1,
    elevation: Platform.OS === 'android' ? 1 : 0,
  },
  callToAction: {
    marginTop: 10,
    padding: 8,
    width: '100%',
    fontSize: 18,
    textAlign: 'center',
    fontWeight: 'bold',
    textTransform: 'uppercase',
    color: 'black',
    backgroundColor: '#2d545e',
  },
  assetContainer: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'space-between',
  },
  assetUpperContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  assetTitleContainer: {
    marginLeft: 4,
    flexDirection: 'column',
    flexGrow: 1,
  },
});

export default NativeAdViewExample;
  • 동일 AdUnitId를 여러 지면에서 사용하는 경우 각 지면을 구분할 수 있도록 placement를 반드시 입력해주세요

주의사항

광고 컴포넌트의 조건부 렌더링

NativeAdView의 자식 광고 컴포넌트들(IconView, TitleView, CallToActionView 등)은 반드시 DOM에 존재해야 합니다. 조건부 렌더링으로 광고 컴포넌트를 숨기면 광고가 로드되어도 표시되지 않습니다.