Hotfy CDP - Flutter SDK
SDK oficial do Hotfy CDP para Flutter. Permite rastrear eventos, identificar usuarios, capturar atribuicao de instalacao, registrar tokens de push e medir receita de anuncios (AdMob ILAR) em aplicativos Android e iOS.
Indice
- Instalacao
- Quick Start
- Configuracao
- Event Tracking
- Identity
- Atribuicao
- Push Notifications
- Ad Revenue (AdMob ILAR)
- Offline Queue
- Contexto Automatico
- Referencia da API
- Eventos Padrao
- Troubleshooting
- Exemplos Completos
1. Instalacao
Adicione o SDK e suas dependencias ao pubspec.yaml:
dependencies:
hotfy_cdp_sdk: ^1.0.0
shared_preferences: ^2.2.0
http: ^1.1.0
package_info_plus: ^9.0.0
device_info_plus: ^10.0.0
Ou via linha de comando:
flutter pub add hotfy_cdp_sdk shared_preferences http package_info_plus device_info_plus
Requisitos minimos:
- Dart SDK:
>=3.0.0 <4.0.0 - Flutter:
>=3.10.0 - Android: minSdkVersion 21 (Android 5.0+)
- iOS: iOS 12+
2. Quick Start
Inicialize o SDK no main.dart e comece a rastrear em 5 linhas:
import 'package:flutter/material.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await HotfyCdp.init(CdpConfig(
apiKey: 'seu-api-key',
baseUrl: 'https://api.cdp.hotfy.com',
));
HotfyCdp.track('app_open');
runApp(MyApp());
}
A partir desse ponto, todos os metodos de rastreamento estao disponiveis de qualquer lugar do app sem necessidade de passar instancias.
3. Configuracao
O CdpConfig aceita os seguintes parametros:
await HotfyCdp.init(CdpConfig(
// Obrigatorios
apiKey: 'seu-api-key', // Chave de autenticacao (header X-Api-Key)
baseUrl: 'https://api.cdp.hotfy.com', // URL do backend (trailing slash removida automaticamente)
// Opcionais
appId: 'uuid-do-app', // UUID do app (inferido da apiKey se omitido)
flushInterval: Duration(seconds: 30), // Intervalo entre flushes automaticos (padrao: 30s)
flushAt: 20, // Quantidade de eventos para disparar flush (padrao: 20)
maxQueueSize: 1000, // Limite maximo da fila em memoria (padrao: 1000)
debug: false, // Ativa logs no console (padrao: false)
));
Descricao das opcoes
| Parametro | Tipo | Padrao | Descricao |
|---|---|---|---|
apiKey |
String |
- | Obrigatorio. Chave de autenticacao da API |
baseUrl |
String |
- | Obrigatorio. URL base do backend CDP |
appId |
String? |
null |
UUID do aplicativo. Opcional se a apiKey ja identifica o app |
flushInterval |
Duration |
30s |
Periodicidade do flush automatico via timer |
flushAt |
int |
20 |
Numero de eventos na fila que aciona flush imediato |
maxQueueSize |
int |
1000 |
Maximo de eventos em memoria. Excedendo, o mais antigo e descartado |
debug |
bool |
false |
Habilita logs [HotfyCdp] no console para depuracao |
Exemplo: ambiente de desenvolvimento
await HotfyCdp.init(CdpConfig(
apiKey: 'dev-api-key',
baseUrl: 'http://localhost:3000',
debug: true,
flushAt: 1, // Flush imediato para ver os eventos no console
flushInterval: Duration(seconds: 5),
));
4. Event Tracking
Rastrear um evento personalizado
HotfyCdp.track('nivel_completado');
// Com propriedades
HotfyCdp.track('compra_realizada', properties: {
'produto_id': 'premium_monthly',
'valor': 29.90,
'moeda': 'BRL',
});
Rastrear visualizacao de tela
HotfyCdp.screen('Home');
// Com propriedades adicionais
HotfyCdp.screen('Produto', properties: {
'produto_id': 'abc123',
'categoria': 'jogos',
});
O metodo screen envia um evento do tipo screen com event_name: "screen_view" e adiciona automaticamente screen_name nas properties.
Convencoes de nomenclatura
- Use
snake_casepara nomes de eventos e propriedades:app_open,button_clicked - Seja descritivo e consistente: prefira
purchase_completedabuy - Propriedades de valor monetario devem usar micros (inteiros):
revenue_micros: 1500000= $1.50
5. Identity
Identificar um usuario
Vincule o ID anonimo a um usuario conhecido apos login:
await HotfyCdp.identify('user-123');
// Com traits (atributos do usuario)
await HotfyCdp.identify('user-123', traits: {
'email': 'joao@exemplo.com',
'nome': 'Joao Silva',
'plano': 'premium',
'created_at': '2024-01-15',
});
O identify envia uma requisicao direta ao endpoint /v1/identify para vincular o anonymous_id ao user_id no backend. Nao e enfileirado - e enviado imediatamente.
Acessar IDs
// ID anonimo gerado na primeira inicializacao (UUID v7, persistido)
String anonId = HotfyCdp.anonymousId;
// ID do usuario identificado (null se ainda nao identificado)
String? uid = HotfyCdp.userId;
print('Anonimo: $anonId');
print('Usuario: $uid');
Reset de identidade
Use ao fazer logout do usuario. Gera um novo anonymous_id e limpa o user_id:
await HotfyCdp.reset();
O reset faz flush de todos os eventos pendentes antes de limpar a identidade.
6. Atribuicao
Capture a origem da instalacao do app. Deve ser chamado uma unica vez, no primeiro app_open. O SDK armazena internamente que a atribuicao ja foi capturada e ignora chamadas subsequentes.
Sem parametros (atribuicao organica)
await HotfyCdp.captureAttribution();
Com parametros do Install Referrer (Android)
Integre com o android_play_install_referrer para capturar a origem real:
// pubspec.yaml: android_play_install_referrer: ^2.0.0
import 'package:android_play_install_referrer/android_play_install_referrer.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
Future<void> captureInstallReferrer() async {
try {
final referrerDetails = await AndroidPlayInstallReferrer.installReferrer;
final referrerUrl = referrerDetails.installReferrer ?? '';
// Exemplos de referrer:
// Google Ads: "gclid=abc123&utm_source=google&utm_medium=cpc"
// Meta: "utm_source=meta&meta_encrypted_data=xyz..."
// Organico: ""
final uri = Uri(query: referrerUrl);
final params = uri.queryParameters;
await HotfyCdp.captureAttribution(
params: AttributionParams(
gclid: params['gclid'],
utmSource: params['utm_source'],
utmMedium: params['utm_medium'],
utmCampaign: params['utm_campaign'],
utmContent: params['utm_content'],
utmTerm: params['utm_term'],
metaEncryptedData: params['meta_encrypted_data'],
networkClickId: params['network_click_id'],
),
);
} catch (e) {
// Fallback: captura sem parametros
await HotfyCdp.captureAttribution();
}
}
Parametros de atribuicao disponiveis
| Parametro | Tipo | Descricao |
|---|---|---|
sourceType |
String? |
Tipo da fonte: google_ads, meta, kwai, affiliate, organic |
touch |
String? |
Tipo de toque: click, impression |
gclid |
String? |
Google Click ID (Google Ads) |
utmSource |
String? |
Parametro UTM source |
utmMedium |
String? |
Parametro UTM medium |
utmCampaign |
String? |
Parametro UTM campaign |
utmContent |
String? |
Parametro UTM content |
utmTerm |
String? |
Parametro UTM term |
networkClickId |
String? |
Click ID de outras redes (Kwai, etc.) |
matchedGaid |
String? |
Google Advertising ID para match de dispositivo. Preenchido automaticamente pelo SDK se nao fornecido |
googleCampaignName |
String? |
Nome da campanha Google Ads |
googleAdgroupName |
String? |
Nome do grupo de anuncio Google |
googleKeyword |
String? |
Keyword Google Ads |
googleNetworkType |
String? |
Tipo de rede Google (Search, Display, etc.) |
metaCampaignGroupName |
String? |
Nome do grupo de campanha Meta |
metaCampaignName |
String? |
Nome da campanha Meta |
metaAdgroupName |
String? |
Nome do conjunto de anuncios Meta |
metaPublisherPlatform |
String? |
Plataforma Meta (facebook, instagram, etc.) |
metaEncryptedData |
String? |
Dado criptografado Meta para decriptacao AES-256-GCM no servidor |
extra |
Map<String, dynamic>? |
Campos adicionais customizados |
7. Push Notifications
Registrar token FCM
Registre o token FCM apos obte-lo do Firebase Messaging:
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
Future<void> setupPushNotifications() async {
final messaging = FirebaseMessaging.instance;
// Solicitar permissao (iOS)
await messaging.requestPermission();
// Obter token e registrar no CDP
final token = await messaging.getToken();
if (token != null) {
await HotfyCdp.registerPushToken(
token,
platform: 'android', // ou 'ios'
deviceModel: 'Pixel 8', // opcional
appVersion: '2.1.0', // opcional
locale: 'pt_BR', // opcional
timezone: 'America/Sao_Paulo', // opcional
);
}
// Atualizar token quando renovado
messaging.onTokenRefresh.listen((newToken) {
HotfyCdp.registerPushToken(newToken, platform: 'android');
});
}
Rastrear entrega e abertura de push
// Quando a notificacao e recebida em foreground
FirebaseMessaging.onMessage.listen((message) {
final sendId = int.tryParse(message.data['send_id'] ?? '');
if (sendId != null) {
HotfyCdp.trackPushDelivered(sendId: sendId);
}
});
// Quando o usuario toca na notificacao
FirebaseMessaging.onMessageOpenedApp.listen((message) {
final sendId = int.tryParse(message.data['send_id'] ?? '');
if (sendId != null) {
HotfyCdp.trackPushOpened(sendId: sendId);
}
});
O trackPushDelivered envia o evento push_received e o trackPushOpened envia push_opened, ambos com a propriedade send_id para correlacionar com a campanha de push no backend.
8. Ad Revenue (AdMob ILAR)
Capture receita de impressao em nivel individual (Impression-Level Ad Revenue) usando o callback onPaidEvent do Google Mobile Ads.
Integracao com google_mobile_ads
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
// Anuncio recompensado (Rewarded)
RewardedAd.load(
adUnitId: 'ca-app-pub-xxx/yyy',
request: const AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (ad) {
// Registrar callback de receita ANTES de exibir
ad.onPaidEvent = (AdValue adValue) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: adValue.valueMicros, // ja em micros
currency: adValue.currencyCode, // ex: "USD"
precision: adValue.precisionType.name.toUpperCase(), // "ESTIMATED", "PRECISE"
adUnitId: ad.adUnitId,
adSource: ad.responseInfo?.loadedAdapterResponseInfo?.adSourceName,
adFormat: 'rewarded',
));
};
ad.show(onUserEarnedReward: (_, reward) {
HotfyCdp.track('reward_earned', properties: {
'reward_type': reward.type,
'reward_amount': reward.amount,
});
});
},
onAdFailedToLoad: (error) {
print('Rewarded failed: $error');
},
),
);
Outros formatos de anuncio
// Banner
bannerAd.onPaidEvent = (AdValue adValue) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: adValue.valueMicros,
currency: adValue.currencyCode,
precision: adValue.precisionType.name.toUpperCase(),
adUnitId: bannerAd.adUnitId,
adFormat: 'banner',
));
};
// Intersticial
interstitialAd.onPaidEvent = (AdValue adValue) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: adValue.valueMicros,
currency: adValue.currencyCode,
precision: adValue.precisionType.name.toUpperCase(),
adUnitId: interstitialAd.adUnitId,
adFormat: 'interstitial',
));
};
Campos de AdImpressionData
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
revenueMicros |
int |
Sim | Receita em micros (1 micro = $0.000001). Use adValue.valueMicros diretamente |
currency |
String |
Nao | Codigo da moeda, padrao "USD" |
precision |
String |
Nao | Precisao: "ESTIMATED", "PUBLISHER_PROVIDED", "PRECISE" |
adUnitId |
String? |
Nao | ID do ad unit AdMob |
adSource |
String? |
Nao | Rede de anuncios: "AdMob", "IronSource", etc. |
adFormat |
String? |
Nao | Formato: "banner", "interstitial", "rewarded", "native" |
Nota sobre micros: O valor
valueMicrosretornado peloAdValueja esta em micros ($1.00 = 1.000.000 micros). Nao converta - passe diretamente pararevenueMicros.
9. Offline Queue
O SDK implementa uma fila duravel de eventos que funciona sem conexao com internet.
Como funciona
- Cada chamada a
track()ouscreen()adiciona o evento a uma fila em memoria - A fila e persistida no
SharedPreferencesapos cada insercao - Na proxima inicializacao do app, eventos nao enviados sao restaurados automaticamente
- O flush acontece automaticamente em tres situacoes:
- Por quantidade: quando a fila atinge
flushAteventos (padrao: 20) - Por timer: a cada
flushIntervalsegundos (padrao: 30s) - Ao pausar/fechar o app: o
LifecycleManagerfaz flush quando o app vai para background (AppLifecycleState.pausedouAppLifecycleState.detached)
- Por quantidade: quando a fila atinge
Limites e comportamento
| Aspecto | Valor | Comportamento |
|---|---|---|
| Limite da fila | maxQueueSize (padrao: 1000) |
Ao exceder, o evento mais antigo e descartado |
| Flush por quantidade | flushAt (padrao: 20) |
Flush automatico ao atingir o limiar |
| Flush por tempo | flushInterval (padrao: 30s) |
Timer periodico |
| Retry em falha | Automatico | Eventos voltam para a fila se o servidor retornar erro |
| Batch size | flushAt eventos por requisicao |
Envia em lotes para o endpoint /v1/batch |
Flush manual
// Forca o envio imediato de todos os eventos enfileirados
await HotfyCdp.flush();
10. Contexto Automatico
O SDK coleta automaticamente os seguintes campos de contexto e os inclui em todos os eventos. A coleta ocorre uma vez na inicializacao e o resultado e cacheado.
| Campo | Fonte | Descricao |
|---|---|---|
os |
Platform.operatingSystem |
Sistema operacional: "android" ou "ios" |
os_version |
Platform.operatingSystemVersion |
Versao completa do SO |
device_model |
device_info_plus |
Modelo do dispositivo (ex: "Pixel 8", "iPhone 15") |
app_version |
package_info_plus |
Versao do app (ex: "2.1.0") |
locale |
PlatformDispatcher.instance.locale |
Locale do sistema (ex: "pt_BR") |
timezone |
DateTime.now().timeZoneName |
Fuso horario (ex: "BRT") |
screen_width |
physicalSize / devicePixelRatio |
Largura da tela em pixels logicos |
screen_height |
physicalSize / devicePixelRatio |
Altura da tela em pixels logicos |
sdk_name |
Constante | "hotfy-cdp-flutter" |
sdk_version |
Constante | "1.0.0" |
advertising_id |
AdvertisingIdClient (plugin nativo) |
Google Advertising ID (GAID). Coletado automaticamente no Android. null no iOS ou se opt-out (Limit Ad Tracking) |
Google Advertising ID (GAID)
O SDK coleta o GAID automaticamente durante a inicializacao (Android only), usando o plugin nativo HotfyCdpPlugin que chama AdvertisingIdClient.getAdvertisingIdInfo().
- Sem dependencias extras no Dart — usa
MethodChannelpara comunicacao nativa - Respeita opt-out: se
isLimitAdTrackingEnabled == true, retornanull - Background thread: a chamada e feita em IO thread (nao bloqueia UI)
- Permissao:
com.google.android.gms.permission.AD_IDdeclarada no AndroidManifest do plugin - iOS: retorna
null(IDFA nao coletado por enquanto)
O GAID e incluido automaticamente no context de todos os eventos enviados. Alem disso, o captureAttribution() auto-preenche matched_gaid com o GAID se nao fornecido manualmente.
O contexto e enviado no campo context de cada evento e nao precisa ser configurado manualmente.
11. Referencia da API
Todos os metodos sao estaticos na classe HotfyCdp. O SDK deve ser inicializado com HotfyCdp.init() antes de qualquer chamada.
Inicializacao e ciclo de vida
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.init(CdpConfig config) |
Future<void> |
Inicializa o SDK. Deve ser chamado uma unica vez, antes de qualquer outro metodo |
HotfyCdp.flush() |
Future<void> |
Forca o envio imediato de todos os eventos na fila |
HotfyCdp.shutdown() |
Future<void> |
Para o SDK, faz flush final e libera recursos |
Rastreamento de eventos
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.track(String name, {Map<String, dynamic>? properties}) |
void |
Enfileira um evento customizado |
HotfyCdp.screen(String name, {Map<String, dynamic>? properties}) |
void |
Enfileira um evento de visualizacao de tela |
Identidade
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.identify(String userId, {Map<String, dynamic>? traits}) |
Future<void> |
Vincula o usuario anonimo a um ID conhecido |
HotfyCdp.anonymousId |
String |
Getter: retorna o ID anonimo atual |
HotfyCdp.userId |
String? |
Getter: retorna o user ID (null se nao identificado) |
HotfyCdp.reset() |
Future<void> |
Gera novo anonymous ID e limpa o user ID |
Atribuicao
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.captureAttribution({AttributionParams? params}) |
Future<void> |
Captura a atribuicao de instalacao (executado apenas uma vez por instalacao) |
Push Notifications
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.registerPushToken(String token, {String platform, ...}) |
Future<void> |
Registra token FCM no backend |
HotfyCdp.trackPushDelivered({required int sendId}) |
void |
Rastreia entrega de push (evento push_received) |
HotfyCdp.trackPushOpened({required int sendId}) |
void |
Rastreia abertura de push (evento push_opened) |
Ad Revenue
| Metodo | Retorno | Descricao |
|---|---|---|
HotfyCdp.trackAdImpression(AdImpressionData data) |
void |
Enfileira evento de impressao de anuncio |
12. Eventos Padrao
Eventos emitidos automaticamente pelo SDK ou por metodos dedicados:
| event_name | Tipo | Propriedades | Descricao |
|---|---|---|---|
screen_view |
screen |
screen_name: String |
Emitido por HotfyCdp.screen() |
push_received |
track |
send_id: int |
Emitido por HotfyCdp.trackPushDelivered() |
push_opened |
track |
send_id: int |
Emitido por HotfyCdp.trackPushOpened() |
ad_impression |
track |
revenue_micros: int, currency: String, precision: String, ad_unit_id?: String, ad_source?: String, ad_format?: String |
Emitido por HotfyCdp.trackAdImpression() |
Eventos customizados recomendados (convencao de nomenclatura):
| event_name | Quando usar | Propriedades sugeridas |
|---|---|---|
app_open |
No inicio de cada sessao | - |
onboarding_completed |
Ao finalizar o onboarding | - |
login |
Apos autenticacao do usuario | method: String |
signup |
Apos criacao de conta | method: String |
purchase |
Apos compra in-app | product_id: String, revenue_micros: int, currency: String |
reward_earned |
Ao ganhar recompensa por anuncio | reward_type: String, reward_amount: num |
level_completed |
Em apps de gamificacao | level: int, score: int |
13. Troubleshooting
Ativar modo debug
Sempre ative o modo debug durante o desenvolvimento para ver todos os logs:
await HotfyCdp.init(CdpConfig(
apiKey: 'seu-api-key',
baseUrl: 'http://localhost:3000',
debug: true,
));
Os logs aparecem no console com o prefixo [HotfyCdp]:
[HotfyCdp] Initialized. anonymousId=019342ab-...
[HotfyCdp] Flushed 3 events
[HotfyCdp] Push token registered: ok
[HotfyCdp] Attribution already captured, skipping
Erros comuns
StateError: [HotfyCdp] SDK not initialized. Call HotfyCdp.init() first.
Causa: Um metodo foi chamado antes de HotfyCdp.init() completar.
Solucao: Certifique-se de que await HotfyCdp.init(...) esta no main() antes do runApp() e que WidgetsFlutterBinding.ensureInitialized() e chamado antes de qualquer operacao assincrona.
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // <- Obrigatorio
await HotfyCdp.init(...); // <- Await obrigatorio
runApp(MyApp());
}
StateError: [HotfyCdp] Not initialized ao acessar HotfyCdp.anonymousId
Causa: anonymousId foi acessado antes da inicializacao completar.
Solucao: Acesse anonymousId somente apos o await HotfyCdp.init(...) completar.
Eventos nao chegam ao servidor
- Verifique a
baseUrl- sem trailing slash e com protocolo correto - Ative
debug: truepara ver erros de flush no console - Use
await HotfyCdp.flush()para forcar envio imediato - Verifique se o backend esta acessivel a partir do dispositivo (emulador usa
10.0.2.2paralocalhostno Android)
// No emulador Android, use o IP da maquina host:
baseUrl: 'http://10.0.2.2:3000', // Ao inves de localhost
[HotfyCdp] Already initialized. Call reset() or shutdown() first.
Causa: HotfyCdp.init() foi chamado mais de uma vez (ex: hot reload em desenvolvimento).
Solucao: O SDK ja esta ativo, o aviso pode ser ignorado em desenvolvimento. Em producao, init() deve ser chamado apenas uma vez na inicializacao do app.
Atribuicao nao e capturada
Causa: captureAttribution() foi chamado mais de uma vez - o SDK ignora chamadas subsequentes por design.
Verificacao: Com debug: true, voce vera [HotfyCdp] Attribution already captured, skipping.
Solucao: Este comportamento e correto. A atribuicao deve ser capturada apenas no primeiro app_open pos-instalacao. Se precisar re-testar, limpe os dados do app no dispositivo.
Receita de anuncio com valor zero
Causa: adValue.valueMicros pode ser 0 para impressoes sem fill ou com leilao em andamento.
Solucao: Filtre valores zero antes de chamar trackAdImpression se necessario:
ad.onPaidEvent = (AdValue adValue) {
if (adValue.valueMicros > 0) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: adValue.valueMicros,
// ...
));
}
};
14. Exemplos Completos
Exemplo 1: App Open com atribuicao
Fluxo completo de inicializacao no primeiro uso do app:
import 'package:flutter/material.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
import 'package:android_play_install_referrer/android_play_install_referrer.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await HotfyCdp.init(CdpConfig(
apiKey: 'meu-api-key',
baseUrl: 'https://api.cdp.hotfy.com',
debug: false,
));
// Rastrear abertura do app
HotfyCdp.track('app_open');
// Capturar atribuicao apenas no primeiro app_open
await _captureFirstInstallAttribution();
runApp(MyApp());
}
Future<void> _captureFirstInstallAttribution() async {
AttributionParams? params;
try {
// Android: ler Install Referrer do Google Play
final referrerDetails = await AndroidPlayInstallReferrer.installReferrer;
final referrerUrl = referrerDetails.installReferrer ?? '';
if (referrerUrl.isNotEmpty) {
final uri = Uri(query: referrerUrl);
final p = uri.queryParameters;
params = AttributionParams(
gclid: p['gclid'],
utmSource: p['utm_source'],
utmMedium: p['utm_medium'],
utmCampaign: p['utm_campaign'],
utmContent: p['utm_content'],
utmTerm: p['utm_term'],
metaEncryptedData: p['meta_encrypted_data'],
networkClickId: p['click_id'],
);
}
} catch (_) {
// iOS ou erro - captura sem parametros
}
await HotfyCdp.captureAttribution(params: params);
}
Exemplo 2: Impressao de anuncio rewarded
Fluxo completo de anuncio recompensado com rastreamento de receita ILAR:
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
class RewardedAdManager {
RewardedAd? _ad;
Future<void> load() async {
await RewardedAd.load(
adUnitId: 'ca-app-pub-3940256099942544/5224354917', // Teste
request: const AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (ad) {
_ad = ad;
// Registrar callback de receita ILAR
ad.onPaidEvent = (AdValue adValue) {
HotfyCdp.trackAdImpression(AdImpressionData(
revenueMicros: adValue.valueMicros,
currency: adValue.currencyCode,
precision: adValue.precisionType.name.toUpperCase(),
adUnitId: ad.adUnitId,
adSource: ad.responseInfo
?.loadedAdapterResponseInfo
?.adSourceName,
adFormat: 'rewarded',
));
};
},
onAdFailedToLoad: (error) {
HotfyCdp.track('ad_load_failed', properties: {
'ad_format': 'rewarded',
'error_code': error.code,
});
},
),
);
}
void show(BuildContext context) {
_ad?.show(
onUserEarnedReward: (AdWithoutView ad, RewardItem reward) {
// Rastrear recompensa concedida
HotfyCdp.track('reward_earned', properties: {
'reward_type': reward.type,
'reward_amount': reward.amount,
'ad_unit_id': ad.adUnitId,
});
},
);
_ad = null; // Limpar referencia apos exibicao
}
}
Exemplo 3: Identify + Attribution Flow
Fluxo completo de onboarding com identificacao e atribuicao:
import 'package:flutter/material.dart';
import 'package:hotfy_cdp_sdk/hotfy_cdp_sdk.dart';
import 'package:shared_preferences/shared_preferences.dart';
class OnboardingScreen extends StatelessWidget {
const OnboardingScreen({super.key});
Future<void> _onUserAcceptedTerms(BuildContext context) async {
// 1. Capturar atribuicao
await HotfyCdp.captureAttribution(
params: AttributionParams(
utmSource: 'google',
utmMedium: 'cpc',
utmCampaign: 'lancamento_2025',
),
);
// 2. Rastrear conclusao do onboarding
HotfyCdp.track('onboarding_completed', properties: {
'step': 'terms_accepted',
'version': 'v2',
});
}
Future<void> _onUserLoggedIn(String firebaseUid) async {
// 3. Identificar o usuario apos login
await HotfyCdp.identify(
firebaseUid,
traits: {
'provider': 'google',
'created_at': DateTime.now().toIso8601String(),
},
);
// 4. Rastrear evento de login
HotfyCdp.track('login', properties: {
'method': 'google',
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Bem-vindo ao App'),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () => _onUserAcceptedTerms(context),
child: const Text('Aceitar Termos e Continuar'),
),
],
),
),
);
}
}
Versao do SDK: 1.1.0 Compatibilidade: Flutter 3.10+ / Dart 3.0+ Suporte: Para reportar problemas, abra uma issue no repositorio do projeto.
Libraries
- hotfy_cdp_sdk
- Hotfy CDP SDK for Flutter