AdMoai Flutter SDK

pub package Platform Dart Flutter Conventional Commits

AdMoai Flutter SDK is a cross-platform advertising solution that enables seamless integration of native and video ads into Flutter applications. The SDK provides a robust API for requesting and displaying various ad formats with advanced targeting capabilities.

Features

  • Native Ads - Multiple template types (wide, image+text, text-only, carousel)
  • Video Ads - JSON, VAST Tag, and VAST XML delivery methods, with Format.video placement filter
  • Rich Targeting - Geo, current-location, destination, and custom key-value targeting
  • GDPR Compliance - Built-in user consent management
  • Event Tracking - Impressions, clicks, video quartiles, and custom events
  • Open Measurement - Pass-through support for third-party verification scripts (IAS, DoubleVerify, …)
  • Flexible Templates - Customizable ad layouts and formats
  • Locale-aware - defaultLanguage config propagates Accept-Language on every request
  • Configurable transport - Per-knob timeouts (request / connect / receive) and pluggable http.Client
  • Per-Request Control - Override user/device data collection per request

Requirements

  • Flutter 3.0+
  • Dart 3.0+
  • iOS 14.0+ / Android API 21+

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  admoai: ^0.3.0

Then run:

flutter pub get

Quick Start

1. Initialize the SDK

final config = SDKConfig(
  baseUrl: "https://api.admoai.com",
  apiVersion: "2025-11-01",
);

final sdk = await AdMoai.initialize(config: config);

2. Configure User Settings (Optional)

sdk.setUserConfig(
  id: "user_123",
  ip: "203.0.113.1",
  timezone: "UTC",
  consent: Consent(gdpr: true),
);

3. Build and Send a Request

final request = sdk.createRequestBuilder()
    .addPlacement(key: "home")
    .addPlacement(key: "promotions", format: Format.native)
    .addGeoTargeting(2643743)
    .addCustomTargeting(key: "category", value: "news")
    .build();

final response = await sdk.requestAds(request);

response.body.data?.forEach((decision) {
  decision.creatives?.forEach((creative) {
    // Render creative
  });
});

4. Extract Content

final headline = creative.contents.getContent(key: "headline")?.value;
final imageUrl = creative.contents.getContent(key: "coverImage")?.value;
final videoAsset = creative.contents.getContent(key: "video_asset")?.value;

5. Track Events

// Impressions
sdk.fireImpression(tracking: creative.tracking);

// Clicks
sdk.fireClick(tracking: creative.tracking);

// Video quartiles
sdk.fireVideoEvent(tracking: creative.tracking, key: "start");
sdk.fireVideoEvent(tracking: creative.tracking, key: "first_quartile");
sdk.fireVideoEvent(tracking: creative.tracking, key: "midpoint");
sdk.fireVideoEvent(tracking: creative.tracking, key: "third_quartile");
sdk.fireVideoEvent(tracking: creative.tracking, key: "complete");

// Custom events
sdk.fireCustom(tracking: creative.tracking, key: "companionOpened");

6. Clean Up on Logout

sdk.clearUserConfig();
sdk.clearDeviceConfig();
sdk.clearAppConfig();

Configuration Reference

SDKConfig

Parameter Type Default Description
baseUrl String Required Decision Engine API endpoint
apiVersion String? null API version (e.g., "2025-11-01")
logger Logger SDK default Custom logger instance

Video Ad Support

The SDK supports three video delivery methods:

Delivery Response Field Tracking
JSON video_asset content key SDK methods (fireVideoEvent)
VAST Tag vast.tagUrl Manual HTTP GET
VAST XML vast.xmlBase64 Manual HTTP GET

Detecting Video Ads

creative.isJsonDelivery()
creative.isVastTagDelivery()
creative.isVastXmlDelivery()

final videoUrl = creative.contents.getContent(key: "video_asset")?.value;
final vastTagUrl = creative.getVastTagUrl();
final vastXmlBase64 = creative.getVastXmlBase64();

Video Tracking Events

Important: Always fire the impression event first when the ad is displayed, then fire video-specific events as playback progresses.

Event When to Fire Key
Impression Ad displayed (before playback) default
Start Video begins playing (0%) start
First Quartile 25% progress first_quartile
Midpoint 50% progress midpoint
Third Quartile 75% progress third_quartile
Complete Video ends (98%) complete
Skip User skips skip
sdk.fireImpression(tracking: creative.tracking);
sdk.fireVideoEvent(tracking: creative.tracking, key: "start");
sdk.fireVideoEvent(tracking: creative.tracking, key: "first_quartile");
sdk.fireVideoEvent(tracking: creative.tracking, key: "midpoint");
sdk.fireVideoEvent(tracking: creative.tracking, key: "third_quartile");
sdk.fireVideoEvent(tracking: creative.tracking, key: "complete");

Video Helper Methods

final isSkippable = creative.isSkippable();
final skipOffset = creative.getSkipOffset();

Event Tracking

The SDK fires tracking beacons via HTTP requests automatically.

Available Methods

sdk.fireImpression(tracking: trackingInfo, key: "default");
sdk.fireClick(tracking: trackingInfo, key: "default");
sdk.fireVideoEvent(tracking: trackingInfo, key: "start");
sdk.fireCustom(tracking: trackingInfo, key: "companionOpened");

Tracking Keys

Each tracking type supports multiple keys. Use "default" for standard events or specify custom keys defined in your campaign configuration.


Request Builder

The DecisionRequestBuilder provides a fluent API:

final request = sdk.createRequestBuilder()
    .addPlacement(key: "home")
    .addPlacement(key: "promotions", format: Format.native)
    
    .setUserId("user_123")
    .setUserIp("203.0.113.1")
    .setUserTimezone("America/New_York")
    .setUserConsent(Consent(gdpr: true))
    
    .addGeoTargeting(2643743)
    .addLocationTargeting(latitude: 37.7749, longitude: -122.4194)
    .addCustomTargeting(key: "category", value: "news")
    
    .disableAppCollection()
    .disableDeviceCollection()
    
    .build();

Response Structure

APIResponse<DecisionResponse>
├── response: http.Response
├── body: APIResponseBody<DecisionResponse>
│   ├── success: bool
│   ├── data: List<Decision>?
│   │   └── Decision
│   │       ├── placement: String
│   │       └── creatives: List<Creative>?
│   │           └── Creative
│   │               ├── contents: List<Content>
│   │               ├── advertiser: Advertiser
│   │               ├── template: Template
│   │               ├── tracking: Tracking
│   │               ├── metadata: Metadata
│   │               ├── delivery: String
│   │               └── vast: VastData?
│   ├── errors: List<AdMoaiError>?
│   └── warnings: List<AdMoaiWarning>?
└── rawBody: String?

Open Measurement (OM)

The Admoai Flutter SDK surfaces third-party verification resources (e.g. IAS, DoubleVerify, Moat) returned by the decision engine, so publishers can plug them into their own OM integration.

Important: Admoai is not OM-certified and does not bundle the IAB OM SDK. The SDK only exposes the verification metadata — the publisher is responsible for loading the scripts into a verified, namespaced OM SDK in their app.

Accessing verification resources

import 'package:admoai/admoai.dart';

response.body.data?.forEach((decision) {
  decision.creatives?.forEach((creative) {
    if (creative.hasOMVerification()) {
      final resources = creative.getVerificationResources()!;
      for (final r in resources) {
        // Pass r.vendorKey, r.scriptUrl, r.verificationParameters
        // to your OM SDK integration.
      }
    }
  });
});

Integration paths

  1. Native OM SDK (IAB) — Full control. Bundle the IAB-namespaced Open Measurement SDK into your app and pass each VerificationScriptResource to its VerificationScriptResource API. Publisher owns the namespace and the integration.
  2. Google IMA SDK — IMA handles <AdVerifications> automatically when fed a VAST tag/XML. The verification resources are processed inside IMA; no extra wiring needed.
  3. Third-party players (e.g. JW Player) — Commercial players ship with OM support; consult their docs for how to feed the verification metadata.

VerificationScriptResource shape

Field Type Description
vendorKey String Vendor identifier (e.g. "ias", "doubleverify").
scriptUrl String JavaScript URL the verification provider hosts.
verificationParameters String? Optional opaque parameters the SDK passes through unchanged.

Contributing

We welcome contributions! Please see our Contributing Guidelines for details on:

  • How to submit Pull Requests
  • Commit message conventions (Conventional Commits)
  • Code style and testing requirements
  • Development workflow

Example App

For a complete example implementation, check out the example app.

Documentation

For detailed documentation, please visit our documentation site.

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with ❤️ by the AdMoai Team

Libraries

admoai