Pular para o conteúdo

SDK de Expo / React Native

@kilden-io/expo é o SDK cliente do Kilden para apps Expo e React Native: captura de eventos, tracking de telas, identidade persistida e feature flags. É a contraparte mobile do SDK web — mesma semântica, adaptada ao React Native (AsyncStorage em vez de localStorage, um flush em background em vez de sendBeacon). Para navegadores use @kilden/sdk; para o seu backend use um SDK de servidor.

Autocapture, session replay e plugins são só web por enquanto; este SDK não os inclui.

Terminal window
npx expo install @kilden-io/expo expo-crypto @react-native-async-storage/async-storage

Bare React Native (sem Expo) também funciona: cada binding de plataforma é uma dependência branda. Sem expo-crypto o SDK cai para qualquer polyfill global de crypto.getRandomValues (p. ex. react-native-get-random-values); sem AsyncStorage ele avisa e mantém a identidade em memória, então os ids não sobrevivem a um reinício do app.

import kilden from "@kilden-io/expo";
kilden.init("YOUR_WRITE_KEY");
kilden.track("order_completed", { revenue: 99.9, currency: "CLP" });
kilden.screen("Checkout", { step: 2 });

O export padrão é um singleton — chame init uma vez e importe onde quiser. Chamadas feitas antes do init são guardadas e reproduzidas em ordem; leituras de flags antes do init resolvem para o seu default. Se precisar de clientes isolados (testes, múltiplos projetos), use createClient(writeKey, options).

Use a write key pública do seu projeto (wk_…). Nunca embarque uma key secreta (sk_…) em um app: qualquer coisa dentro de um bundle pode ser extraída, e uma key secreta vazada permite a qualquer um escrever eventos de servidor verificados no seu projeto. O construtor rejeita keys secretas de imediato — a imagem espelhada dos SDKs de servidor, que rejeitam as públicas. O modelo completo está em níveis de confiança.

Método O que faz
init(writeKey, options?) Inicializa o singleton. Ver Configuração
track(event, properties?, options?) Enfileira um evento. options aceita timestamp e uuid explícitos
screen(name, properties?, options?) Registra uma visualização de tela: um evento $screen com $screen_name
identify(distinctId, traits?, options?) Liga o usuário anônimo ao seu id de usuário. Ver Identidade
alias(aliasId) Liga outro id conhecido à identidade atual (emite $alias)
reset() Logout: id anônimo novo, token de identidade e cache de flags limpos
getDistinctId() Distinct id atual. Async — espera a hidratação do storage
setIdentityToken(token) Define ou limpa o JWT de verificação de identidade
isFeatureEnabled(key, options?) / getFeatureFlag(key, options?) Feature flags, avaliadas remotamente. Async — ver Feature flags
flush() Força o envio da fila
close() Flush final com deadline de 10 segundos, depois o client fica inerte

As garantias são as do SDK web: a API pública nunca lança depois da construção, seus dados nunca são mutados, e cada evento carrega um UUID v7 gerado no cliente para que os retries sejam idempotentes. O formato de wire, a política de retry e o comportamento do payload seguem o kilden-sdk-spec — a mesma autoridade contra a qual os SDKs de servidor são testados.

Os usuários começam anônimos: um id anon_ + UUID v7, gerado na primeira execução e persistido no AsyncStorage. Quando fazem login:

kilden.identify("user_42", { plan: "pro", email: "[email protected]" });

identify liga o histórico anônimo ao seu id de usuário, com a mesma semântica do grafo de pessoas da web. No logout:

kilden.reset();

reset rotaciona para uma identidade anônima nova e descarta o token de identidade e o cache de flags. Se você pular isso, o próximo login naquele dispositivo fica ligado ao rastro anônimo do usuário anterior.

Diferente do SDK web, este SDK também expõe alias(aliasId): emite $alias, ligando outro id conhecido à identidade atual sem mudar o estado local. A maioria dos apps só precisa de identify.

Eventos de cliente são não verificados por padrão — qualquer um pode extrair sua write key pública do bundle do app. Para obter eventos verified: true (exigidos pelo messenger, respeitados pelos gatilhos de campanhas), seu backend assina um JWT de vida curta para o usuário logado e o SDK o carrega com cada batch:

kilden.init("YOUR_WRITE_KEY", {
getIdentityToken: async () => {
const response = await fetch("https://your-backend.example/kilden/identity", {
method: "POST",
headers: { Authorization: `Bearer ${sessionToken}` }, // o token de sessão do seu app
});
if (!response.ok) return null;
const { token } = await response.json();
return token;
},
});

O SDK atualiza o token cerca de 60 segundos antes de expirar e uma vez ao receber um 401. Os SDKs de servidor te dão o endpoint de assinatura em três linhas — o kilden/laravel traz POST /kilden/identity pronto. Modelo completo: verificação de identidade.

Avaliação remota contra o /decide, com cache de 30 segundos por identidade:

if (await kilden.isFeatureEnabled("new_checkout")) {
renderNewCheckout();
}
const variant = await kilden.getFeatureFlag("checkout_test", {
personProperties: { plan: "pro" }, // só esta avaliação; ignora o cache
default: "control", // devolvido quando o Kilden não consegue responder
});

Leituras de flags nunca lançam e nunca fazem retry — uma resposta atrasada de flag é inútil, então uma leitura que falha devolve o seu default (false se você não definiu um). identify() e reset() invalidam o cache, então os valores convergem para a nova identidade na hora. A primeira leitura de cada flag emite um evento de exposição $feature_flag_called. A semântica de segmentação e bucketing está no guia de feature flags.

Os eventos ficam em fila na memória e são enviados a cada 5 segundos, ao chegar a 20 eventos enfileirados, e quando o app sai do primeiro plano (via AppState — React Native não tem sendBeacon, então o flush em background é o substituto mobile). A entrega faz retry com backoff exponencial e respeita Retry-After. A fila é limitada a 10.000 eventos; no limite o evento novo é descartado, nunca o histórico.

Por padrão a fila vive em memória: eventos ainda enfileirados quando o OS mata o app são perdidos (React Native não expõe um sinal de “o app vai terminar” — o flush em background é o último hook confiável). Defina persistQueue: true para escrever a fila write-through no AsyncStorage: eventos não entregues são restaurados e enviados no próximo launch. A entrega é at-least-once — o Kilden dedupa pelo uuid do evento, então um batch que estava em voo durante um kill nunca conta em dobro. Chame flush() em checkpoints naturais, e close() se o seu app tiver um ponto de shutdown real — ele drena a fila com um deadline de 10 segundos e deixa o client inerte.

Todas as opções com seus defaults:

kilden.init("YOUR_WRITE_KEY", {
apiHost: "https://ingest.kilden.io",
flushAt: 20, // tamanho de fila que dispara um flush
flushIntervalMs: 5000, // flush periódico
maxQueueSize: 10000, // teto duro; no teto o evento NOVO é descartado
requestTimeoutMs: 10000, // por request HTTP
debug: false, // logging verboso + avisos de prefixo $
enabled: true, // false transforma o client inteiro em um no-op
persistQueue: false, // true = a fila sobrevive ao OS matar o app (restaurada e entregue no próximo launch)
});

O resto são pontos de injeção e encanamento de identidade:

Opção O que faz
identityToken JWT de identidade inicial, se você já tem um no init
getIdentityToken Fetcher async do token, chamado 60 s antes de expirar e em um 401. Ver verificação de identidade
context () => Properties mesclado em cada evento como properties de sistema extras (as properties explícitas do evento ganham)
storage Override de KeyValueStorage; por padrão AsyncStorage
transport Override de Transport; por padrão fetch
getRandomValues Override de entropia; por padrão expo-crypto, depois o crypto.getRandomValues global
appState Override da fonte de ciclo de vida; por padrão o AppState do React Native

Os pontos de injeção existem para o core rodar em qualquer lugar — bare React Native, Expo Web, testes em Node. Por padrão cada evento carrega contexto do dispositivo: $os, $os_version, $device_type, $screen_width, $screen_height, mais $lib e $lib_version.