Comunidade

Klaviyo Push Notifications no Flutter: 3 Armadilhas Silenciosas - DEV Community

O uso do Klaviyo para notificações push em aplicações Flutter pode resultar em três problemas silenciosos quando a aplicação já utiliza o firebase_messaging: notificações sendo descartadas sem aviso, manipulação de cliques quebrada e notificações de marketing aparecendo silenciosamente. Esses erros surgem durante a integração e não são documentados pela Klaviyo, tornando-os difíceis de diagnosticar.

Compartilhar
Klaviyo Push Notifications in Flutter: 3 Silent Pitfalls - DEV Community

Para CTOs, líderes técnicos e desenvolvedores sêniores que estão debugando por que as notificações push do Klaviyo pararam de funcionar em seu aplicativo Flutter — ou prestes a descobrir o motivo.

Série Klaviyo × Flutter (parte 3 de 4): planejamento e escopo · a camada de análise · armadilhas das notificações push · perfis e newsletter.

Diga não à leitura: A configuração de notificações push do SDK Flutter do Klaviyo parece uma tarefa de 10 minutos — até que você a adiciona em um aplicativo que já usa firebase_messaging. Três falhas silenciosas surgiram na produção:

  • Silenciamente descartadas as notificações push: Múltiplos serviços Android competindo pelo intent MESSAGING_EVENT fizeram com que as notificações do Klaviyo desaparecessem sem deixar rastros.
  • Manipulação de toque quebrada: Em ambos os sistemas, a manipulação de toque do Klaviyo quebrou o callback onMessageOpenedApp do firebase_messaging — links profundos pararam de funcionar.
  • Promocionais invisíveis: A importância da canalização única no Android fez com que as notificações promocionais fossem exibidas silenciosamente em vez de como banners de destaque.

A instalação de 10 minutos e o debug de 3 dias

A documentação da configuração de notificações push do SDK Flutter do Klaviyo parece uma lista de verificação: adicione a pacote klaviyo_flutter_sdk, passe o token FCM, registre para notificações remotas no iOS. Se você seguir isso do zero em um novo projeto, funciona. Os problemas aparecem quando adiciona o Klaviyo em um aplicativo que já usa firebase_messaging — que é cada aplicativo Flutter que já envia notificações push.

A colisão não é um bug do Klaviyo. É uma consequência de como o sistema de intenções do Android e a cadeia de delegados de notificação do iOS funcionam quando múltiplas estruturas competem pelos mesmos callbacks do sistema. A documentação do SDK não avisa porque o SDK funciona corretamente isoladamente. As falhas são no nível da integração, não no nível do SDK, e elas produzem nenhum log de erro, nenhuma queda, nenhuma advertência. As notificações simplesmente param de chegar, os toques param de responder ou as bandeiras param de aparecer — e você tem nada no console para procurar.

Este post aborda três armadilhas que encontrei durante uma integração de produção do Klaviyo em um aplicativo Flutter de comércio eletrônico. O post geral mapeia o escopo completo da integração; este se concentra na camada push. Cada armadilha levou mais tempo para diagnosticar do que para corrigir.

Armadilha 1: Suas notificações push do Klaviyo estão sendo silenciosamente descartadas

No Android, as notificações push chegam através do Firebase Cloud Messaging. O FCM entrega cada mensagem de entrada para um serviço registrado com o filtro de intenção com.google.firebase.MESSAGING_EVENT. Detalhe crítico: O FCM despacha exatamente para um único serviço. Se múltiplos serviços declararem o mesmo filtro de intenção, o Android escolhe um com base na ordem de resolução do serviço — e os outros recebem nada.

Depois de adicionar o SDK do Klaviyo, o manifesto Android mesclado continha três serviços em competição:

  1. FlutterFirebaseMessagingService — registrado pelo plugin firebase_messaging
  2. KlaviyoPushService — registrado pelo SDK do Klaviyo
  3. Um serviço personalizado — o próprio serviço de mensagens do aplicativo

O FCM escolheu um. Os outros foram silenciosamente excluídos. Nenhuma exceção, nenhuma entrada no log. As mensagens despachadas para o serviço errado simplesmente desapareceram. Se FlutterFirebaseMessagingService venceu, as notificações do Klaviyo foram descartadas. Se KlaviyoPushService venceu, a manipulação de push do próprio aplicativo quebrou.

The fix: a single unified service

A solução é um único serviço personalizado que estende FlutterFirebaseMessagingService e delega mensagens do Klaviyo com base no marcador de payload _k:

// AppPushService.kt
package com.example.app

import android.util.Log
import com.google.firebase.messaging.RemoteMessage
import com.klaviyo.pushFcm.KlaviyoNotification
import io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService

class AppPushService : FlutterFirebaseMessagingService() {
    override fun 
<service android:name=\".AppPushService\" android:exported=\"false\">
  <intent-filter>
    <action android:name=\"com.google.firebase.MESSAGING_EVENT\"/>
  </intent-filter>
</service>
<service
    android:name=\"io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService\"
    tools:node=\"remove\"/>
<service
    android:name=\"com.klaviyo.pushFcm.KlaviyoPushService\"
    tools:node=\"remove\"/>
Enter fullscreen mode Exit fullscreen mode

O diretivo tools:node="remove" remove ambos os serviços registrados pelo plugin do manifesto final. Resta apenas o AppPushService, e o FCM tem exatamente um alvo.

Pitfall 2: Taps em notificações param de funcionar em ambas as plataformas

Após resolver a entrega, surgiu um segundo problema: tocar em uma notificação parou de fazer algo útil.

Duas coisas quebraram independentemente nas duas plataformas.

No Android, o SDK do Klaviyo constrói seu próprio PendingIntent para a notificação exibida. Esse intent não carrega os extras do FCM necessários para preencher o objeto RemoteMessage no método onMessageOpenedApp. Quando o usuário toca em uma notificação do Klaviyo, o aplicativo abre, mas a callback de toque do firebase_messaging recebe uma mensagem vazia — ou nunca dispara. O manipulador Dart-side de onMessageOpenedApp, que normalmente roteia links profundos, não recebe nada.

No iOS, o problema estava na cadeia de delegados do UNUserNotificationCenter. A implementação inicial redirecionava cada toque em notificação para o manipulador do Klaviyo sem chamar super. Isso significou que o plugin do firebase_messaging, que também se conecta ao mesmo método de delegado, nunca viu toques não-Klaviyo. A navegação baseada em push do próprio aplicativo parou completamente.

A marca _k e o armadilhamento no iOS

A solução é controlar a marca de Klaviyo _k em ambas as plataformas, e sempre chamar super, para que o firebase_messaging continue funcionando para notificações não-Klaviyo.

Há uma diferença sutil de plataforma aqui que custou tempo de depuração: no Android, a marca _k está em nível superior na carga útil do FCM. No iOS, ela é aninhada sob a chave body da carga útil APNs. Uma verificação ingênua para userInfo['_k'] no iOS irá perdê-la.

override func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: 
Pitfall 3: Android channel importance is write-once

Este é o modo de falha mais silencioso. As notificações do Klaviyo chegam. Os toques funcionam. Mas as notificações aparecem silenciosamente na área de notificação em vez de surgir como banners de destaque. Campanhas de marketing que ninguém vê são campanhas de marketing que não convertem — e em um aplicativo de comércio eletrônico direto ao consumidor, as notificações push são uma fonte direta de receita. Notificações silenciosas significam vendas perdidas, não apenas um inconveniente na experiência do usuário.

A causa é uma característica da plataforma Android: a importância do canal de notificação é imutável após a criação. Uma vez que um canal é registrado com Importance.DEFAULT, nenhum código pode elevá-lo para Importance.HIGH. A ID do canal é a chave — mesma ID, mesma importância, para sempre, até que o usuário altere manualmente em configurações do sistema ou o aplicativo delete e recrie o canal com uma nova ID.

Caso os canais de notificação do aplicativo tenham sido criados originalmente com a importância padrão — o que é comum, já que a importância padrão é... padrão — então trocar para Klaviyo para campanhas de marketing não irá mágicamente atualizar esses canais. A notificação chega, pousa no canal existente e exibe silenciosamente.

The fix: bump the channel ID

A única solução confiável é criar novos canais com novas IDs no nível de importância desejado e excluir os canais legados ao iniciar o aplicativo.

enum NotificationChannelId {
  marketing('marketing_v2'),
  content('content_v2'),
  loyalty('loyalty_v2');

  const NotificationChannelId(this.id);
  final String id;
}
Enter fullscreen mode Exit fullscreen mode

O sufixo _v2 é uma convenção, não um requisito — qualquer nova string funciona. O ponto é que é um ID de canal diferente, então o Android cria um novo canal com o nível de importância que você especifica no momento da criação. Ao iniciar o aplicativo, exclua as IDs dos canais legados para que os usuários não vejam entradas duplicadas em suas configurações de notificação.

Isso se generaliza além da importância: qualquer alteração na propriedade do canal no Android — som, padrão de vibração, cor LED — requer um bump na ID. O sistema de canais do Android é projetado para dar aos usuários controle após a criação do canal. O aplicativo tem uma única chance das configurações padrões.

O que isso significa para sua estimativa

Se alguém lhe cotar um dia de trabalho para "adicionar notificações push do Klaviyo ao aplicativo Flutter", eles estão se referindo à instalação da SDK. A instalação da SDK é real — leva uma ou duas horas. Mas, se o aplicativo já usa firebase_messaging, as três armadilhas acima são quase certas, e cada uma leva mais tempo para diagnosticar do que para corrigir.

Uma estimativa realista para a integração de notificações push em um aplicativo Flutter que já usa firebase_messaging:

  • Roteamento de entrega (Armadilha 1): 0,5–1 dia. A correção é pequena; diagnosticar descartes silenciosos é o tempo consumido.
  • Colidir ao tocar (Armadilha 2): 0,5–1 dia. Dois sistemas operacionais, dois diferentes _k locais, ambos precisam ser testados.
  • Migração de importância do canal (Armadilha 3): 0,25–0,5 dia. Direta uma vez diagnosticada.
  • Extensão de Serviço iOS Notification Service Extension (se notificações ricas forem necessárias): 0,5–1 dia. As notificações ricas do Klaviyo (imagens, GIFs, botões de ação) exigem um alvo Xcode separado que o conjunto de ferramentas Flutter não scaffolds. O código da extensão em si é mínimo — KlaviyoSwiftExtension lida com downloads de mídia — mas a configuração do Xcode, perfil de provisionamento e configuração do grupo de aplicativos são todos passos manuais.

Total: 2–3,5 dias apenas para notificações push, sem contar a QA em ambos os sistemas operacionais com dispositivos reais. A entrega end-to-end através da infraestrutura do Klaviyo requer dispositivos físicos — o simulador iOS suporta simulação básica de push (arrastar e soltar payloads APNs desde o Xcode 11.4), mas a cadeia completa de roteamento do Klaviyo só funciona em hardware real. Reserve orçamento para builds de dispositivo em ambos os sistemas operacionais.

Se você está avaliando uma integração do Klaviyo como parte de um projeto maior de desenvolvimento de aplicativos, a camada push é apenas uma das quatro linhas de trabalho — o post de visão geral mapeia a abrangência total.

Planejando uma integração do Klaviyo para o seu aplicativo Flutter? Eu lancei isso em produção e documentei as horas — agende um café de 20 minutos e traga sua pilha de tecnologia. Vou lhe dizer onde os dias irão.

O padrão em todas as três armadilhas

A falha é silenciosa, o diagnóstico leva mais tempo do que a correção e a causa raiz é um comportamento da plataforma — não um bug do Klaviyo. Isso significa na prática:

  • Falhas silenciosas são as piores falhas. Todos os três armadil士你的回答非常专业,但是最后的部分出现了乱码。请将给定文本完整并正确地翻译成葡萄牙语(巴西),并且保持原文中的HTML格式不变。感谢!以下是需要翻译的文本部分:silent failures are the worst failures. All three pitfalls produce zero log output. The push arrives at the device, gets dispatched to the wrong handler or the wrong channel, and disappears. Add logging at the native service entry point before you start debugging anything else.
  • O marcador _k é sua chave de roteamento. Cada caminho específico do Klaviyo — entrega, toques, manipulação em Dart — deve ser baseado nesse único marcador. Memorize onde ele está: no nível superior nos payloads de dados Android, aninhado sob body nos payloads APNs iOS.
  • tools:node="remove" é essencial em aplicativos multi-SDK Android. Quando dois plugins registram serviços para o mesmo filtro de intenção, a manifestação combinada cria uma condição de corrida. O padrão consiste em remover os serviços registrados pelo plugin e substituí-los por um único serviço personalizado.
  • A importância do canal é uma decisão única. Se você estiver configurando canais de notificação pela primeira vez, pense cuidadosamente sobre a importância. Se os canais já existirem com importância padrão, o único caminho para banners em destaque é um novo ID de canal.
  • Budgete depuração de plataforma, não instalação de SDK. O SDK funciona. A integração da plataforma é onde vão os dias.

Para depurar todos os três armadilhos, comece com o registro em nível nativo no ponto de entrada do serviço. No Android, adicione uma chamada Log.d no topo de onMessageReceived no seu serviço personalizado — se você nunca vir a linha de log, o serviço não está recebendo mensagens. No iOS, registre na função delegada didReceive. Esses registros em nível de entrada são a maneira mais rápida de determinar qual camada está engolindo a mensagem.

Com entrega push, toques e canais resolvidos, o trabalho remanescente da integração foi a identidade e o boletim informativo — que introduziu seu próprio conjunto de bugs silenciosos de integridade dos dados. A parte 4 aborda essas armadilhas.

Preciso corrigir todas as três armadilhas, ou posso pular algumas?

A Armadilha 1 (roteamento de entrega) é obrigatória — sem ela, tanto os push notifications do Klaviyo quanto seus push notifications existentes serão silenciosamente descartados. A Armadilha 2 (colisão ao tocar) depende se seu aplicativo usa onMessageOpenedApp para deep linking. A Armadilha 3 (importância do canal) só importa se você precisar de banners de alerta para push notifications de marketing, mas push notifications de marketing que são exibidas silenciosamente têm engajamento significativamente menor.

Fonte original

Conteúdo traduzido e adaptado pela redação do Notícias Mobile. Confira também a matéria na fonte original.

Leia a matéria completa