Deferred Deep Links em Flutter: preservando contexto após instalação — sem pacote (Parte 6)
Nas últimas partes da série, saímos do zero e chegamos a um sistema funcional: configuramos a captura nativa no Android (Post 2) e no iOS (Post 3), integramos tudo ao Flutter com DeepLinkService, MethodChannel e EventChannel (Post 4), e publicamos os arquivos de verificação em deeplinkslab.dev para que App Links e Universal Links funcionem em produção (Post 5).
E, continuando a série… Esse post resolve um problema de produto, não só técnico.
Cenário:
- Usuário clica em link de referral
- Não tem o app instalado
- Vai para a loja, instala, abre
- O
referralCodesumiu
Deep links normais não cobrem esse caso. O sistema operacional não entrega nada no primeiro launch vindo da loja. O contexto fica no navegador.
A solução: Deferred Deep Links.
Solução 1: LocalStorage (simples)
A página web de redirect salva o referralCode antes de redirecionar para a loja:
// Na página web (ver Post 7)
localStorage.setItem('pending_referral', referralCode);
No Flutter, o DeepLinkService captura no primeiro launch e recupera no signup:
// Salvar no primeiro launch
Future<void> processDeferredLink() async {
if (initialLink != null && initialLink!.contains('referralCode')) {
final code = _extractReferralCode(initialLink!);
await _storage.write('pending_referral', code);
}
}
// Recuperar no signup
Future<String?> getPendingReferralCode() async {
final code = await _storage.read('pending_referral');
if (code != null) await _storage.remove('pending_referral');
return code;
}
✅ Zero backend. Funciona offline.
⚠️ Não funciona cross-device.
Solução 2: Backend com fingerprint (robusto)
O conceito: IP + User-Agent + Accept-Language formam um fingerprint que identifica o mesmo device em dois momentos — o clique e o primeiro launch.
// Processar clique e salvar em Redis por 48h
app.get("/s/:code", async (req, res) => {
const referralCode = await db.get(req.params.code);
const fingerprint = generateFingerprint(req);
await redis.setex(`pending:${fingerprint}`, 172800, referralCode);
res.redirect(getStoreUrl(detectPlatform(req)));
});
// Recuperar no primeiro launch do app
app.post("/api/referral/get-pending", async (req, res) => {
const fingerprint = generateFingerprint(req);
const code = await redis.get(`pending:${fingerprint}`);
if (code) {
await redis.del(`pending:${fingerprint}`);
res.json({ referralCode: code });
} else {
res.status(404).json({ message: "Not found" });
}
});
No Flutter, uma chamada no primeiro launch:
Future<String?> checkPendingOnBackend() async {
try {
final response = await dio.post('/api/referral/get-pending');
return response.data['referralCode'];
} catch (e) {
return null;
}
}
✅ Cross-device. Analytics de conversão.
⚠️ Requer backend e Redis. Fingerprinting não é 100% preciso em redes com NAT ou VPN.
Quando usar cada um
MVP ou app novo → LocalStorage.
Analytics de conversão ou cross-device → backend.
Fonte (post completo no Medium)
https://medium.com/p/f3388d58e49a?postPublishedType=initial
Como você resolve isso em produção? LocalStorage, Firebase Dynamic Links, Branch.io ou backend próprio?
Queria saber o que a galera usa de verdade.