Pular para o conteúdo principal

Pendo

Pendo é ferramenta de product analytics + in-app guides / tours / NPS. Não substitui pixel de conversão — mas, diferente do que a versão anterior desta página dizia, o Pendo também recebe eventos de conversão do front (ver "Eventos" abaixo).

Configuração por brand

// overrides/<brand>/app/config/analytics/pendo.ts
import type { PendoConfig } from "~/types/pendo";

export const pendoConfig: PendoConfig = {
enabled: true,
token: "479456b8-d797-4b4a-a03c-b3790265ef4a",
accountId: "cl-bet7k-com",
};

export type { PendoConfig } from "~/types/pendo";
CampoTipoPra quê serve
enabledbooleanMaster switch. false → o hook inteiro é no-op
tokenstring?Agent token do Pendo. Vai no src do script: https://cdn.pendo.io/agent/static/<token>/pendo.js
accountIdstring?Identificador de conta anexado a toda sessão (account.id)

:::danger Não existe apiKey A versão anterior desta página documentava pendoConfig = { enabled, apiKey }. apiKey não existe em PendoConfig (app/types/pendo.ts) — o campo do token chama-se token. Config com apiKey é silenciosamente ignorada e o Pendo não carrega (o hook exige enabled && token && accountId). :::

Default do base: { enabled: false }. Brands opt-in por override.

Brands (estado real)

BrandenabledObservação
cl-bet7k-comtrueligado por decisão de produto
ng-7k-bettrueligado por decisão de produto
7k-bet-brfalsedesligado por decisão de produto (2026-07-16); token/accountId preservados
betpontobet-bet-brfalseidem
demais brandsfalseherdam o default do base (sem override)

As quatro brands com override compartilham o mesmo agent token; o que separa as contas é o accountId.

Religar uma brand desligada = voltar enabled pra true (a config já está lá).

Como carrega — lane exclusiva de interação

Pendo não está na lane deferred junto com Hotjar/RA. Ele tem a sua própria: scheduleThirdPartyOnInteraction, que só libera após a primeira interação real do visitante.

Racional (de AnalyticsLoaders.tsx): Pendo só importa pra usuário engajado. É um deferral honesto, não truque de lab — vale igual pra todo mundo: um visitante real que entra e sai sem interagir também nunca carrega Pendo, e uma auditoria sintética (que nunca interage) se comporta exatamente como essa visita não-engajada. Sem branch específico de bot.

Consequência operacional: se você abre a página e não clica em nada, window.pendo não vai existir. Isso é esperado.

O loader instala um stub com fila (pendo._q) antes do script chegar, então chamadas antecipadas não se perdem.

Identificação do visitante

pendo.initialize({
visitor: { id: <visitorId>, user_id: <numeric id> },
account: { id: pendoConfig.accountId },
autoFrameInstall: true,
frameIdentitySync: true,
})
CampoValor
visitor.ido cactus_id do usuário — string enviada pelo BFF em /auth/user-profile, distinta do AuthUser.id numérico. É o identificador canônico cross-stack usado pelas integrações de terceiro
visitor.id (fallback)quando o usuário autenticado não tem cactus_id — ele é gerado só após KYC, e algumas contas não têm (ex: Nigeria) — cai pro AuthUser.id numérico stringificado, pra que o usuário logado ainda seja identificado em vez de rastreado como anônimo
visitor.user_idsempre o AuthUser.id numérico stringificado quando autenticado. Vai em toda interação coletada (Features no-code e pendo.track()), pra segmento/relatório do lado do Pendo
account.idpendoConfig.accountId

Visita não autenticada manda visitor.id vazio → Pendo rastreia anonimamente.

Em transição de auth (login/logout) o hook re-identifica: prefere pendo.identify() quando o agent expõe, e cai pro initialize() quando não.

Eventos

Seis eventos chegam ao Pendo, por dois caminhos diferentes.

Manuais (emitidos pelo usePendo)

O agent no-code do Pendo não consegue observar estes, então o hook os emite explicitamente via pendo.track():

EventoQuando
app_loadeduma vez por carregamento de documento, logo após o auth hidratar. Cobre primeira visita, F5/reload e navegação externa de volta pro site. Não dispara em navegação SPA (mesmo documento). Params: authenticated, visitor_id
loginquando isAuthenticated transiciona false → true. Param: visitor_id
logoutquando isAuthenticated transiciona true → false

Via matriz de destinos

Três eventos de conversão roteados pelo canal pendo de app/analytics/destinations.ts:

Evento do frontTrack Event no Pendo
sign_upsign_up
deposit_confirmeddeposit_confirmed
withdrawwithdraw

:::note login está fora da matriz de propósito login é emitido reativamente pelo usePendo (na transição de auth). Roteá-lo também pela matriz duplicaria a contagem. É por isso que o slot pendo de login é null em destinations.ts — não é esquecimento. :::

O adapter no-opa quando a brand tem Pendo desligado ou o agent ainda não está pronto.

O que Pendo entrega

  • Tours interativos pra novo usuário (highlight de features)
  • Guias contextuais
  • NPS surveys agendadas
  • Analytics de uso de feature (Features no-code)

Configuração de cada tour é feita no painel Pendo (https://app.pendo.io), não no código.

Pendo escreve cookies próprios pendo_* (formato interno). TTL ~1 ano. Categoria LGPD: outros / marketing.

Como debuggar

window.pendo // SDK (só existe DEPOIS da 1ª interação)
window.pendo._q // fila do stub, antes do agent carregar
window.__pendoInitialized // guard de initialize único

Painel: https://app.pendo.io. Network → filtra pendo.io.

Se window.pendo estiver undefined: (1) interagiu com a página?, (2) a brand tem enabled: true?, (3) token e accountId estão preenchidos?

Anti-patterns

  1. Usar apiKey no config. O campo é token. O hook exige enabled && token && accountId — sem token ele é no-op silencioso.
  2. Tour disparado em todo user, sempre. Anti-UX. Use targeting no painel (só novos users, ou só quem passou por X tela).
  3. Rotear login pela matriz de destinos. Duplica com o evento reativo do hook.
  4. Concluir que Pendo está quebrado porque window.pendo não existe no load. A lane é interaction-only por design.
  5. Confundir NPS do Pendo com NPS do Hotjar. Use um só pra evitar fadiga de pesquisa (hoje o Hotjar está desligado em todas as brands — ver Hotjar).