身為一個在台灣的獨立開發者,我花了不少時間研究 Flutter App 的變現方式。試過各種方案後,Google AdMob 仍然是我認為最適合個人開發者起步的廣告平台。今天就來分享我在自己的 App 中整合 AdMob 的完整流程和踩過的坑。
為什麼選擇 AdMob?
在台灣做獨立開發,付費下載的市場其實不大。大部分使用者更習慣免費下載搭配廣告的模式。AdMob 的優勢在於:
- 背後是 Google,廣告填充率高,在台灣市場也有不錯的表現
- 與 Firebase 生態系整合良好,數據分析方便
- 支援多種廣告格式,可以依據 App 類型靈活選擇
- Flutter 有官方維護的
google_mobile_ads套件,穩定度有保障
前置準備
註冊 AdMob 帳號
首先到 AdMob 官網 註冊帳號。注意,你需要一個有效的 Google 帳號,而且審核通過後才能開始放置廣告。我當時大約等了兩天就通過了。
建立 App 與廣告單元
在 AdMob 後台新增你的 App,然後建立廣告單元(Ad Unit)。常用的有三種:
- Banner Ad(橫幅廣告):固定在畫面上方或下方的小型廣告
- Interstitial Ad(插頁廣告):全螢幕廣告,適合在自然過場時顯示
- Rewarded Ad(獎勵廣告):使用者主動觀看後獲得獎勵
每個廣告單元建立後會拿到一組 Ad Unit ID,後面程式碼會用到。
安裝套件與平台設定
在 pubspec.yaml 加入依賴:
dependencies:
google_mobile_ads: ^5.3.0
Android 設定
在 android/app/src/main/AndroidManifest.xml 的 <application> 標籤內加入:
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
把 value 換成你在 AdMob 後台拿到的 App ID。
iOS 設定
在 ios/Runner/Info.plist 加入:
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy</string>
另外記得在 ios/Podfile 確認最低版本是 iOS 14.0 以上,不然編譯可能會出問題。
初始化 AdMob SDK
在 main.dart 的 main() 函數中初始化:
import 'package:google_mobile_ads/google_mobile_ads.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await MobileAds.instance.initialize();
runApp(const MyApp());
}
這一步很重要,一定要在 runApp 之前完成初始化,否則廣告載入會失敗。
實作 Banner Ad
Banner 廣告是最基本也最不干擾使用者的格式。我通常會放在畫面底部:
class BannerAdWidget extends StatefulWidget {
const BannerAdWidget({super.key});
@override
State<BannerAdWidget> createState() => _BannerAdWidgetState();
}
class _BannerAdWidgetState extends State<BannerAdWidget> {
BannerAd? _bannerAd;
bool _isLoaded = false;
@override
void initState() {
super.initState();
_loadAd();
}
void _loadAd() {
_bannerAd = BannerAd(
adUnitId: 'ca-app-pub-xxxxx/yyyyy', // 換成你的 Ad Unit ID
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() => _isLoaded = true);
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
debugPrint('Banner 載入失敗: $error');
},
),
)..load();
}
@override
void dispose() {
_bannerAd?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (!_isLoaded || _bannerAd == null) return const SizedBox.shrink();
return SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!),
);
}
}
實作 Interstitial Ad
插頁廣告適合在遊戲關卡結束、頁面切換時顯示。重點是不要太頻繁,不然使用者體驗會很差:
class InterstitialAdManager {
InterstitialAd? _interstitialAd;
void loadAd() {
InterstitialAd.load(
adUnitId: 'ca-app-pub-xxxxx/yyyyy',
request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (ad) {
_interstitialAd = ad;
},
onAdFailedToLoad: (error) {
debugPrint('插頁廣告載入失敗: $error');
},
),
);
}
void showAd() {
if (_interstitialAd != null) {
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdDismissedFullScreenContent: (ad) {
ad.dispose();
loadAd(); // 預先載入下一則
},
);
_interstitialAd!.show();
_interstitialAd = null;
}
}
}
我自己的做法是每隔三到五個關卡才顯示一次插頁廣告。過度投放廣告只會讓使用者想移除你的 App。
實作 Rewarded Ad
獎勵廣告是我最推薦的格式,因為使用者是主動選擇觀看的,體驗最好:
void loadRewardedAd() {
RewardedAd.load(
adUnitId: 'ca-app-pub-xxxxx/yyyyy',
request: const AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (ad) {
ad.fullScreenContentCallback = FullScreenContentCallback(
onAdDismissedFullScreenContent: (ad) => ad.dispose(),
);
ad.show(
onUserEarnedReward: (ad, reward) {
// 給使用者獎勵,例如額外生命、金幣等
debugPrint('獲得獎勵: ${reward.amount} ${reward.type}');
},
);
},
onAdFailedToLoad: (error) {
debugPrint('獎勵廣告載入失敗: $error');
},
),
);
}
測試廣告的注意事項
開發階段請務必使用 Google 提供的測試 Ad Unit ID,千萬不要用正式的 ID 去點擊,否則帳號可能會被停權。官方測試 ID 如下:
- Banner:
ca-app-pub-3940256099942544/6300978111 - Interstitial:
ca-app-pub-3940256099942544/1033173712 - Rewarded:
ca-app-pub-3940256099942544/5224354917
上架前記得切換回正式的 Ad Unit ID。
關於 app-ads.txt
如果你有自己的開發者網站,記得在根目錄放一個 app-ads.txt 檔案。這是 IAB 的標準,用來驗證你確實是該 App 的授權廣告發布者。我自己的網站上就有放這個檔案,內容大概長這樣:
google.com, pub-3594215621243517, DIRECT, f08c47fec0942fa0
在 AdMob 後台的「App 設定」裡可以找到對應的資訊。
結語
整合 AdMob 其實不困難,真正的挑戰在於找到廣告收益和使用者體驗之間的平衡。我的建議是先從 Banner 和 Rewarded Ad 開始,等流量穩定後再考慮插頁廣告。
最後提醒一下,AdMob 的政策經常更新,特別是關於兒童應用的 COPPA 規範。如果你的 App 可能有兒童使用者,一定要在 AdMob 後台正確設定「兒童導向處理方式」,這部分我會在另一篇文章詳細說明。
希望這篇教學對同樣在台灣做獨立開發的朋友有幫助,有問題歡迎留言討論!