hotfy_wrapper_sdk 0.1.26
hotfy_wrapper_sdk: ^0.1.26 copied to clipboard
Hotfy Wrapper SDK for Flutter — remote-controlled ad orchestration (interstitial, app open, rewarded, banner, native) for AdMob and GAM, configured via the Hotfy App Console.
hotfy_wrapper_sdk #
Wrapper SDK da Hotfy para Flutter — orquestração remota de anúncios (interstitial, app open, rewarded, banner, native) com AdMob e GAM, configurada via Hotfy App Console.
O que esse SDK te dá #
- Config remota: ad units por tela por segmento, decididos no console — mude no dashboard, sem rebuild do app
- Pool embutido: interstitials são pré-carregados por ad unit, em paralelo, com re-preload automático após cada exibição
- Boot ad: app open ou interstitial no slot do splash, com timeout e fallback
- Rewarded ads: API
Future<bool> - Banner & Native widgets:
WrapperBannereWrapperNativeAd - App Open on foreground: warm return ad com cooldown global
- Logs padronizados:
Ad [TYPE] ACTION key=value...pra grep / dashboards - API de eventos: pluga em qualquer analytics (Hotfy CDP, Mixpanel, Amplitude, Sentry…) — o SDK é zero-dep de analytics
- Guards de test ad: bloqueia builds de produção de servir ad units de teste por engano
Instalação #
flutter pub add hotfy_wrapper_sdk google_mobile_ads
Equivalente a adicionar no pubspec.yaml:
dependencies:
hotfy_wrapper_sdk: ^0.1.0
google_mobile_ads: ^5.0.0
Por que declarar
google_mobile_adsno seu app também? O wrapper já o declara como dependência transitiva e o pub resolve pra uma única versão, mas declarar explicitamente no seupubspec.yamlte dá controle de qual minor/patch ficar fixado na sua lockfile.
Você também precisa configurar o google_mobile_ads no app:
- Android: AdMob App ID em
android/app/src/main/AndroidManifest.xml - iOS: AdMob App ID + SKAdNetwork IDs em
ios/Runner/Info.plist
Ver os docs oficiais.
Quick start #
1. Inicializa uma vez no boot do app #
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await MobileAds.instance.initialize();
await HotfyWrapper.init(WrapperInitConfig(
appId: const String.fromEnvironment('WRAPPER_APP_ID'),
baseUrl: const String.fromEnvironment('WRAPPER_BASE_URL'),
// O SDK classifica a origem do user (google_ads, meta_ads, organic, …)
// a partir desses campos crus — passe o que tiver do install referrer.
utmSource: attribution?.utmSource,
utmMedium: attribution?.utmMedium,
utmCampaign: attribution?.utmCampaign,
utmContent: attribution?.utmContent, // necessário pra detectar Meta Install Referrer encriptado
gclid: attribution?.gclid, // se veio de Google Ads
daysSinceInstall: daysSinceInstall, // calculado do seu first-open timestamp
useTestAds: kDebugMode, // opcional
debug: kDebugMode,
));
startAdPreload(); // pré-carrega interstitials configurados pro segmento resolvido
runApp(const MyApp());
}
O backend resolve o segmento (d0_meta, d0_google, d0_organic, etc.)
a partir desses campos. Passa o que tiver — o SDK escolhe a heurística
certa internamente (sem precisar você classificar no app).
2. Mostra um interstitial #
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
Future<void> handleProceed() async {
await showInterstitial('cart_proceed');
if (mounted) Navigator.pushNamed(context, '/checkout');
}
A screenKey é o único contrato entre o app e o console. O console decide
qual ad unit (ou fallback) servir pra essa tela no segmento do user. Se
nenhum unit tá configurado, a chamada resolve silenciosamente (no-op).
3. Mostra boot ad durante o splash #
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
// antes de remover o splash / push da próxima tela
await loadAndShowBootAd(timeoutMs: 4000);
Suporta tanto app_open quanto interstitial no slot do boot, com
fallback automático se o primário não preencher dentro do orçamento de tempo.
4. Mostra um rewarded ad #
final earned = await showRewarded(screenKey: 'chat');
if (earned) unlockTurn();
5. Banner #
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
WrapperBanner(screenKey: 'home', size: WrapperBannerSize.adaptive),
WrapperBanner(screenKey: 'feed', size: WrapperBannerSize.mediumRectangle),
Tamanhos: adaptive (anchored adaptive — recomendado), inlineAdaptive,
banner (320×50), largeBanner (320×100), mediumRectangle (300×250),
fullBanner (468×60), leaderboard (728×90).
O widget renderiza SizedBox.shrink() se ads estiverem desativados ou não
tiver unit configurado pra essa tela. Cai pra screens[X].banner_fallback
se o primário falhar ao carregar.
6. Native ad #
Native ads no google_mobile_ads suportam dois caminhos de renderização:
Template style (recomendado pra começar — sem código nativo):
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
WrapperNativeAd(
screenKey: 'feed',
minHeight: 90,
nativeTemplateStyle: NativeTemplateStyle(
templateType: TemplateType.medium,
mainBackgroundColor: Colors.white,
),
)
Factory (layout 100% custom — requer registrar NativeAdFactory no
Android/iOS host app):
WrapperNativeAd(
screenKey: 'feed',
factoryId: 'listTile',
)
Nota:
google_mobile_adspara nativos expõe apenasonAdImpressionsem payload de receita (semonPaidEvent). O wrapper emiteimpressionpra native ads comrevenueMicros,value,currencyeprecisionnulos. Chequeif (e.revenueMicros != null)antes de usar campos de receita no listener.
Eventos — pluga em qualquer analytics #
O SDK emite eventos tipados. Pluga eles em qualquer stack de analytics — o próprio SDK não tem dependência de analytics.
import 'package:hotfy_wrapper_sdk/hotfy_wrapper_sdk.dart';
import 'package:hotfy_cdp/hotfy_cdp.dart';
HotfyWrapper.on<AdImpressionEvent>(WrapperEventName.impression, (e) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: e.revenueMicros ?? 0,
currency: e.currency ?? 'USD',
precision: e.precision ?? 'ESTIMATED',
adUnitId: e.adUnitId,
adSource: e.network.value,
adFormat: e.format.value,
));
});
HotfyWrapper.on<AdErrorEvent>(WrapperEventName.error, (e) {
Sentry.captureMessage('Ad ${e.format} ${e.reason}: ${e.message}');
});
Eventos disponíveis #
| Evento | Quando dispara |
|---|---|
load |
Ad começou a carregar |
show |
Ad foi mostrado pro user |
close |
User fechou o ad |
impression |
Evento onPaidEvent do GMA — receita confirmada (use pra revenue tracking) |
error |
Falha no load ou show |
skip |
Ad pulado (sem unit configurado, slot vazio, ads desativados, cooldown, etc.) |
A função on() retorna uma função de unsubscribe:
final off = HotfyWrapper.on<AdImpressionEvent>(WrapperEventName.impression, listener);
// depois, se quiser parar de escutar:
off();
App Open on foreground (warm return) #
Quando o backend retorna app_open_on_foreground: true no config do
segmento ativo, o SDK passa a mostrar App Open ad quando o user volta do
background (depois de ≥30s away). O cooldown global vem de
app_open_cooldown_minutes e é compartilhado entre boot ad (cold start)
e foreground ad.
Pra suprimir manualmente (ex: durante onboarding crucial):
HotfyWrapper.disableAppOpenOnForeground();
Persiste até HotfyWrapper.reset() ser chamado.
Como funciona #
O pool é indexado por unitId, não por screenKey. Cada ad unit único
ganha seu próprio slot, pré-carregado em paralelo no startup. Chamar
showInterstitial(screenKey) faz lookup do unit configurado pra essa
tela e mostra do slot dele — garantindo que o unit correto sempre
apareça na tela correta.
Licença #
UNLICENSED — proprietário. Copyright (c) 2026 Hotfy LLC. Todos os direitos reservados. Ver LICENSE pros termos. Sem uso, modificação ou distribuição sem permissão escrita prévia da Hotfy LLC.