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

> Learn how to implement banner ads using CDN.

## Implementation Methods

Banner ads can be easily implemented using HTML attributes only. Ads are automatically requested when the ad placement is rendered, without any function calls.

<Note>
  Use the test unit ID in development: `PUBLIC_TEST_UNIT_ID_320_100`
</Note>

***

## Data Attributes Method

Just add the `data-adrop-unit` attribute and the SDK will automatically load the ad.

```html theme={null}
<div
  data-adrop-unit="YOUR_UNIT_ID"
  data-adrop-context-id="YOUR_CONTEXT_ID"
  data-adrop-theme="light"
  data-adrop-custom-click="true">
</div>
```

### Data Attributes

<ParamField body="data-adrop-unit" type="string" required>
  Unit ID created in Ad Control Console
</ParamField>

<ParamField body="data-adrop-context-id" type="string">
  Context ID for [Contextual Targeting](/sdk/web/cdn-targeting#contextual-targeting)
</ParamField>

<ParamField body="data-adrop-theme" type="string" default="light">
  Theme setting (`light` or `dark`) - See [Dark Mode Settings](/ad-unit/dark-mode)
</ParamField>

<ParamField body="data-adrop-custom-click" type="boolean" default={false}>
  Enable custom click handling - When `true`, SDK will not automatically navigate to the destination URL on click, only emit `adClicked` event. Allows developers to implement custom click behavior.
</ParamField>

<ParamField body="data-adrop-backfill-mode" type="string" default="responsive">
  Backfill ad rendering mode (`responsive` or `fixed`). See the [Backfill Rendering Mode](/sdk/web/backfill) guide for details. (SDK 1.2.3+)
</ParamField>

<ParamField body="data-adrop-ad-id" type="string">
  Advertising identifier — required for the **View on Device** feature to preview a draft creative on a registered test device. Do not hard-code in production.
</ParamField>

### Refreshing Ads

Create a new ad placement DOM and replace the existing DOM to request a new ad.

```javascript theme={null}
const container = document.getElementById('ad-wrapper');
const newAd = document.createElement('div');
newAd.setAttribute('data-adrop-unit', 'YOUR_UNIT_ID');
Adrop.instance().clear(container);
container.appendChild(newAd);
```

***

## renderAd Method

Use this when you want direct control over ad loading timing.

```html theme={null}
<div id="ad-container"></div>

<script>
  const container = document.getElementById('ad-container');
  const adrop = Adrop.instance();

  adrop.renderAd(container, {
    unit: 'YOUR_UNIT_ID',
    contextId: 'YOUR_CONTEXT_ID',
    theme: 'light',
    useCustomClick: true  // Enable custom click handling
  });
</script>
```

### renderAd Options

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

<ParamField body="uid" type="string">
  User identifier (used to override SDK-level setting for individual placements)
</ParamField>

<ParamField body="contextId" type="string">
  Context ID for [Contextual Targeting](/sdk/web/cdn-targeting#contextual-targeting)
</ParamField>

<ParamField body="theme" type="string" default="light">
  Theme setting (`light` or `dark`) - See [Dark Mode Settings](/ad-unit/dark-mode)
</ParamField>

<ParamField body="useCustomClick" type="boolean" default={false}>
  Enable custom click handling - When `true`, SDK will not automatically navigate to the destination URL on click, only emit `adClicked` event with destination URL. Allows developers to implement custom click behavior.
</ParamField>

<ParamField body="backfillMode" type="'responsive' | 'fixed'" default="responsive">
  Backfill ad rendering mode. See the [Backfill Rendering Mode](/sdk/web/backfill) guide for details. (SDK 1.2.3+)
</ParamField>

<ParamField body="adId" type="string">
  Advertising identifier — required for the **View on Device** feature to preview a draft creative on a registered test device. Do not hard-code in production.
</ParamField>

### Refreshing Ads

Call `renderAd()` again to request a new ad.

```javascript theme={null}
const container = document.getElementById('ad-container');
Adrop.instance().renderAd(container, {
  unit: 'YOUR_UNIT_ID'
});
```

### Removing Ads

Call `clear()` to remove the ad from the container.

```javascript theme={null}
const container = document.getElementById('ad-container');
Adrop.instance().clear(container);
```

***

## Ad Size

Recommended: responsive width + `aspect-ratio` matching the registered unit size. The slot scales with the device width and the height is locked by the ratio (no CLS).

```html theme={null}
<div
  data-adrop-unit="YOUR_UNIT_ID"
  data-adrop-backfill-mode="fixed"
  style="width: 100%; aspect-ratio: 320 / 100;">
</div>
```

Fixed pixel size is also supported when pixel-precise alignment is required.

```html theme={null}
<div
  data-adrop-unit="YOUR_UNIT_ID"
  style="width: 320px; height: 100px;">
</div>
```

| Type         | Size Setting                                                                              | Alignment                  |
| ------------ | ----------------------------------------------------------------------------------------- | -------------------------- |
| Direct Ads   | Responsive support, height required                                                       | Horizontal/Vertical center |
| Backfill Ads | Auto-matched to container width (`responsive`) or stretched to container height (`fixed`) | Horizontal center          |

<Note>
  For container sizing patterns and how to choose a backfill rendering mode, see the [Backfill Rendering Mode](/sdk/web/backfill) guide.
</Note>

***

## Event Handling

You can detect ad status changes and handle the UI appropriately.

```html theme={null}
<script>
  const adrop = Adrop.instance();

  // Ad received successfully
  function handleReceived(unit, adData) {
    console.log('Ad received:', unit);
  }

  // No direct ads available
  function handleNoFill(unit) {
    console.warn('No ad available:', unit);
  }

  // Request failed
  function handleFailed(unit) {
    console.error('Ad failed:', unit);
  }

  // Impression
  function handleImpression(unit, adData) {
    console.log('Ad impression:', unit);
  }

  // Click
  function handleClicked(unit, adData) {
    console.log('Ad clicked:', unit);
  }

  // No backfill ad available
  function handleBackfillNoFill(unit) {
    console.warn('No backfill ad:', unit);
  }

  // Video playback started
  function handleVideoStart(unit, adData) {
    console.log('Video started:', unit);
  }

  // Video playback ended
  function handleVideoEnd(unit, adData) {
    console.log('Video ended:', unit);
  }

  // Filter for specific unit only
  const filter = { unit: 'YOUR_UNIT_ID' };

  adrop.on(Adrop.Events.AD_RECEIVED, handleReceived, filter);
  adrop.on(Adrop.Events.AD_NO_FILL, handleNoFill, filter);
  adrop.on(Adrop.Events.AD_FAILED, handleFailed, filter);
  adrop.on(Adrop.Events.AD_IMPRESSION, handleImpression, filter);
  adrop.on(Adrop.Events.AD_CLICKED, handleClicked, filter);
  adrop.on(Adrop.Events.AD_BACKFILL_NO_FILL, handleBackfillNoFill, filter);
  adrop.on(Adrop.Events.AD_VIDEO_START, handleVideoStart, filter);
  adrop.on(Adrop.Events.AD_VIDEO_END, handleVideoEnd, filter);
</script>
```

### Supported Events

| Event          | Constant              | Description               |
| -------------- | --------------------- | ------------------------- |
| Ad Received    | `AD_RECEIVED`         | Ad request successful     |
| No Ad          | `AD_NO_FILL`          | No direct ads available   |
| Request Failed | `AD_FAILED`           | Ad request failed         |
| Impression     | `AD_IMPRESSION`       | Ad impression recorded    |
| Click          | `AD_CLICKED`          | User clicked the ad       |
| No Backfill    | `AD_BACKFILL_NO_FILL` | No backfill ad available  |
| Video Start    | `AD_VIDEO_START`      | Video ad playback started |
| Video End      | `AD_VIDEO_END`        | Video ad playback ended   |

### Removing Event Listeners

Remove event listeners using `off()` when no longer needed.

```javascript theme={null}
adrop.off(Adrop.Events.AD_RECEIVED, handleReceived);
```

### AdData

Ad data passed to event handlers. See [Reference > AdData](/sdk/web/reference#addata) for detailed field information.

***

## Custom Click Handling

When `useCustomClick` is enabled, the SDK will not automatically navigate to the destination URL. Instead, you can handle the click event and implement custom behavior.

```html theme={null}
<script>
  const adrop = Adrop.instance();
  
  // Handle ad click with custom behavior
  function handleCustomClick(unit, adData) {
    console.log('Ad clicked:', unit);
    console.log('Destination URL:', adData.destinationURL);
    
    // Implement custom click behavior
    // For example: show confirmation dialog, track analytics, etc.
    const userConfirmed = confirm('Do you want to visit the advertiser page?');
    if (userConfirmed && adData.destinationURL) {
      window.open(adData.destinationURL, '_blank');
    }
  }
  
  // Register click handler
  adrop.on(Adrop.Events.AD_CLICKED, handleCustomClick);
  
  // Render ad with custom click enabled
  const container = document.getElementById('ad-container');
  adrop.renderAd(container, {
    unit: 'YOUR_UNIT_ID',
    useCustomClick: true
  });
</script>
```

<Note>
  With custom click handling enabled, you have full control over what happens when users click the ad. The `destinationURL` is provided in the `adClicked` event data.
</Note>

***

## Complete Example

```html theme={null}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Banner Ad Example</title>
</head>
<body>
  <header>
    <!-- Header banner ad -->
    <div
      data-adrop-unit="HEADER_BANNER_UNIT_ID"
      style="width: 100%; height: 80px;">
    </div>
  </header>

  <main>
    <h1>Content</h1>
  </main>

  <footer>
    <!-- Footer banner ad -->
    <div
      data-adrop-unit="FOOTER_BANNER_UNIT_ID"
      data-adrop-theme="dark"
      style="width: 320px; height: 100px;">
    </div>
  </footer>

  <script src="https://cdn.jsdelivr.net/npm/@adrop/ads-web-sdk@latest/dist/adrop-ads.min.js"></script>
  <script>
    const adrop = Adrop.observe({
      appId: 'YOUR_APP_ID',
      debug: true
    });

    adrop.on(Adrop.Events.AD_CLICKED, function(unit, adData) {
      console.log('Ad clicked:', unit);
    });
  </script>
</body>
</html>
```
