> ## 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.

# Banner Ads

> Guide to implementing banner ads in React Native apps.

## Overview

Banner ads are rectangular ads displayed in a portion of the screen. They can be easily implemented using the `AdropBanner` component.

### Key Features

* Can be fixed at the top, bottom, or middle of the screen
* Support for image and video ads
* Support for automatic or manual ad loading
* Ad event handling through callbacks
* Provides ad metadata (creative ID, campaign ID, etc.)

<Note>
  Use test unit IDs in development: `PUBLIC_TEST_UNIT_ID_320_100` or `PUBLIC_TEST_UNIT_ID_320_50`
</Note>

***

## AdropBanner Component

### Props

<ParamField body="unitId" type="string" required>
  Unit ID created in the Ad Control Console
</ParamField>

<ParamField body="style" type="ViewStyle" required>
  Banner style (width and height required)
</ParamField>

<ParamField body="autoLoad" type="boolean" default="true">
  Whether to automatically load ads when the component is mounted
</ParamField>

<ParamField body="useCustomClick" type="boolean" default="false">
  Whether to use custom click handling. If set to `true`, the browser won't automatically open on ad click.
</ParamField>

<ParamField body="adSize" type="{ width: number; height: number } | null">
  Explicit ad size to request from the server. When `style.width` is a number, `adSize` is automatically derived from the style dimensions (`{ width: style.width, height: style.height }`). When `style.width` is a string (e.g., `'100%'`), `adSize` defaults to `null` and the SDK uses responsive sizing. You generally do not need to set this prop manually.
</ParamField>

<ParamField body="onAdReceived" type="(unitId: string, metadata?: AdropBannerMetadata) => void">
  Callback invoked when ad is successfully received
</ParamField>

<ParamField body="onAdClicked" type="(unitId: string, metadata?: AdropBannerMetadata) => void">
  Callback invoked when user clicks the ad
</ParamField>

<ParamField body="onAdImpression" type="(unitId: string, metadata?: AdropBannerMetadata) => void">
  Callback invoked when ad is displayed on screen
</ParamField>

<ParamField body="onAdFailedToReceive" type="(unitId: string, errorCode?: string) => void">
  Callback invoked when ad reception fails
</ParamField>

<ParamField body="onAdVideoStart" type="(unitId: string) => void">
  Callback invoked when a video ad starts playing
</ParamField>

<ParamField body="onAdVideoEnd" type="(unitId: string) => void">
  Callback invoked when a video ad finishes playing
</ParamField>

***

## Basic Usage

### Auto Load (Recommended)

Automatically load the ad when the component is mounted.

```typescript theme={null}
import React from 'react'
import { View, StyleSheet, Dimensions } from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

const App = () => {
  const screenWidth = Dimensions.get('window').width

  return (
    <View style={styles.container}>
      {/* Main content */}
      <View style={styles.content}>
        {/* ... */}
      </View>

      {/* Banner ad */}
      <AdropBanner
        unitId="YOUR_UNIT_ID"
        style={{ width: screenWidth, height: 80 }}
        onAdReceived={(unitId, metadata) => {
          console.log('Banner ad received successfully', unitId, metadata)
        }}
        onAdFailedToReceive={(unitId, errorCode) => {
          console.log('Banner ad failed to receive', unitId, errorCode)
        }}
      />
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  content: {
    flex: 1,
  },
})

export default App
```

***

## Manual Load Using Ref

You can load ads at the desired time using `ref`.

```typescript theme={null}
import React, { useRef } from 'react'
import { View, Button, StyleSheet, Dimensions } from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

interface AdropBannerRef {
  load: () => void
}

const App = () => {
  const bannerRef = useRef<AdropBannerRef>(null)
  const screenWidth = Dimensions.get('window').width

  const loadBanner = () => {
    bannerRef.current?.load()
  }

  return (
    <View style={styles.container}>
      <Button title="Load Banner Ad" onPress={loadBanner} />

      <AdropBanner
        ref={bannerRef}
        unitId="YOUR_UNIT_ID"
        style={{ width: screenWidth, height: 80 }}
        autoLoad={false}
        onAdReceived={(unitId, metadata) => {
          console.log('Banner ad received successfully', unitId, metadata)
        }}
        onAdFailedToReceive={(unitId, errorCode) => {
          console.log('Banner ad failed to receive', unitId, errorCode)
        }}
      />
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
})

export default App
```

***

## Callback Functions

### onAdReceived

Called when ad reception is successful.

```typescript theme={null}
const handleAdReceived = (unitId: string, metadata?: AdropBannerMetadata) => {
  console.log('Banner ad received successfully')
  console.log('Unit ID:', unitId)
  console.log('Creative ID:', metadata?.creativeId)
  console.log('Campaign ID:', metadata?.campaignId)
  console.log('Transaction ID:', metadata?.txId)
  console.log('Destination URL:', metadata?.destinationURL)

  // Handle actions such as hiding loading indicator
}
```

### onAdClicked

Called when user clicks the ad.

```typescript theme={null}
const handleAdClicked = (unitId: string, metadata?: AdropBannerMetadata) => {
  console.log('Banner ad clicked')
  console.log('Unit ID:', unitId)
  console.log('Destination URL:', metadata?.destinationURL)

  // Handle actions such as click analytics logging
}
```

### onAdImpression

Called when ad is displayed on screen.

```typescript theme={null}
const handleAdImpression = (unitId: string, metadata?: AdropBannerMetadata) => {
  console.log('Banner ad impression')
  console.log('Unit ID:', unitId)
  console.log('Creative ID:', metadata?.creativeId)

  // Handle actions such as impression analytics logging
}
```

### onAdFailedToReceive

Called when ad reception fails.

```typescript theme={null}
const handleAdFailedToReceive = (unitId: string, errorCode?: string) => {
  console.log('Banner ad failed to receive')
  console.log('Unit ID:', unitId)
  console.log('Error code:', errorCode)

  // Handle errors and display fallback content
  if (errorCode === AdropErrorCode.network) {
    console.log('Please check your network connection')
  } else if (errorCode === AdropErrorCode.adNoFill) {
    console.log('No ads available to display')
  }
}
```

### onAdVideoStart

Called when a video ad starts playing.

```typescript theme={null}
const handleAdVideoStart = (unitId: string) => {
  console.log('Video ad started playing')
  console.log('Unit ID:', unitId)
}
```

### onAdVideoEnd

Called when a video ad finishes playing.

```typescript theme={null}
const handleAdVideoEnd = (unitId: string) => {
  console.log('Video ad finished playing')
  console.log('Unit ID:', unitId)
}
```

***

## AdropBannerMetadata

Type for ad metadata.

```typescript theme={null}
type AdropBannerMetadata = {
  creativeId: string      // Creative ID
  txId: string           // Transaction ID
  campaignId: string     // Campaign ID
  destinationURL: string // Destination URL
  browserTarget: BrowserTarget // Browser target (EXTERNAL = 0, INTERNAL = 1)
}
```

This information can be useful for ad analytics, tracking, and reporting.

***

## Ad Sizes

Banner ads should have style dimensions that match the size set in the unit.

### Common Banner Sizes

| Size       | Usage         |
| ---------- | ------------- |
| 320 x 50   | Small banner  |
| 320 x 100  | Medium banner |
| 16:9 ratio | Video banner  |

### Using Fixed Size

```typescript theme={null}
<AdropBanner
  unitId="YOUR_UNIT_ID"
  style={{ width: 320, height: 100 }}
/>
```

### Fitting to Screen Width

```typescript theme={null}
import { Dimensions } from 'react-native'

const screenWidth = Dimensions.get('window').width

<AdropBanner
  unitId="YOUR_UNIT_ID"
  style={{ width: screenWidth, height: 80 }}
/>
```

### Using Responsive Size

```typescript theme={null}
<AdropBanner
  unitId="YOUR_UNIT_ID"
  style={{ width: '100%', height: 80 }}
/>
```

<Note>
  If `width` is set as a string (e.g., `'100%'`), it works responsively, but if set as a number, that value is passed to the ad server to request ads of appropriate size.
</Note>

***

## Test Unit IDs

Use the following test unit IDs during development and testing.

| Ad Type          | Test Unit ID                  | Size      |
| ---------------- | ----------------------------- | --------- |
| Banner (320x50)  | `PUBLIC_TEST_UNIT_ID_320_50`  | 320 x 50  |
| Banner (320x100) | `PUBLIC_TEST_UNIT_ID_320_100` | 320 x 100 |

### Usage Example

```typescript theme={null}
<AdropBanner
  unitId="PUBLIC_TEST_UNIT_ID_320_100"
  style={{ width: 320, height: 100 }}
/>
```

***

## Error Handling

Implement appropriate error handling when ad loading fails.

### Managing Error State

```typescript theme={null}
import React, { useState } from 'react'
import { View, Text, StyleSheet } from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

const App = () => {
  const [error, setError] = useState<string | null>(null)

  const handleAdReceived = () => {
    setError(null)
  }

  const handleAdFailedToReceive = (unitId: string, errorCode?: string) => {
    setError(errorCode || 'Unknown error')
  }

  return (
    <View style={styles.container}>
      <AdropBanner
        unitId="YOUR_UNIT_ID"
        style={{ width: 320, height: 100 }}
        onAdReceived={handleAdReceived}
        onAdFailedToReceive={handleAdFailedToReceive}
      />

      {error && (
        <Text style={styles.errorText}>
          Ad loading failed: {error}
        </Text>
      )}
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  errorText: {
    marginTop: 8,
    color: 'red',
  },
})

export default App
```

***

## Best Practices

### 1. Screen Visibility

Load ads when the banner is visible on screen.

```typescript theme={null}
import React, { useEffect, useRef } from 'react'
import { AppState } from 'react-native'

const App = () => {
  const bannerRef = useRef<{ load: () => void }>(null)
  const appState = useRef(AppState.currentState)

  useEffect(() => {
    const subscription = AppState.addEventListener('change', nextAppState => {
      if (
        appState.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        // Refresh ad when app returns to foreground
        bannerRef.current?.load()
      }
      appState.current = nextAppState
    })

    return () => {
      subscription.remove()
    }
  }, [])

  return (
    <AdropBanner
      ref={bannerRef}
      unitId="YOUR_UNIT_ID"
      style={{ width: 320, height: 100 }}
    />
  )
}
```

### 2. Loading Indicator

Improve user experience during ad loading.

```typescript theme={null}
import React, { useState } from 'react'
import { View, ActivityIndicator, StyleSheet } from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

const App = () => {
  const [loading, setLoading] = useState(true)

  return (
    <View style={styles.container}>
      {loading && (
        <ActivityIndicator
          style={styles.loader}
          size="small"
          color="#999"
        />
      )}

      <AdropBanner
        unitId="YOUR_UNIT_ID"
        style={{ width: 320, height: 100 }}
        onAdReceived={() => setLoading(false)}
        onAdFailedToReceive={() => setLoading(false)}
      />
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    position: 'relative',
  },
  loader: {
    position: 'absolute',
    top: '50%',
    left: '50%',
    transform: [{ translateX: -12 }, { translateY: -12 }],
  },
})
```

### 3. Managing Multiple Banners

Manage the state of each banner when using multiple banners.

```typescript theme={null}
import React, { useState } from 'react'
import { View, Text } from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

const App = () => {
  const [banner1Loaded, setBanner1Loaded] = useState(false)
  const [banner2Loaded, setBanner2Loaded] = useState(false)

  return (
    <View>
      <Text>Banner 1: {banner1Loaded ? 'Loaded' : 'Loading'}</Text>
      <AdropBanner
        unitId="UNIT_ID_1"
        style={{ width: 320, height: 100 }}
        onAdReceived={() => setBanner1Loaded(true)}
      />

      <Text>Banner 2: {banner2Loaded ? 'Loaded' : 'Loading'}</Text>
      <AdropBanner
        unitId="UNIT_ID_2"
        style={{ width: 320, height: 100 }}
        onAdReceived={() => setBanner2Loaded(true)}
      />
    </View>
  )
}
```

### 4. Custom Click Handling

Use `useCustomClick` to handle ad clicks directly.

```typescript theme={null}
import { Linking } from 'react-native'
import { AdropBanner, type AdropBannerMetadata } from 'adrop-ads-react-native'

const App = () => {
  const handleAdClicked = (unitId: string, metadata?: AdropBannerMetadata) => {
    console.log('Ad clicked:', unitId)

    // Custom analytics logging
    analytics.logEvent('ad_clicked', {
      unitId,
      campaignId: metadata?.campaignId,
    })

    // Manually open browser
    if (metadata?.destinationURL) {
      Linking.openURL(metadata.destinationURL)
    }
  }

  return (
    <AdropBanner
      unitId="YOUR_UNIT_ID"
      style={{ width: 320, height: 100 }}
      useCustomClick={true}
      onAdClicked={handleAdClicked}
    />
  )
}
```

***

## Complete Example

### TypeScript Example

```typescript theme={null}
import React, { useRef, useState } from 'react'
import {
  View,
  Text,
  Button,
  StyleSheet,
  Dimensions,
  ActivityIndicator,
} from 'react-native'
import { AdropBanner, type AdropBannerMetadata } from 'adrop-ads-react-native'

interface AdropBannerRef {
  load: () => void
}

const BannerExample = () => {
  const bannerRef = useRef<AdropBannerRef>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [metadata, setMetadata] = useState<AdropBannerMetadata | null>(null)

  const screenWidth = Dimensions.get('window').width

  const loadBanner = () => {
    setLoading(true)
    setError(null)
    bannerRef.current?.load()
  }

  const handleAdReceived = (unitId: string, metadata?: AdropBannerMetadata) => {
    console.log('✅ Banner ad received successfully')
    console.log('Unit ID:', unitId)
    console.log('Metadata:', metadata)

    setLoading(false)
    setError(null)
    if (metadata) {
      setMetadata(metadata)
    }
  }

  const handleAdClicked = (unitId: string, metadata?: AdropBannerMetadata) => {
    console.log('👆 Banner ad clicked')
    console.log('Unit ID:', unitId)
    console.log('Destination URL:', metadata?.destinationURL)
  }

  const handleAdImpression = (unitId: string, metadata?: AdropBannerMetadata) => {
    console.log('👁️ Banner ad impression')
    console.log('Unit ID:', unitId)
    console.log('Creative ID:', metadata?.creativeId)
  }

  const handleAdFailedToReceive = (unitId: string, errorCode?: string) => {
    console.log('❌ Banner ad failed to receive')
    console.log('Unit ID:', unitId)
    console.log('Error code:', errorCode)

    setLoading(false)
    setError(errorCode || 'Unknown error')
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Banner Ad Example</Text>

      <Button title="Load Banner Ad" onPress={loadBanner} />

      <View style={styles.bannerContainer}>
        {loading && (
          <ActivityIndicator
            style={styles.loader}
            size="small"
            color="#666"
          />
        )}

        <AdropBanner
          ref={bannerRef}
          unitId="YOUR_UNIT_ID"
          style={{ width: screenWidth, height: 80 }}
          autoLoad={false}
          onAdReceived={handleAdReceived}
          onAdClicked={handleAdClicked}
          onAdImpression={handleAdImpression}
          onAdFailedToReceive={handleAdFailedToReceive}
        />

        {error && (
          <View style={styles.errorContainer}>
            <Text style={styles.errorText}>Error: {error}</Text>
          </View>
        )}

        {metadata && (
          <View style={styles.metadataContainer}>
            <Text style={styles.metadataTitle}>Ad Metadata:</Text>
            <Text style={styles.metadataText}>
              Creative ID: {metadata.creativeId}
            </Text>
            <Text style={styles.metadataText}>
              Campaign ID: {metadata.campaignId}
            </Text>
            <Text style={styles.metadataText}>
              Transaction ID: {metadata.txId}
            </Text>
          </View>
        )}
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    marginVertical: 50,
    paddingHorizontal: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  bannerContainer: {
    marginTop: 20,
    position: 'relative',
    width: '100%',
  },
  loader: {
    position: 'absolute',
    top: 40,
    left: '50%',
    transform: [{ translateX: -12 }],
    zIndex: 1,
  },
  errorContainer: {
    marginTop: 8,
    padding: 8,
    backgroundColor: '#ffebee',
    borderRadius: 4,
  },
  errorText: {
    color: '#c62828',
    textAlign: 'center',
  },
  metadataContainer: {
    marginTop: 12,
    padding: 12,
    backgroundColor: '#f5f5f5',
    borderRadius: 4,
  },
  metadataTitle: {
    fontSize: 14,
    fontWeight: 'bold',
    marginBottom: 4,
  },
  metadataText: {
    fontSize: 12,
    color: '#666',
    marginTop: 2,
  },
})

export default BannerExample
```

### JavaScript Example

```javascript theme={null}
import React, { useRef, useState } from 'react'
import {
  View,
  Text,
  Button,
  StyleSheet,
  Dimensions,
  ActivityIndicator,
} from 'react-native'
import { AdropBanner } from 'adrop-ads-react-native'

const BannerExample = () => {
  const bannerRef = useRef(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)

  const screenWidth = Dimensions.get('window').width

  const loadBanner = () => {
    setLoading(true)
    setError(null)
    bannerRef.current?.load()
  }

  const handleAdReceived = (unitId, metadata) => {
    console.log('Banner ad received successfully', unitId, metadata)
    setLoading(false)
    setError(null)
  }

  const handleAdFailedToReceive = (unitId, errorCode) => {
    console.log('Banner ad failed to receive', unitId, errorCode)
    setLoading(false)
    setError(errorCode || 'Unknown error')
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Banner Ad Example</Text>

      <Button title="Load Banner Ad" onPress={loadBanner} />

      <View style={styles.bannerContainer}>
        {loading && <ActivityIndicator style={styles.loader} />}

        <AdropBanner
          ref={bannerRef}
          unitId="YOUR_UNIT_ID"
          style={{ width: screenWidth, height: 80 }}
          autoLoad={false}
          onAdReceived={handleAdReceived}
          onAdFailedToReceive={handleAdFailedToReceive}
        />

        {error && (
          <Text style={styles.errorText}>Error: {error}</Text>
        )}
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    marginVertical: 50,
    paddingHorizontal: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  bannerContainer: {
    marginTop: 20,
    width: '100%',
  },
  loader: {
    marginVertical: 20,
  },
  errorText: {
    marginTop: 8,
    color: 'red',
    textAlign: 'center',
  },
})

export default BannerExample
```

***

## Backfill Ads

<Info>To use backfill ads, you must have the backfill dependency added to your native platforms (Android/iOS).</Info>

When backfill ads are enabled, the SDK automatically falls back to backfill ads when no direct ad is available. You can handle backfill-specific error codes in the `onAdFailedToReceive` callback.

```tsx theme={null}
<AdropBanner
  unitId="YOUR_UNIT_ID"
  onAdReceived={(unitId, metadata) => {
    console.log('Ad loaded:', metadata?.creativeId)
  }}
  onAdFailedToReceive={(unitId, errorCode) => {
    switch (errorCode) {
      case AdropErrorCode.adNoFill:
        console.log('No direct ad available, requesting backfill...')
        break
      case AdropErrorCode.backfillNoFill:
        console.log('No backfill ad available either')
        break
      default:
        console.log('Ad load failed:', errorCode)
    }
  }}
/>
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Native Ads" href="/sdk/react-native/native">
    Implement customizable native ads for your UI
  </Card>

  <Card title="Interstitial Ads" href="/sdk/react-native/interstitial">
    Implement full-screen interstitial ads
  </Card>

  <Card title="Popup Ads" href="/sdk/react-native/popup">
    Implement ads displayed in popup format
  </Card>

  <Card title="Reference" href="/sdk/react-native/reference">
    Reference types, methods, and error codes
  </Card>
</CardGroup>
