> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# ネイティブ広告

> React Nativeアプリでネイティブ広告を実装する方法をご案内します。

## 概要

ネイティブ広告はアプリのデザインに合わせて広告UIを自由にカスタマイズできる広告フォーマットです。広告素材（画像、動画）、タイトル、説明、CTAボタンなどの要素を個別に配置して自然なユーザー体験を提供できます。

### 主な機能

* **完全なUIカスタマイズ**：アプリのデザインシステムに合わせて広告レイアウトを自由に構成
* **多様なメディア対応**：画像および動画広告素材対応
* **柔軟なクリック処理**：全体クリックまたはカスタムクリック処理が可能
* **プロフィール情報表示**：広告主プロフィールロゴおよび名前対応
* **バックフィル広告対応**：バックフィル広告かどうか確認可能

***

## AdropNativeAdクラス

ネイティブ広告をロードして管理するメインクラスです。

### コンストラクタ

```typescript theme={null}
new AdropNativeAd(
  unitId: string,
  useCustomClick?: boolean,
  preferredAdChoicesPosition?: AdropAdChoicesPosition
)
```

<ParamField path="unitId" type="string" required>
  広告ユニットID（コンソールで発行）
</ParamField>

<ParamField path="useCustomClick" type="boolean" default="false">
  カスタムクリック処理使用有無

  * `true`：開発者が直接クリック処理を実装（ビデオ広告コントローラー使用可能）
  * `false`：AdropNativeAdViewがすべてのクリックイベントを自動処理
</ParamField>

<ParamField path="preferredAdChoicesPosition" type="AdropAdChoicesPosition" default="AdropAdChoicesPosition.topRight">
  バックフィルネイティブ広告のAdChoicesマーク表示位置
</ParamField>

### メソッド

| メソッド        | 説明               |
| ----------- | ---------------- |
| `load()`    | 広告をリクエストしてロードします |
| `destroy()` | 広告リソースを解放します     |

### プロパティ

| プロパティ            | タイプ                     | 説明                     |
| ---------------- | ----------------------- | ---------------------- |
| `isLoaded`       | `boolean`               | 広告ロード完了有無（読み取り専用）      |
| `unitId`         | `string`                | 広告ユニットID（読み取り専用）       |
| `useCustomClick` | `boolean`               | カスタムクリック処理使用有無（読み取り専用） |
| `creativeId`     | `string`                | 広告素材ID（読み取り専用）         |
| `txId`           | `string`                | トランザクションID（読み取り専用）     |
| `campaignId`     | `string`                | キャンペーンID（読み取り専用）       |
| `isBackfilled`   | `boolean`               | バックフィル広告かどうか（読み取り専用）   |
| `isVideoAd`      | `boolean`               | ビデオ広告かどうか（読み取り専用）      |
| `browserTarget`  | `BrowserTarget`         | ブラウザターゲット設定（読み取り専用）    |
| `properties`     | `AdropNativeProperties` | 広告プロパティ情報（読み取り専用）      |
| `listener`       | `AdropNativeAdListener` | 広告イベントリスナー             |

***

## AdropNativeAdViewコンポーネント

ネイティブ広告を表示するコンテナコンポーネントです。

### Props

```typescript theme={null}
interface Props extends ViewProps {
  nativeAd?: AdropNativeAd
}
```

<ParamField path="nativeAd" type="AdropNativeAd">
  表示するネイティブ広告インスタンス
</ParamField>

### 使用例

```tsx theme={null}
<AdropNativeAdView nativeAd={nativeAd} style={styles.adContainer}>
  {/* 広告要素 */}
</AdropNativeAdView>
```

<Note>
  `AdropNativeAdView`は広告コンテキストを提供するため、すべての広告要素ビューはこのコンポーネント内部に配置する必要があります。
</Note>

***

## ネイティブ広告要素ビュー

### AdropProfileLogoView

広告主プロフィールロゴを表示する画像コンポーネントです。

```tsx theme={null}
<AdropProfileLogoView style={styles.profileLogo} />
```

**Props**: `Omit<ImageProps, 'source'>`（React NativeのImageコンポーネントプロパティ、`source`は自動設定されます）

### AdropProfileNameView

広告主プロフィール名を表示するテキストコンポーネントです。

```tsx theme={null}
<AdropProfileNameView style={styles.profileName} />
```

**Props**: `TextProps`（React NativeのTextコンポーネントプロパティ）

### AdropHeadLineView

広告タイトルを表示するテキストコンポーネントです。

```tsx theme={null}
<AdropHeadLineView style={styles.headline} />
```

**Props**: `TextProps`（React NativeのTextコンポーネントプロパティ）

### AdropBodyView

広告本文を表示するテキストコンポーネントです。

```tsx theme={null}
<AdropBodyView style={styles.body} />
```

**Props**: `TextProps`（React NativeのTextコンポーネントプロパティ）

### AdropMediaView

広告画像または動画を表示するメディアコンポーネントです。

```tsx theme={null}
<AdropMediaView style={styles.media} />
```

**Props**: `ViewProps`（React NativeのViewコンポーネントプロパティ）

<Warning>
  **ネイティブ広告の動画クリエイティブ**は、必ず`properties.creative`（HTMLペイロード）を`WebView`でレンダリングする必要があります。`properties.asset`を`react-native-video`などの独自プレイヤーに直接渡すと、SDKの動画トラッキングパイプラインを経由しなくなり、**VTRが計測されず**、`onAdVideoStart` / `onAdVideoEnd`コールバックも呼び出されません。[動画トラッキングとVTR](#動画トラッキングとvtr)セクションを参照してください。
</Warning>

### AdropCallToActionView

行動誘導フレーズ（CTA）を表示するテキストコンポーネントです。

```tsx theme={null}
<AdropCallToActionView style={styles.cta} />
```

**Props**: `TextProps`（React NativeのTextコンポーネントプロパティ）

### AdropAdvertiserView

広告主名を表示するテキストコンポーネントです。

```tsx theme={null}
<AdropAdvertiserView style={styles.advertiser} />
```

**Props**: `TextProps`（React NativeのTextコンポーネントプロパティ）

### AdropIconView

広告アイコンを表示する画像コンポーネントです。

```tsx theme={null}
<AdropIconView style={styles.icon} />
```

**Props**: `Omit<ImageProps, 'source'>`（React NativeのImageコンポーネントプロパティ、`source`は自動設定されます）

***

## AdropNativeAdListenerインターフェース

広告イベントを処理するリスナーインターフェースです。

```typescript theme={null}
interface AdropNativeAdListener {
  onAdReceived?: (ad: AdropNativeAd) => void
  onAdClicked?: (ad: AdropNativeAd) => void
  onAdImpression?: (ad: AdropNativeAd) => void
  onAdFailedToReceive?: (ad: AdropNativeAd, errorCode?: any) => void
  onAdVideoStart?: (ad: AdropNativeAd) => void
  onAdVideoEnd?: (ad: AdropNativeAd) => void
}
```

| コールバックメソッド            | 説明                      |
| --------------------- | ----------------------- |
| `onAdReceived`        | 広告受信成功時に呼び出されます         |
| `onAdClicked`         | 広告クリック時に呼び出されます         |
| `onAdImpression`      | 広告表示（インプレッション）時に呼び出されます |
| `onAdFailedToReceive` | 広告受信失敗時に呼び出されます         |
| `onAdVideoStart`      | 動画広告の再生開始時に呼び出されます      |
| `onAdVideoEnd`        | 動画広告の再生終了時に呼び出されます      |

***

## AdropNativePropertiesタイプ

広告プロパティ情報を含むタイプです。

```typescript theme={null}
type AdropNativeProperties = {
  icon?: string                      // アイコン画像URL
  cover?: string                     // カバー画像URL
  headline?: string                  // 広告タイトル
  body?: string                      // 広告本文
  creative?: string                  // 広告素材HTML（WebViewレンダリング用）
  asset?: string                     // アセット情報
  destinationURL?: string            // 遷移先URL
  advertiserURL?: string             // 広告主URL
  accountTag?: string                // アカウントタグ
  creativeTag?: string               // 素材タグ
  advertiser?: string                // 広告主名
  callToAction?: string              // 行動誘導フレーズ
  profile?: AdropNativeProfile       // プロフィール情報
  extra?: Record<string, string>     // 追加情報
  isBackfilled?: boolean             // バックフィル広告かどうか
}
```

***

## AdropNativeProfileタイプ

広告主プロフィール情報を含むタイプです。

```typescript theme={null}
type AdropNativeProfile = {
  displayName: string                // プロフィール表示名
  displayLogo: string                // プロフィールロゴ画像URL
}
```

***

## 実装例

以下はネイティブ広告を実装する完全な例です。

```tsx theme={null}
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import {
  AdropBodyView,
  AdropHeadLineView,
  AdropMediaView,
  AdropNativeAd,
  AdropNativeAdView,
  AdropProfileLogoView,
  AdropProfileNameView,
} from 'adrop-ads-react-native'
import type { AdropNativeAdListener } from 'adrop-ads-react-native'
import { WebView } from 'react-native-webview'
import {
  Button,
  Dimensions,
  ScrollView,
  StyleSheet,
  Text,
  View,
  Linking,
  Platform,
} from 'react-native'

const NativeAdExample: React.FC = () => {
  const [nativeAd, setNativeAd] = useState<AdropNativeAd>()
  const [isLoaded, setIsLoaded] = useState(false)
  const [errorCode, setErrorCode] = useState('')

  // URL開きハンドラー
  const openUrl = useCallback((url: string) => {
    Linking.openURL(url).catch((err) =>
      console.error('Failed to open URL:', err)
    )
  }, [])

  // 広告イベントリスナー
  const listener = useMemo(
    (): AdropNativeAdListener => ({
      onAdReceived: (ad) => {
        console.log('広告受信:', ad.unitId, ad.properties)
        setIsLoaded(true)
        setErrorCode('')
      },
      onAdFailedToReceive: (_, error) => {
        console.log('広告受信失敗:', error)
        setErrorCode(error)
      },
      onAdClicked: (ad) => {
        console.log('広告クリック:', ad.unitId)
      },
      onAdImpression: (ad) => {
        console.log('広告表示:', ad.unitId)
      },
    }),
    []
  )

  // 広告初期化
  const initialize = useCallback(
    (unitId: string) => {
      const adropNativeAd = new AdropNativeAd(unitId)
      adropNativeAd.listener = listener

      setNativeAd((prev) => {
        prev?.destroy()
        return adropNativeAd
      })

      setIsLoaded(false)
      setErrorCode('')
    },
    [listener]
  )

  // コンポーネントマウント時に広告初期化
  useEffect(() => {
    initialize('YOUR_UNIT_ID')

    // コンポーネントアンマウント時に広告解放
    return () => {
      nativeAd?.destroy()
    }
  }, [])

  // 広告ロード
  const load = () => nativeAd?.load()

  // 広告ビューレンダリング
  const adView = useMemo(() => {
    if (!isLoaded) return null

    return (
      <AdropNativeAdView
        nativeAd={nativeAd}
        style={{
          ...styles.adContainer,
          width: Dimensions.get('window').width,
        }}
      >
        {/* プロフィール領域 */}
        <View style={styles.rowContainer}>
          <AdropProfileLogoView style={styles.profileLogo} />
          <AdropProfileNameView style={styles.profileName} />
        </View>

        {/* 広告タイトル */}
        <AdropHeadLineView style={styles.headline} />

        {/* 広告本文 */}
        <AdropBodyView style={styles.body} />

        {/* バックフィル広告または非ビデオ広告はAdropMediaView、ビデオ広告はWebView */}
        {!nativeAd?.isVideoAd || nativeAd?.isBackfilled ? (
          // バックフィル広告または非ビデオ広告：AdropMediaView使用
          <AdropMediaView style={styles.media} />
        ) : (
          // ビデオ広告：WebViewでレンダリング
          <WebView
            source={{
              html: nativeAd?.properties?.creative ?? '',
            }}
            style={styles.media}
            javaScriptEnabled={true}
            mediaPlaybackRequiresUserAction={false}
            allowsInlineMediaPlayback={true}
            scrollEnabled={false}
            onNavigationStateChange={(event) => {
              // Android WebViewイベント
              if (
                event.url &&
                event.url !== 'about:blank' &&
                !event.url.startsWith('data:')
              ) {
                openUrl(event.url)
              }
            }}
            onOpenWindow={(event) => {
              // iOS WebViewイベント（window.open）
              if (event.nativeEvent?.targetUrl) {
                openUrl(event.nativeEvent.targetUrl)
              }
            }}
          />
        )}
      </AdropNativeAdView>
    )
  }, [isLoaded, nativeAd, openUrl])

  return (
    <ScrollView>
      <View style={styles.container}>
        {/* 広告ロードボタン */}
        <View style={styles.button}>
          <Button title="広告ロード" onPress={load} />
        </View>

        {/* 広告ビュー */}
        {adView}

        {/* エラー表示 */}
        {errorCode && (
          <Text style={styles.error}>
            エラー: {errorCode}
          </Text>
        )}
      </View>
    </ScrollView>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    paddingVertical: 5,
    paddingHorizontal: 16,
  },
  button: {
    marginVertical: 8,
  },
  adContainer: {
    paddingHorizontal: 16,
  },
  rowContainer: {
    flexDirection: 'row',
    justifyContent: 'flex-start',
    alignItems: 'center',
    marginBottom: 8,
  },
  profileLogo: {
    width: 32,
    height: 32,
    marginRight: 8,
    borderRadius: 16,
  },
  profileName: {
    fontSize: 14,
    fontWeight: 'bold',
    color: 'black',
  },
  headline: {
    fontSize: 16,
    fontWeight: 'bold',
    color: 'black',
    marginTop: 8,
  },
  body: {
    fontSize: 14,
    color: 'black',
    marginVertical: 8,
  },
  media: {
    width: '100%',
    height: 360,
    marginTop: 8,
  },
  error: {
    color: 'red',
    marginVertical: 8,
  },
})

export default NativeAdExample
```

***

## テストユニットID

開発およびテスト時には以下のテストユニットIDを使用してください。

| プラットフォーム    | フォーマット         | テストユニットID                               |
| ----------- | -------------- | --------------------------------------- |
| Android/iOS | ネイティブ（画像）      | `PUBLIC_TEST_UNIT_ID_NATIVE`            |
| Android/iOS | ネイティブビデオ（16:9） | `PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_16_9` |
| Android/iOS | ネイティブビデオ（9:16） | `PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_9_16` |

<Warning>
  プロダクション配布前に必ず実際のユニットIDに置き換えてください。
</Warning>

***

## エラー処理

広告ロード失敗時に`onAdFailedToReceive`コールバックでエラーコードを受け取ることができます。

### 主なエラーコード

| エラーコード                          | 説明          |
| ------------------------------- | ----------- |
| `AdropErrorCode.network`        | ネットワークエラー   |
| `AdropErrorCode.internal`       | 内部エラー       |
| `AdropErrorCode.initialize`     | 初期化エラー      |
| `AdropErrorCode.invalidUnit`    | 無効なユニットID   |
| `AdropErrorCode.adNoFill`       | 表示可能な広告なし   |
| `AdropErrorCode.adLoading`      | 広告ロード中      |
| `AdropErrorCode.backfillNoFill` | バックフィル広告もなし |

### エラー処理の例

```typescript theme={null}
const listener: AdropNativeAdListener = {
  onAdFailedToReceive: (ad, errorCode) => {
    switch (errorCode) {
      case AdropErrorCode.adNoFill:
        console.log('表示可能な広告がありません - 広告領域を非表示')
        break
      case AdropErrorCode.network:
        console.log('ネットワークエラー - 再試行')
        setTimeout(() => ad.load(), 3000)
        break
      default:
        console.log('広告ロード失敗:', errorCode)
    }
  }
}
```

***

## ベストプラクティス

### 1. リソース解放

コンポーネントアンマウント時に必ず広告リソースを解放してください。

```typescript theme={null}
useEffect(() => {
  const ad = new AdropNativeAd('YOUR_UNIT_ID')
  setNativeAd(ad)

  return () => {
    ad.destroy()
  }
}, [])
```

### 2. ビデオ広告およびバックフィル広告処理

ビデオ広告かどうか、およびバックフィル広告かどうかに応じて適切なレンダリング方式を選択してください。

```tsx theme={null}
{!nativeAd?.isVideoAd || nativeAd?.isBackfilled ? (
  <AdropMediaView style={styles.media} />
) : (
  <WebView source={{ html: nativeAd?.properties?.creative ?? '' }} />
)}
```

### 3. URL処理

WebViewでURLクリック時に外部ブラウザで開くように処理してください。

```tsx theme={null}
<WebView
  onNavigationStateChange={(event) => {
    if (event.url && event.url !== 'about:blank') {
      Linking.openURL(event.url)
    }
  }}
/>
```

### 4. 広告要素の選択的使用

アプリのデザインに合わせて必要な広告要素のみ選択的に使用してください。

```tsx theme={null}
<AdropNativeAdView nativeAd={nativeAd}>
  {/* 最小構成：メディアとタイトルのみ表示 */}
  <AdropHeadLineView style={styles.headline} />
  <AdropMediaView style={styles.media} />
</AdropNativeAdView>
```

***

## 動画トラッキングとVTR

Adropはネイティブ広告の動画指標 — VTR（動画完了率）、`onAdVideoStart`、`onAdVideoEnd` — を、SDKメディアコンテナ内で動画がレンダリングされる場合にのみ収集します。React Nativeでは[実装例](#実装例)セクションのように、`properties.creative`（HTMLペイロード）を`WebView`でレンダリングする方式がこれに該当します。

`properties.asset`フィールドは元の画像または動画ファイルのURLを返します。これはサムネイル表示や媒体社独自分析などの**補助メタデータ**として公開されており、再生を直接行うためのものではありません。

<Warning>
  動画ネイティブ広告の`properties.asset` URLを独自の動画プレイヤー（`react-native-video`、`expo-av`またはサードパーティプレイヤー）に直接渡さないでください。SDKメディアコンテナを経由しないと以下の現象が発生します。

  * 該当面で**VTR（動画完了率）が収集されません。**
  * `onAdVideoStart` / `onAdVideoEnd`コールバックが**呼び出されません。**
  * 該当ユニットの動画パフォーマンス集計が欠落または0として報告されます。

  クリック（`onAdClicked`）とインプレッション（`onAdImpression`）トラッキングは`AdropNativeAdView`に接続されているため引き続き動作しますが、動画関連シグナルは失われます。
</Warning>

### 推奨パターン

動画クリエイティブは`AdropNativeAdView`内部に配置した`WebView`でHTMLクリエイティブをレンダリングしてください。

```tsx theme={null}
{!nativeAd?.isVideoAd || nativeAd?.isBackfilled ? (
  <AdropMediaView style={styles.media} />
) : (
  <WebView
    source={{ html: nativeAd?.properties?.creative ?? '' }}
    style={styles.media}
    javaScriptEnabled
    mediaPlaybackRequiresUserAction={false}
    allowsInlineMediaPlayback
    scrollEnabled={false}
  />
)}
```

`AdropNativeAd`の`isVideoAd`と`isBackfilled`フラグを使用すると、asset URLを直接検査することなく、`<AdropMediaView />`（画像またはバックフィルクリエイティブ）と`<WebView />`（ダイレクト動画クリエイティブ）を分岐できます。

<Note>
  特定の面がどうしても独自プレイヤーを使う必要があり、VTRが計測されないことを許容する場合、広告を`AdropNativeAdView`にバインドしたままにすることで、クリックとインプレッションのアトリビューションは引き続き確保できます。ただしその面を社内レポートで**非VTRインベントリ**として分類し、SDKが計測した動画パフォーマンスと混在させないでください。
</Note>

***

## AdChoicesの位置調整

バックフィルネイティブ広告で、AdChoicesマークを表示するコーナーを指定できます。`AdropNativeAd`コンストラクタの3番目の引数として`preferredAdChoicesPosition`を渡してください。

```tsx theme={null}
import { AdropNativeAd, AdropAdChoicesPosition } from 'adrop-ads-react-native'

const nativeAd = new AdropNativeAd(
  'YOUR_UNIT_ID',
  false, // useCustomClick
  AdropAdChoicesPosition.bottomRight
)

nativeAd.listener = {
  onAdReceived: (ad) => console.log('受信完了'),
  onAdFailedToReceive: (ad, errorCode) => console.log('失敗', errorCode),
}

nativeAd.load()
```

| 値                                    | 説明        |
| ------------------------------------ | --------- |
| `AdropAdChoicesPosition.topLeft`     | 左上        |
| `AdropAdChoicesPosition.topRight`    | 右上（デフォルト） |
| `AdropAdChoicesPosition.bottomLeft`  | 左下        |
| `AdropAdChoicesPosition.bottomRight` | 右下        |

<Note>
  この設定はバックフィルネットワークに渡される希望位置のヒントで、バックフィルネイティブ広告にのみ適用されます — ダイレクト広告には影響しません。バックフィルネットワークがポリシー上別の位置に表示する場合があります。
</Note>

***

## 次のステップ

<CardGroup cols={2}>
  <Card title="バナー広告" icon="rectangle-ad" href="/ja/sdk/react-native/banner">
    バナー広告を実装する
  </Card>

  <Card title="インタースティシャル広告" icon="window-maximize" href="/ja/sdk/react-native/interstitial">
    インタースティシャル広告を実装する
  </Card>

  <Card title="ポップアップ広告" icon="up-right-from-square" href="/ja/sdk/react-native/popup">
    ポップアップ広告を実装する
  </Card>

  <Card title="リワード広告" icon="gift" href="/ja/sdk/react-native/rewarded">
    リワード広告を実装する
  </Card>
</CardGroup>
