Visão geral
SDK de atribuição UTM para aplicativos Flutter. Capture UTMs recebidas por deep links e associe sessões de usuários ao rastreamento de origem em Android e iOS.
Requisitos
- Flutter 3.29+
- Dart 3.10+
- Android:
minSdkVersion 21
- iOS: Deployment Target 11.0+
Instalação
1. Adicione a dependência
Para obter a biblioteca nemu_attribution, entre em contato com o suporte e receba um arquivo .zip.
Após receber o .zip, extraia a pasta nemu_attribution para ./flutter/nemu_attribution (no seu projeto Flutter).
No pubspec.yaml do seu projeto, adicione o pacote:
dependencies:
nemu_attribution:
path: ./flutter/nemu_attribution
Em seguida, instale as dependências:
2. Configuração Android
No arquivo android/app/src/main/AndroidManifest.xml, adicione o intent-filter dentro da <activity> principal para habilitar deep links:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="app.seudominio.com" />
</intent-filter>
3. Configuração iOS
No Xcode, acesse Signing & Capabilities e adicione Associated Domains com o valor:
applinks:app.seudominio.com
Certifique-se de que o arquivo apple-app-site-association esteja disponível no domínio configurado.
Credenciais
O SDK precisa de duas credenciais fornecidas pela Nemu: PIXEL_ID e SDK_TOKEN.
Recomendamos utilizar variáveis de ambiente para não expor credenciais no código-fonte.
Você pode usar o pacote flutter_dotenv ou injetar via --dart-define:
flutter run \
--dart-define=NEMU_PIXEL_ID=<SEU_PIXEL_ID> \
--dart-define=NEMU_SDK_TOKEN=<SEU_SDK_TOKEN>
No código Dart, acesse os valores com:
const pixelId = String.fromEnvironment('NEMU_PIXEL_ID');
const sdkToken = String.fromEnvironment('NEMU_SDK_TOKEN');
Inicialização
Inicialize o SDK o mais cedo possível no ciclo de vida do app, preferencialmente na função main():
import 'package:flutter/material.dart';
import 'package:nemu_attribution/nemu_attribution.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await NemuAttribution.instance.init(
const NemuAttributionConfig(
pixelId: String.fromEnvironment('NEMU_PIXEL_ID'),
sdkToken: String.fromEnvironment('NEMU_SDK_TOKEN'),
debug: true, // Desabilite em produção
),
);
runApp(const MyApp());
}
A chamada init() é idempotente: chamar mais de uma vez não causa efeito.
O SDK inicializa apenas na primeira chamada.
Identificação do Usuário
Após o login, registre o identificador único do usuário para associar a atribuição ao perfil:
import 'package:nemu_attribution/nemu_attribution.dart';
Future<void> signIn(String email, String password) async {
final user = await authApi.login(email: email, password: password);
await NemuAttribution.instance.setUserId(user.id);
}
Para sessões já autenticadas (ex: ao abrir o app com token salvo):
import 'package:nemu_attribution/nemu_attribution.dart';
Future<void> bootstrapSession() async {
final user = await sessionManager.loadUser();
if (user != null) {
await NemuAttribution.instance.setUserId(user.id);
}
}
Obtendo as UTMs da Sessão
Acesse as UTMs da última atribuição capturada:
import 'package:nemu_attribution/nemu_attribution.dart';
Future<void> getUtms() async {
final attribution = await NemuAttribution.instance.getAttribution();
print('utm_source: ${attribution?.source}');
print('utm_medium: ${attribution?.medium}');
print('utm_campaign: ${attribution?.campaign}');
print('utm_content: ${attribution?.content}');
print('utm_term: ${attribution?.term}');
}
Ao enviar dados de compra para a API da Nemu, inclua as UTMs capturadas:
import 'package:nemu_attribution/nemu_attribution.dart';
Future<Map<String, dynamic>> buildPurchasePayload() async {
final attribution = await NemuAttribution.instance.getAttribution();
return {
'transactionId': '123',
'netValue': 99.9,
'status': 'paid',
'utm_source': attribution?.source,
'utm_medium': attribution?.medium,
'utm_campaign': attribution?.campaign,
'utm_content': attribution?.content,
'utm_term': attribution?.term,
};
}
Captura Manual de Deep Link
Caso precise processar uma URL manualmente (ex: recebida por outro mecanismo):
final result = await NemuAttribution.instance.captureDeepLink(
'https://app.seudominio.com?utm_source=google&utm_medium=cpc&utm_campaign=verao',
);
if (result != null) {
print('Atribuição capturada: ${result.source}');
}
Modo Debug
Habilite o modo debug durante o desenvolvimento para verificar a integração via logs do console:
await NemuAttribution.instance.init(
const NemuAttributionConfig(
pixelId: 'SEU_PIXEL_ID',
debug: true, // Habilita logs detalhados
),
);
Os logs são exibidos com o prefixo [NemuAttribution] e podem ser visualizados no DevTools ou no terminal.
Desabilite o modo debug em produção.
Deep Links e Deferred Deep Links
O SDK captura automaticamente:
- Cold-start deep links - quando o app é aberto via link (app fechado)
- Warm-start deep links - quando o app recebe um link enquanto já está aberto
- Deferred deep links - preserva os dados UTM mesmo quando o usuário instala o app após clicar no link
Para habilitar deferred deep links, configure o endpoint na inicialização:
await NemuAttribution.instance.init(
const NemuAttributionConfig(
pixelId: 'SEU_PIXEL_ID',
sdkToken: 'SEU_SDK_TOKEN',
deferredDeepLinkUrl: 'https://api.nemu.com.br/deferred',
),
);
Fluxo de Atribuição
Primeiro acesso (first install):
1. Deep link (cold-start) -> se tiver UTMs, usa como first-touch
2. Deferred deep link -> se configurado, tenta resolver
3. Orgânico -> fallback (source: "organic", medium: "none")
Acessos subsequentes:
- Deep links atualizam apenas o last-touch
- First-touch é imutável após a primeira instalação
- Last-touch respeita o TTL configurado (padrão: 30 dias)