BiddingStack Flutter SDK

BiddingStack Flutter SDK Integration Guide

BiddingStack Flutter SDK provides cross-platform header bidding for iOS and Android with Google Ad Manager (GAM) integration. It wraps the native iOS and Android SDKs via platform channels. View Changelog.

Requirements

ComponentMinimum Version
Flutter3.3+
Dart3.9+
iOS15.6+
Android Min SDK23

Installation

1. Add Dependencies

Add the BiddingStack Flutter packages to your pubspec.yaml:

dependencies:
  biddingstack_core:
    path: ../biddingstack-flutter-core
  biddingstack_gam_adapter:
    path: ../biddingstack-flutter-gam-adapter

2. iOS Setup

Add to your Info.plist:

<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX</string>

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to deliver personalized ads to you.</string>

<key>SKAdNetworkItems</key>
<array>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>22mmun2rn5.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>3qcr597p9d.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>3rd42ekr43.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>44jx6755aq.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>47vhws6wlr.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>4dzt52r2t5.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>578prtvx9j.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>8c4e2ghe7u.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>97r2b46745.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>a2p9lx4jpn.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>c3frkrj4fj.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>cp8zw746q7.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>gta9lk7p23.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>k674qkevps.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>kbmxgpxpgc.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>ludvb6z3bs.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>mlmmfzh3r3.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>n38lu8286q.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>su67r6k2v3.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>tl55sbb4fm.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>v4nxqhlyqp.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>v9wttpbfk9.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>vutu7akeur.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>wg4vff78zm.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>y5ghdn5j9k.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
        <key>SKAdNetworkIdentifier</key>
        <string>ydx93a7ass.skadnetwork</string>
    </dict>
</array>
SKAdNetwork ID reference table
SKAdNetwork IDCompany
cstr6suwn9Google
4fzdc2evr5Aarki
2fnua5tdw4AppLovin
ydx93a7assAdikteev
p78axxw29gByteDance (Pangle)
v72qych5uuAppier
c6k4g5qg8mBeeswax (Freewheel)
hs6bdukanmCriteo
mlmmfzh3r3Appreciate
wzmmz9fp6wSnap Inc.
yclnxrl5pmJampp
t38b2kh725Lifestreet
7ug5zh24huLiftoff (Vungle)
9t245vhmplMoloco
44jx6755aqPersona.ly
4468km3ulzKayzen
tl55sbb4fmPubNative (Verve Group)
2u9pt9hc89Remerge
8s468mfl3yRTB House
klf5c3l5u5Sift
ppxm28t8apSmadex
3rd42ekr43YouAppi
OthersGoogle (Demand Partners)

3. Android Setup

Update AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application ...>
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX"/>
</application>

SDK Initialization

Initialize BiddingStack from Dart before rendering any ads. Use await to ensure the remote config is loaded before building the widget tree:

import 'package:biddingstack_core/services.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await BiddingStack.initialize('YOUR_BS_ACCOUNT_ID', enableTestMode: true);
  runApp(const MyApp());
}

Important: iOS and Android use separate BiddingStack account IDs and config IDs. See Platform-Specific Configuration for how to pass the correct values per platform.

Initialize Parameters

ParameterTypeDefaultDescription
accountIdStringrequiredYour BiddingStack Account ID
appBundleString''App bundle ID (auto-detected if empty)
appNameString''App name (resolved from config if empty)
appStoreIdString''App Store / Play Store ID (resolved from config if empty)
timeoutint2000Bid request timeout in ms
enableTestModeboolfalseEnable debug logging and test mode
currencyString'USD'Currency code for bid requests
enableCMPbooltrueAuto-read IAB CMP strings from UserDefaults/SharedPreferences
requestATTPermissionbooltrueiOS only: prompt for App Tracking Transparency permission during initialization

Note: App bundle, name, store ID, and GAM ad unit paths are resolved automatically from the remote config. You only need to pass the account ID.

Ad Formats

final bannerAdUnit = BiddingStackBannerAdUnit(
    configId: 'YOUR_CONFIG_ID',
    gamAdUnitId: 'YOUR_GAM_AD_UNIT_ID', // optional fallback if config API is unavailable
    adSizes: const [BiddingStackAdSize(300, 250)],
    autoRefreshEnabled: true,
);

BiddingStackGAMBannerView(
    adUnit: bannerAdUnit,
    onAdLoaded: () => debugPrint('Banner loaded'),
    onAdFailedToLoad: (error) => debugPrint('Banner failed: \$error'),
)

BiddingStackBannerAdUnit Parameters

ParameterTypeDefaultDescription
configIdStringrequiredPlacement config ID
gamAdUnitIdString''GAM ad unit path (resolved from config if empty)
adSizesList<BiddingStackAdSize>requiredAd sizes
autoRefreshEnabledboolfalseAuto-refresh ads
lazyLoadEnabledboolfalseLazy load when visible
isAutoLoadAdbooltrueAuto-load on creation
formatsList<BiddingStackFormat>[banner]banner, video

Outstream Video

final videoAdUnit = BiddingStackBannerAdUnit(
    configId: 'YOUR_VIDEO_CONFIG_ID',
    adSizes: [BiddingStackAdSize(300, 250)],
    formats: [BiddingStackFormat.video],
);

BiddingStackIMAVideoRendererBannerView(
    adUnit: videoAdUnit,
    onAdLoaded: () => debugPrint('Video loaded'),
    onAdPlaybackCompleted: () => debugPrint('Video complete'),
)

Interstitial Ad

// Google interstitial size: 320x480 phone, 768x1024 tablet
final interstitialAdUnit = BiddingStackInterstitialAdUnit(
    configId: 'YOUR_CONFIG_ID',
    size: BiddingStackAdSize(320, 480),
    formats: [BiddingStackFormat.banner, BiddingStackFormat.video],
);

// Load and show via GAM
BiddingStackGAMAdapter.loadAndShowInterstitialAdByGAM(interstitialAdUnit);

Interstitial Banner Ad

// Load
BiddingStackGAMAdapter.loadInterstitialAdWithGAMBannerProvider(
    interstitialAdUnit,
    GAMBannerProvider(adUnitId: 'AD_UNIT_ID', sizes: [BiddingStackAdSize(320, 480)]),
);

// Show when ready
BiddingStackGAMAdapter.showInterstitialAdWithGAMBannerProvider(interstitialAdUnit);

App Open Ad

App open ads show at natural app-entry points, such as launch or returning from the background. The SDK preloads the ad, sizes it for the device (320x480 phone, 768x1024 tablet), and preloads the next one after each show.

// Preload early, e.g. at app start
BiddingStackGAMAdapter.loadAppOpenAd('YOUR_CONFIG_ID', 'AD_UNIT_ID');

// Show when the app returns to the foreground
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      BiddingStackGAMAdapter.showAppOpenAdIfAvailable();
    }
  }
}

showAppOpenAdIfAvailable() returns true when an ad was shown. If no ad is ready, it starts loading one for the next opportunity and returns false.

Rewarded Ad

final rewardedAdUnit = BiddingStackRewardedAdUnit(
    configId: 'YOUR_CONFIG_ID',
    size: BiddingStackAdSize(300, 250),
);

BiddingStackGAMAdapter.loadAndShowRewardedAdByGAM(rewardedAdUnit);

Native Ad

final nativeAdUnit = BiddingStackNativeAdUnit(
    configId: 'YOUR_CONFIG_ID',
);

final ad = await BiddingStack.getNativeAd(nativeAdUnit);
if (ad != null) {
    print(ad.title);
    print(ad.body);
    print(ad.callToAction);
}

BiddingStackNativeAd Properties

PropertyTypeDescription
titleString?Ad headline
bodyString?Ad body text
callToActionString?CTA button text
sponsoredByString?Sponsor/advertiser name
iconURLString?Icon image URL
mainImageURLString?Main image URL
clickURLStringClick-through URL

Advanced Features

Bid Preloading

await BiddingStack.preloadBid(bannerAdUnit);
// Later, the ad view uses the cached bid automatically

User Data & Targeting

BiddingStack.setUserId("1234");
BiddingStack.setUserGender("M");
BiddingStack.setUserYob(1980);
BiddingStack.setUserLatLng(34.0522, -118.2437);
BiddingStack.setAppStoreUrl("https://apps.apple.com/app/id123456");
BiddingStack.setAppCategories(["IAB1", "IAB2"]);
BiddingStack.setExternalUserIds({"partner": "uid_abc"});
BiddingStack.setSchainObject('{"ver":"1.0","complete":1,"nodes":[...]}');
BiddingStack.setBuyerUid("buyer_123");

// Custom targeting
BiddingStack.addTargetingKV("interest", "tech");
BiddingStack.addTargetingKV("interest", ["tech", "gaming"]);
BiddingStack.removeTargetingKey("interest");
BiddingStack.clearTargetingKV();

Content URL

Pass the web URL of the content the user is currently viewing so it is included in every bid request as app.content.url. This is important for brand safety and yield: it gives bidders page-level context to verify where their ads run, which increases bid rates and CPMs. Call it before the screen's ad widgets build — e.g. in initState — and update it on each screen change; pass null to clear.

@override
void initState() {
  super.initState();
  BiddingStack.setContentUrl("https://www.example.com/article/12345");
}

Available since SDK 26.7.1.

Privacy & Compliance

BiddingStack.setCoppa(true);
BiddingStack.setUSPrivacy("1YNN");
BiddingStack.setGppConsent("gpp_string", [1, 2]);
BiddingStack.setGDPR("USER_CONSENT_STRING", true);
BiddingStack.setIdfa("IDFA_STRING"); // iOS only

PMP Deals

final bannerAdUnit = BiddingStackBannerAdUnit(
    configId: 'YOUR_CONFIG_ID',
    adSizes: const [BiddingStackAdSize(300, 250)],
    deals: [BiddingStackDeal(id: 'deal_123', bidfloor: 5.50, bidfloorcur: 'USD')],
);

Platform-Specific Configuration

If iOS and Android use different account IDs or config IDs:

import 'dart:io' show Platform;

await BiddingStack.initialize(
  Platform.isIOS ? 'IOS_ACCOUNT_ID' : 'ANDROID_ACCOUNT_ID',
  enableTestMode: true,
);

final bannerAdUnit = BiddingStackBannerAdUnit(
    configId: Platform.isIOS ? 'ios_config_id' : 'android_config_id',
    adSizes: [BiddingStackAdSize(300, 250)],
);

Debug Logging

BiddingStack.enableLogging = true;