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

# Popup Ads

> Learn how to implement popup ads in your Flutter app.

## Overview

Popup ads are displayed as a popup at the center or bottom of the screen. They support a "Don't show today" feature to improve user experience.

### Key Features

* Selectable center or bottom position
* "Don't show today" feature support
* Customizable button colors
* Image ad support

<Note>
  Use test unit IDs in development environment:

  * Bottom: `PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM`
  * Center: `PUBLIC_TEST_UNIT_ID_POPUP_CENTER`
</Note>

***

## AdropPopupAd

### Constructor

```dart theme={null}
AdropPopupAd({
  required String unitId,
  AdropPopupListener? listener,
  Color? closeTextColor,
  Color? hideForTodayTextColor,
  Color? backgroundColor,
})
```

**Parameters**

| Parameter               | Type                 | Required | Description                           |
| ----------------------- | -------------------- | -------- | ------------------------------------- |
| `unitId`                | `String`             | Y        | Unit ID created in Ad Control Console |
| `listener`              | `AdropPopupListener` | N        | Ad event listener                     |
| `closeTextColor`        | `Color`              | N        | Close button text color               |
| `hideForTodayTextColor` | `Color`              | N        | "Don't show today" button text color  |
| `backgroundColor`       | `Color`              | N        | Button background color               |

### Properties

| Property         | Type             | Description                           |
| ---------------- | ---------------- | ------------------------------------- |
| `isLoaded`       | `bool`           | Whether ad is loaded                  |
| `unitId`         | `String`         | Ad unit ID                            |
| `creativeId`     | `String`         | Creative ID                           |
| `txId`           | `String`         | Transaction ID                        |
| `campaignId`     | `String`         | Campaign ID                           |
| `destinationURL` | `String`         | Destination URL                       |
| `browserTarget`  | `BrowserTarget?` | Browser target (external or internal) |

### Methods

| Method      | Return Type    | Description            |
| ----------- | -------------- | ---------------------- |
| `load()`    | `Future<void>` | Loads the ad           |
| `show()`    | `Future<void>` | Shows the ad on screen |
| `close()`   | `Future<void>` | Closes the ad          |
| `dispose()` | `Future<void>` | Releases resources     |

***

## Basic Usage

```dart theme={null}
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

class PopupExample extends StatefulWidget {
  const PopupExample({super.key});

  @override
  State<PopupExample> createState() => _PopupExampleState();
}

class _PopupExampleState extends State<PopupExample> {
  bool isLoaded = false;
  AdropPopupAd? popupAd;

  @override
  void initState() {
    super.initState();
    _createPopupAd();
  }

  void _createPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          debugPrint('Popup ad loaded successfully: ${ad.creativeId}');
          setState(() {
            isLoaded = true;
          });
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('Popup ad failed to load: $errorCode');
        },
        onAdClicked: (ad) {
          debugPrint('Popup ad clicked');
        },
        onAdImpression: (ad) {
          debugPrint('Popup ad impression');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('Popup ad presented');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('Popup ad dismissed');
        },
        onAdFailedToShowFullScreen: (ad, errorCode) {
          debugPrint('Popup ad failed to show: $errorCode');
        },
      ),
    );
  }

  void loadAd() {
    popupAd?.load();
  }

  void showAd() {
    if (isLoaded) {
      popupAd?.show();
    }
  }

  @override
  void dispose() {
    popupAd?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Popup Ad Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: loadAd,
              child: const Text('Load Ad'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: isLoaded ? showAd : null,
              child: const Text('Show Ad'),
            ),
          ],
        ),
      ),
    );
  }
}
```

***

## AdropPopupListener

Listener for handling popup ad events.

### Callbacks

```dart theme={null}
AdropPopupListener(
  onAdReceived: (AdropAd ad) {
    // Ad loaded successfully
  },
  onAdClicked: (AdropAd ad) {
    // Ad clicked
  },
  onAdImpression: (AdropAd ad) {
    // Ad impression
  },
  onAdWillPresentFullScreen: (AdropAd ad) {
    // Just before ad is presented (iOS only)
  },
  onAdDidPresentFullScreen: (AdropAd ad) {
    // Ad presented
  },
  onAdWillDismissFullScreen: (AdropAd ad) {
    // Just before ad is dismissed (iOS only)
  },
  onAdDidDismissFullScreen: (AdropAd ad) {
    // Ad dismissed
  },
  onAdFailedToReceive: (AdropAd ad, AdropErrorCode errorCode) {
    // Ad failed to load
  },
  onAdFailedToShowFullScreen: (AdropAd ad, AdropErrorCode errorCode) {
    // Ad failed to show
  },
  onAdVideoStart: (AdropAd ad) {
    // Video ad started playing
  },
  onAdVideoEnd: (AdropAd ad) {
    // Video ad finished playing
  },
)
```

### Callback Descriptions

| Callback                     | Description                                   |
| ---------------------------- | --------------------------------------------- |
| `onAdReceived`               | Called when ad loads successfully             |
| `onAdClicked`                | Called when ad is clicked                     |
| `onAdImpression`             | Called when ad is shown                       |
| `onAdWillPresentFullScreen`  | Called just before ad is presented (iOS only) |
| `onAdDidPresentFullScreen`   | Called after ad is presented                  |
| `onAdWillDismissFullScreen`  | Called just before ad is dismissed (iOS only) |
| `onAdDidDismissFullScreen`   | Called after ad is dismissed                  |
| `onAdFailedToReceive`        | Called when ad fails to load                  |
| `onAdFailedToShowFullScreen` | Called when ad fails to show                  |
| `onAdVideoStart`             | Called when video ad starts playing           |
| `onAdVideoEnd`               | Called when video ad finishes playing         |

***

## Button Color Customization

You can customize the colors of the close button and "Don't show today" button.

```dart theme={null}
popupAd = AdropPopupAd(
  unitId: 'YOUR_UNIT_ID',
  // Close button text color
  closeTextColor: Colors.white,
  // "Don't show today" button text color
  hideForTodayTextColor: Colors.white,
  // Button background color
  backgroundColor: Colors.black87,
  listener: AdropPopupListener(
    onAdReceived: (ad) {
      setState(() {
        isLoaded = true;
      });
    },
  ),
);
```

### Color Options

| Parameter               | Description                          | Default        |
| ----------------------- | ------------------------------------ | -------------- |
| `closeTextColor`        | Close button text color              | System default |
| `hideForTodayTextColor` | "Don't show today" button text color | System default |
| `backgroundColor`       | Button background color              | System default |

***

## Popup Position

The popup position is configured when creating the unit in the Ad Control Console.

### Center Popup

The popup is displayed at the center of the screen. Suitable for announcements and event notifications.

```dart theme={null}
// Use center popup unit ID
popupAd = AdropPopupAd(
  unitId: 'YOUR_CENTER_POPUP_UNIT_ID',
  listener: AdropPopupListener(...),
);
```

### Bottom Popup

The popup is displayed at the bottom of the screen. Suitable for banner-style notifications on app launch.

```dart theme={null}
// Use bottom popup unit ID
popupAd = AdropPopupAd(
  unitId: 'YOUR_BOTTOM_POPUP_UNIT_ID',
  listener: AdropPopupListener(...),
);
```

***

## Don't Show Today

When a user selects "Don't show today", the ad will not be shown on that device until midnight.

<Note>
  When loading an ad in "Don't show today" state, the `adHideForToday` error is returned.
</Note>

```dart theme={null}
onAdFailedToReceive: (ad, errorCode) {
  if (errorCode == AdropErrorCode.adHideForToday) {
    debugPrint('User selected don\'t show today.');
    // Display alternative content instead of ad
  }
}
```

***

## Ad Recreation

Popup ads are one-time use. Once shown, they cannot be shown again, so you must recreate the instance to load a new ad.

```dart theme={null}
class _PopupState extends State<PopupWidget> {
  bool isLoaded = false;
  bool isShown = false;
  AdropPopupAd? popupAd;

  @override
  void initState() {
    super.initState();
    _createPopupAd();
  }

  void _createPopupAd() {
    popupAd?.dispose();
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      backgroundColor: Colors.black87,
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          setState(() {
            isLoaded = true;
          });
        },
        onAdDidDismissFullScreen: (ad) {
          setState(() {
            isShown = true;
          });
          // Prepare new ad for next show
          _createPopupAd();
          popupAd?.load();
        },
      ),
    );

    setState(() {
      isLoaded = false;
      isShown = false;
    });
  }

  @override
  void dispose() {
    popupAd?.dispose();
    super.dispose();
  }
}
```

***

## Error Handling

```dart theme={null}
class _PopupState extends State<PopupWidget> {
  bool isLoaded = false;
  AdropErrorCode? errorCode;
  AdropPopupAd? popupAd;

  void _createPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          setState(() {
            isLoaded = true;
            errorCode = null;
          });
        },
        onAdFailedToReceive: (ad, error) {
          setState(() {
            isLoaded = false;
            errorCode = error;
          });
          _handleError(error);
        },
        onAdFailedToShowFullScreen: (ad, error) {
          setState(() {
            errorCode = error;
          });
          _handleError(error);
        },
      ),
    );
  }

  void _handleError(AdropErrorCode error) {
    switch (error) {
      case AdropErrorCode.network:
        debugPrint('Network error occurred.');
        break;
      case AdropErrorCode.adNoFill:
        debugPrint('No ads available.');
        break;
      case AdropErrorCode.adHideForToday:
        debugPrint('User selected don\'t show today.');
        break;
      case AdropErrorCode.adShown:
        debugPrint('Ad already shown.');
        break;
      default:
        debugPrint('Error occurred: ${error.code}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: popupAd?.load,
          child: const Text('Load Ad'),
        ),
        ElevatedButton(
          onPressed: isLoaded ? popupAd?.show : null,
          child: const Text('Show Ad'),
        ),
        if (errorCode != null)
          Text(
            'Error: ${errorCode?.code}',
            style: const TextStyle(color: Colors.red),
          ),
      ],
    );
  }
}
```

***

## Best Practices

### 1. Show Popup on App Launch

Display announcements or events as a popup when the app launches.

```dart theme={null}
class SplashScreen extends StatefulWidget {
  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  AdropPopupAd? popupAd;

  @override
  void initState() {
    super.initState();
    _loadPopupAd();
  }

  void _loadPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          // Show ad when loaded
          popupAd?.show();
        },
        onAdFailedToReceive: (ad, errorCode) {
          // Navigate to main screen if ad load fails
          if (errorCode != AdropErrorCode.adHideForToday) {
            _navigateToMain();
          }
        },
        onAdDidDismissFullScreen: (ad) {
          // Navigate to main screen after popup is dismissed
          _navigateToMain();
        },
      ),
    );
    popupAd?.load();
  }

  void _navigateToMain() {
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const MainScreen()),
    );
  }

  @override
  void dispose() {
    popupAd?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
}
```

### 2. Use Theme-Matched Colors

Set button colors to match your app's theme.

```dart theme={null}
void _createPopupAd() {
  final isDarkMode = Theme.of(context).brightness == Brightness.dark;

  popupAd = AdropPopupAd(
    unitId: 'YOUR_UNIT_ID',
    closeTextColor: isDarkMode ? Colors.white : Colors.black,
    hideForTodayTextColor: isDarkMode ? Colors.white70 : Colors.black54,
    backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[200],
    listener: AdropPopupListener(...),
  );
}
```

### 3. Resource Management

Always dispose of unused ad instances.

```dart theme={null}
@override
void dispose() {
  popupAd?.dispose();
  super.dispose();
}
```

***

## Complete Example

```dart theme={null}
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

class PopupAdPage extends StatefulWidget {
  const PopupAdPage({super.key});

  @override
  State<PopupAdPage> createState() => _PopupAdPageState();
}

class _PopupAdPageState extends State<PopupAdPage> {
  bool isLoaded = false;
  bool isLoading = false;
  bool isShown = false;
  AdropErrorCode? errorCode;
  AdropPopupAd? popupAd;

  @override
  void initState() {
    super.initState();
    _createPopupAd();
  }

  void _createPopupAd() {
    popupAd?.dispose();
    popupAd = AdropPopupAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM', // Test unit ID
      closeTextColor: Colors.white,
      hideForTodayTextColor: Colors.white70,
      backgroundColor: Colors.black87,
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          debugPrint('Ad loaded successfully');
          debugPrint('Creative ID: ${ad.creativeId}');
          debugPrint('Campaign ID: ${ad.campaignId}');
          setState(() {
            isLoaded = true;
            isLoading = false;
            errorCode = null;
          });
        },
        onAdClicked: (ad) {
          debugPrint('Ad clicked: ${ad.destinationURL}');
        },
        onAdImpression: (ad) {
          debugPrint('Ad impression: ${ad.creativeId}');
        },
        onAdWillPresentFullScreen: (ad) {
          debugPrint('Ad will present');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('Ad presented');
        },
        onAdWillDismissFullScreen: (ad) {
          debugPrint('Ad will dismiss');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('Ad dismissed');
          setState(() {
            isShown = true;
          });
        },
        onAdFailedToReceive: (ad, error) {
          debugPrint('Ad failed to load: $error');
          setState(() {
            isLoaded = false;
            isLoading = false;
            errorCode = error;
          });
        },
        onAdFailedToShowFullScreen: (ad, error) {
          debugPrint('Ad failed to show: $error');
          setState(() {
            errorCode = error;
          });
        },
      ),
    );

    setState(() {
      isLoaded = false;
      isShown = false;
      errorCode = null;
    });
  }

  void loadAd() {
    setState(() {
      isLoading = true;
      errorCode = null;
    });
    popupAd?.load();
  }

  void showAd() {
    if (isLoaded) {
      popupAd?.show();
    }
  }

  @override
  void dispose() {
    popupAd?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Popup Ad Example'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // Load button
              ElevatedButton(
                onPressed: isLoading ? null : loadAd,
                child: Text(isLoading ? 'Loading...' : 'Load Ad'),
              ),
              const SizedBox(height: 16),

              // Show button
              ElevatedButton(
                onPressed: isLoaded ? showAd : null,
                child: const Text('Show Ad'),
              ),
              const SizedBox(height: 16),

              // Reset button
              TextButton(
                onPressed: (isShown || errorCode != null)
                    ? () => _createPopupAd()
                    : null,
                child: const Text('Reset'),
              ),
              const SizedBox(height: 24),

              // Status display
              Text('Loaded: ${isLoaded ? "Yes" : "No"}'),
              Text('Shown: ${isShown ? "Yes" : "No"}'),

              // Error display
              if (errorCode != null) ...[
                const SizedBox(height: 16),
                Text(
                  'Error: ${errorCode?.code}',
                  style: const TextStyle(color: Colors.red),
                ),
                if (errorCode == AdropErrorCode.adHideForToday)
                  const Text(
                    '(User selected don\'t show today)',
                    style: TextStyle(color: Colors.grey, fontSize: 12),
                  ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}
```

***

## Backfill Ads

When backfill ads are enabled, backfill ads are automatically loaded when direct ads are unavailable. You can handle backfill-related errors using the error code.

```dart theme={null}
popupAd = AdropPopupAd(
  unitId: 'YOUR_UNIT_ID',
  listener: AdropPopupListener(
    onAdReceived: (ad) {
      debugPrint('Ad loaded: ${ad.creativeId}');
    },
    onAdFailedToReceive: (ad, errorCode) {
      switch (errorCode) {
        case AdropErrorCode.adNoFill:
          debugPrint('No direct ad available');
          break;
        case AdropErrorCode.backfillNoFill:
          debugPrint('No backfill ad available either');
          break;
        default:
          debugPrint('Ad load failed: ${errorCode.code}');
      }
    },
  ),
);
```

<Note>
  To use backfill ads, add the backfill dependency to native platforms. See [Getting Started](/sdk/flutter/overview).
</Note>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Targeting" href="/sdk/flutter/targeting">
    Set up targeting for personalized ads
  </Card>

  <Card title="Reference" href="/sdk/flutter/reference">
    Reference types, methods, and error codes
  </Card>

  <Card title="Examples" href="/sdk/flutter/examples">
    Explore various implementation examples
  </Card>
</CardGroup>
