You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@solucx/react-native-solucx-widget

Package Overview
Dependencies
Maintainers
2
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solucx/react-native-solucx-widget

The React Native SDK for Solucx Widget

latest
npmnpm
Version
2.0.7
Version published
Weekly downloads
304
-61.76%
Maintainers
2
Weekly downloads
 
Created
Source

@solucx/react-native-solucx-widget

React Native Expo TypeScript

Widget React Native para coleta de feedback e pesquisas de satisfacao, desenvolvido pela SoluCX.

Instalacao

npm install @solucx/react-native-solucx-widget

Inicio Rapido

Voce pode integrar o widget de duas formas:

  • Por funcao: monta um SoluCXWidgetHost no root e dispara a exibicao com SoluCXWidget.create(...).show().
  • Por componente: renderiza SoluCXWidget diretamente no JSX, no ponto exato em que o widget deve aparecer.

1. Uso por funcao: adicione o SoluCXWidgetHost no root do app

O SoluCXWidgetHost deve ser montado uma unica vez no componente raiz da aplicacao. Ele e responsavel por renderizar o widget quando solicitado via SoluCXWidget.create(...).show().

// App.tsx
import { SoluCXWidgetHost } from '@solucx/react-native-solucx-widget';

export default function App() {
  return (
    <>
      <NavigationContainer>
        <Stack.Navigator>{/* suas telas */}</Stack.Navigator>
      </NavigationContainer>

      {/* Obrigatorio: monte uma vez no root */}
      <SoluCXWidgetHost />
    </>
  );
}

2. Uso por funcao: dispare o widget em qualquer tela

Use SoluCXWidget.create() para construir e exibir o widget. As opcoes de supressao (dias de espera) sao opcionais — se nao forem passadas, o widget as busca automaticamente do painel de configuracao da jornada (configurado remotamente).

// CheckoutScreen.tsx
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

function onCheckoutComplete() {
  SoluCXWidget
    .create('SUA_CHAVE_SOLUCX')
    .setType('modal')
    .setData({
      journey: 'pos_venda',
      user_id: 'user_123',
      email: 'cliente@email.com',
      name: 'Joao Silva',
    })
    .show();
}

Pronto! O widget vai buscar as configuracoes de supressao remotamente e decidir se deve exibir ou nao.

3. Uso por componente: renderize o widget diretamente no JSX

Quando voce quiser controlar a exibicao pelo proprio componente React, use SoluCXWidget. Nesse modo, nao e necessario montar SoluCXWidgetHost.

// CheckoutScreen.tsx
import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

export function CheckoutScreen() {
  return (
    <SoluCXWidget
      soluCXKey="SUA_CHAVE_SOLUCX"
      type="inline"
      data={{
        journey: 'pos_venda',
        user_id: 'user_123',
        email: 'cliente@email.com',
        name: 'Joao Silva',
      }}
      callbacks={{
        onOpened: (userId) => {
          console.log('Widget exibido para:', userId);
        },
      }}
    />
  );
}

Exemplos Completos

Exemplo 1: Uso minimo (opcoes configuradas remotamente)

Este e o caso de uso mais comum. As regras de supressao (quantos dias esperar apos cada evento) sao configuradas no painel de configuracao da jornada e buscadas automaticamente pelo widget. Voce nao precisa passar nenhuma opcao.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

// Disparar apos uma compra
function afterPurchase() {
  SoluCXWidget
    .create('SUA_CHAVE_SOLUCX')
    .setType('bottom')
    .setData({
      journey: 'pos_venda',
      user_id: 'user_123',
      email: 'cliente@email.com',
      name: 'Joao Silva',
      store_id: 'loja_01',
    })
    .show();
  // As opcoes de supressao serao buscadas automaticamente da API
  // com base na configuracao da jornada "pos_venda"
}

Exemplo 2: Com callbacks para monitorar eventos

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

function showSurvey() {
  SoluCXWidget
    .create('SUA_CHAVE_SOLUCX')
    .setType('modal')
    .setData({
      journey: 'atendimento',
      user_id: 'user_456',
      email: 'maria@email.com',
      name: 'Maria Santos',
      employee_id: 'atendente_01',
      employee_name: 'Carlos',
    })
    .setCallbacks({
      onPreOpen: (userId) => {
        console.log('Preparando widget para:', userId);
      },
      onOpened: (userId) => {
        console.log('Widget exibido para:', userId);
        analytics.track('survey_shown', { userId });
      },
      onBlocked: (reason) => {
        // Widget nao foi exibido por causa de uma regra de supressao
        console.log('Widget bloqueado:', reason);
        // Ex: "BLOCKED_BY_WIDGET_DISMISS_INTERVAL"
      },
      onClosed: () => {
        console.log('Usuario fechou o widget');
      },
      onCompleted: (userId) => {
        console.log('Pesquisa respondida por:', userId);
        analytics.track('survey_completed', { userId });
      },
      onPartialCompleted: (userId) => {
        console.log('Pesquisa parcialmente respondida por:', userId);
      },
      onError: (message) => {
        console.error('Erro no widget:', message);
      },
    })
    .show();
}

Exemplo 3: Com opcoes locais (sobrescrevendo configuracao remota)

Se voce precisar sobrescrever as configuracoes da jornada para um caso especifico, passe as opcoes diretamente. Quando setOptions() e chamado, o widget nao busca configuracoes da API e usa os valores fornecidos.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

function showUrgentSurvey() {
  SoluCXWidget
    .create('SUA_CHAVE_SOLUCX')
    .setType('modal')
    .setData({
      journey: 'nps_trimestral',
      user_id: 'user_789',
      email: 'pedro@email.com',
    })
    .setOptions({
      height: 600,
      maxAttemptsAfterDismiss: 5,        // Máximo de 5 tentativas para essa jornada
      waitDaysAfterWidgetDismiss: 90,    // Esperar 90 dias após o usuário fechar
      waitDaysAfterWidgetSubmit: 30,     // Esperar 30 dias após resposta completa
      waitDaysAfterWidgetDisplay: 7,     // Esperar 7 dias após qualquer exibição
    })
    .setCallbacks({
      onOpened: (userId) => console.log('Abriu:', userId),
      onCompleted: (userId) => console.log('Respondeu:', userId),
    })
    .show();
}

Exemplo 4: Diferentes tipos de widget

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

const data = {
  journey: 'pos_venda',
  user_id: 'user_123',
  email: 'cliente@email.com',
};

// Bottom: barra fixa na parte inferior (padrao)
SoluCXWidget.create('KEY').setType('bottom').setData(data).show();

// Top: barra fixa no topo
SoluCXWidget.create('KEY').setType('top').setData(data).show();

// Modal: sobreposicao centralizada que bloqueia o fundo
SoluCXWidget.create('KEY').setType('modal').setData(data).show();

// Inline: integrado ao fluxo do layout (respeita a posicao no JSX)
SoluCXWidget.create('KEY').setType('inline').setData(data).show();

Exemplo 5: Fechar o widget programaticamente

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

// Fechar o widget a qualquer momento
function handleTimeout() {
  SoluCXWidget.dismiss();
}

Exemplo 6: Consultar logs de supressao

Os metodos de log sao metodos de instancia — usam os dados do builder (instanceKey do create(), journey e userId do setData()) para identificar automaticamente qual registro acessar. Nao e necessario passar esses parametros novamente.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

// Cria a instancia com os dados que identificam o registro
const widget = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

// Consultar os logs de supressao
const logs = await widget.getWidgetLogs();
console.log(logs);
// {
//   attempts: 3,                       // quantas vezes o widget foi exibido nesta experiencia
//   answeredTransactionIds: ['txn-1'], // transacoes que ja responderam e nao devem reabrir o widget
//   lastExperienceId: 'pos_venda',     // ultima jornada associada ao contador
//   lastDisplayAttempt: 1741000000000, // ultima tentativa de exibicao bloqueada
//   lastFirstAccess: 1740000000000,    // primeira vez que o widget foi exibido
//   lastDisplay: 1741000000000,        // ultima exibicao do widget
//   lastDismiss: 1741000000000,        // ultima vez que o usuario fechou
//   lastSubmit: 0,                     // ultimo envio completo
//   lastPartialSubmit: 0,              // ultimo envio parcial
// }

Exemplo 7: Sobrescrever datas de eventos (debug/teste)

Use overrideTimestamp para simular cenarios de teste sem esperar os dias reais.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

const widget = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

// Informar primeiro acesso do usuário 
await widget.overrideTimestamp('lastFirstAccess', new Date('2026-01-01T00:00:00Z'));

// Ou usar timestamp em milissegundos diretamente
await widget.overrideTimestamp('lastFirstAccess', 1700000000000);

// Resetar um campo para "nunca aconteceu" (valor 0)
await widget.overrideTimestamp('lastSubmit', 0);

// Depois de sobrescrever, pode exibir o widget normalmente
widget.show();

Campos disponiveis para overrideTimestamp:

CampoDescricao
lastDisplayAttemptUltima tentativa de exibicao (widget foi bloqueado)
lastFirstAccessPrimeira vez que o widget foi exibido para o usuario
lastDisplayUltima exibicao do widget
lastDismissUltima vez que o usuario fechou o widget
lastSubmitUltimo envio completo da pesquisa
lastPartialSubmitUltimo envio parcial da pesquisa
answeredTransactionIdsLista de transaction_id que ja responderam e devem ser bloqueados localmente

Exemplo 8: Limpar logs de supressao

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

const widget = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

// Limpar TODOS os logs (reseta contadores e timestamps)
await widget.clearWidgetLogs();

// Apos limpar, o widget vai se comportar como se nunca tivesse sido exibido
widget.show();

Exemplo 9: Forcar exibicao do widget (ignorar bloqueio)

Se o widget esta sendo bloqueado por uma regra de supressao e voce quer forca-lo a exibir (por exemplo, para testes), sobrescreva a data do evento que esta bloqueando:

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

const widget = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

// Verificar qual evento esta bloqueando
const logs = await widget.getWidgetLogs();
console.log('Ultimo dismiss:', new Date(logs.lastDismiss));
console.log('Tentativas:', logs.attempts);

// Resetar o dismiss para desbloquear
await widget.overrideTimestamp('lastDismiss', 0);

// Agora o widget vai exibir (se nao houver outra regra bloqueando)
widget.show();

Exemplo 10: Isolamento por jornada — dois widgets independentes

Cada combinacao de instanceKey + journey + userId tem seus proprios logs. Widgets de jornadas diferentes nao interferem entre si.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

// Widget da jornada "pos_venda"
const widgetPosVenda = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

// Widget da jornada "atendimento"
const widgetAtendimento = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'atendimento', user_id: 'user_123' });

// Os logs sao independentes:
const logsPosVenda = await widgetPosVenda.getWidgetLogs();
const logsAtendimento = await widgetAtendimento.getWidgetLogs();
// logsPosVenda pode ter 5 tentativas enquanto logsAtendimento tem 0

// Limpar os logs de uma jornada NAO afeta a outra
await widgetPosVenda.clearWidgetLogs();
// Apenas os logs de pos_venda foram resetados

Exemplo 11: Widget sem userId (dispositivo anonimo)

Quando nao ha user_id, email ou cpf, os logs sao compartilhados por todos os usuarios daquela jornada naquele dispositivo.

import { SoluCXWidget } from '@solucx/react-native-solucx-widget';

// Sem userId — logs sao por instanceKey:journey (compartilhado no dispositivo)
const widget = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda' });

const logs = await widget.getWidgetLogs();
// Chave de armazenamento: "SUA_CHAVE_SOLUCX:pos_venda"

// Com userId — logs sao por instanceKey:journey:userId (isolado por usuario)
const widgetComUser = SoluCXWidget
  .create('SUA_CHAVE_SOLUCX')
  .setData({ journey: 'pos_venda', user_id: 'user_123' });

const logsComUser = await widgetComUser.getWidgetLogs();
// Chave de armazenamento: "SUA_CHAVE_SOLUCX:pos_venda:user_123"

Opcoes de Supressao (waitDays)

Importante: Voce nao precisa passar essas opcoes no codigo. Elas podem (e devem) ser configuradas remotamente no painel de configuracao da jornada. O widget busca automaticamente as configuracoes da API quando setOptions() nao e chamado.

As opcoes controlam quantos dias o widget deve esperar apos cada tipo de evento antes de exibir novamente:

OpcaoDescricao
enabledHabilita/desabilita o widget. Quando false, bloqueia imediatamente sem validar outras regras
samplingPercentagePorcentagem de usuarios que verao o widget (0-100). Valor 100 ou undefined = sem amostragem
maxAttemptsAfterDismissNumero maximo de tentativas de exibicao por experiencia
waitDaysAfterWidgetDisplayAttemptDias apos uma tentativa de exibicao bloqueada
waitDaysAfterWidgetFirstAccessDias apos o primeiro acesso do usuario a jornada
waitDaysAfterWidgetDisplayDias apos qualquer exibicao do widget
waitDaysAfterWidgetDismissDias apos o usuario fechar o widget
waitDaysAfterWidgetSubmitDias apos o usuario responder a pesquisa
waitDaysAfterWidgetPartialSubmitDias apos o usuario responder parcialmente

Regras:

  • enabled: false bloqueia o widget imediatamente com BLOCKED_BY_DISABLED, sem verificar nenhuma outra regra
  • enabled: true ou undefined = widget habilitado (comportamento padrao)
  • samplingPercentage: sorteia se o usuario vera o widget. Ex: 50 = 50% de chance. Valor 100 ou undefined = todos veem. Valor 0 = ninguem ve
  • Valor 0 ou undefined nos campos de dias = sem restricao (o campo nao bloqueia)
  • Se qualquer regra bloquear, o widget nao exibe e chama onBlocked(reason)
  • Quando bloqueado, o reason indica qual regra bloqueou (ex: "BLOCKED_BY_WIDGET_DISMISS_INTERVAL")
  • maxAttemptsAfterDismiss conta quantas vezes o widget foi exibido para aquela experiencia (jornada). Se o ID da experiencia (journey ou form_id) mudar, o contador de tentativas e resetado automaticamente
  • Quando o usuario engaja na pesquisa (QUESTION_ANSWERED, envio completo ou envio parcial), o contador de tentativas tambem e resetado para nao bloquear exibicoes futuras por tentativas antigas
  • Quando existe transaction_id e essa transacao ja foi concluida ou parcialmente concluida antes, o widget bloqueia localmente e nao faz chamadas de opcoes nem de preflight

API Completa

SoluCXWidget (classe principal)

Metodos de construcao (builder pattern)

MetodoDescricao
SoluCXWidget.create(soluCXKey)Cria uma nova instancia do widget
.setType(type)Define o tipo: 'bottom', 'top', 'modal', 'inline'
.setData(data)Define os dados do usuario/transacao
.setOptions(options)Define opcoes locais (opcional - se nao chamar, busca da API)
.setCallbacks(callbacks)Define callbacks de eventos
.show()Exibe o widget

Metodos estaticos

MetodoDescricao
SoluCXWidget.dismiss()Fecha o widget programaticamente

Metodos de instancia (log management)

Usam os dados do builder (instanceKey, journey, userId) para acessar os logs da combinacao correta.

MetodoDescricao
.getWidgetLogs()Retorna os logs de supressao
.overrideTimestamp(field, date)Sobrescreve uma data de evento (debug/teste)
.clearWidgetLogs()Limpa todos os logs

Isolamento de armazenamento: Os logs sao isolados por instanceKey:journey:userId. Um app com 2 widgets de jornadas diferentes tera dados de supressao independentes. O userId e opcional — quando presente, os logs sao por usuario.

SoluCXWidgetHost (componente React)

Componente que deve ser montado uma vez no root do app quando a integracao for feita por funcao com SoluCXWidget.create(...).show(). Nao e necessario ao usar SoluCXWidgetView diretamente.

import { SoluCXWidgetHost } from '@solucx/react-native-solucx-widget';

// No root do app
<SoluCXWidgetHost />

SoluCXWidgetView (componente React)

Componente para uso direto no JSX. Pode ser usado no lugar do fluxo por funcao quando fizer mais sentido controlar a renderizacao pelo componente.

import { SoluCXWidgetView } from '@solucx/react-native-solucx-widget';

<SoluCXWidgetView
  soluCXKey="SUA_CHAVE_SOLUCX"
  type="inline"
  data={{ journey: 'pos_venda', user_id: 'user_123' }}
/>

Props:

PropDescricao
soluCXKeyChave de instancia do widget
typeTipo do widget: 'bottom', 'top', 'modal', 'inline'
dataDados do usuario/transacao
optionsOpcoes locais de configuracao e supressao
callbacksCallbacks de ciclo de vida e eventos

WidgetData

interface WidgetData {
  journey?: string;          // Nome da jornada (obrigatorio na pratica)
  user_id?: string;          // ID do usuario
  email?: string;            // Email do usuario
  name?: string;             // Nome do usuario
  cpf?: string;              // CPF
  document?: string;         // Documento
  phone?: string;            // Telefone
  phone2?: string;           // Telefone secundario
  birth_date?: string;       // Data de nascimento (YYYY-MM-DD)
  transaction_id?: string;   // ID da transacao
  customer_id?: string;      // ID do cliente
  store_id?: string;         // ID da loja
  store_name?: string;       // Nome da loja
  employee_id?: string;      // ID do funcionario
  employee_name?: string;    // Nome do funcionario
  amount?: number;           // Valor da transacao
  score?: number;            // Score
  [key: `param_${string}`]: string | number | undefined;  // Parametros customizados
}

WidgetCallbacks

interface WidgetCallbacks {
  onPreOpen?: (userId: string) => void;        // Antes de abrir
  onOpened?: (userId: string) => void;         // Widget aberto
  onBlocked?: (reason: BlockReason) => void;   // Widget bloqueado por regra de supressao
  onClosed?: () => void;                       // Usuario fechou
  onCompleted?: (userId: string) => void;      // Pesquisa respondida
  onPartialCompleted?: (userId: string) => void; // Pesquisa parcialmente respondida
  onError?: (message: string) => void;         // Erro no widget
  onPageChanged?: (page: string) => void;      // Pagina mudou
  onQuestionAnswered?: () => void;             // Pergunta respondida
  onResize?: (height: string) => void;         // Widget redimensionou
}

WidgetOptions

interface WidgetOptions {
  enabled?: boolean;  // Habilita/desabilita o widget (default: true). Quando false, bloqueia sem validar.
  samplingPercentage?: number;  // Porcentagem de usuarios que verao o widget (0-100). Default: 100 (todos).
  height?: number;  // Altura fixa em pontos (se nao informado, altura dinamica)
  maxAttemptsAfterDismiss?: number;  // Maximo de tentativas por experiencia (0 ou undefined = sem limite)
  // Regras de supressao (opcionais - configuradas remotamente pelo painel da jornada):
  waitDaysAfterWidgetDisplayAttempt?: number;
  waitDaysAfterWidgetFirstAccess?: number;
  waitDaysAfterWidgetDisplay?: number;
  waitDaysAfterWidgetDismiss?: number;
  waitDaysAfterWidgetSubmit?: number;
  waitDaysAfterWidgetPartialSubmit?: number;
}

BlockReason

Valores possiveis retornados no callback onBlocked:

ValorSignificado
BLOCKED_BY_DISABLEDWidget desabilitado (enabled: false)
BLOCKED_BY_SAMPLINGUsuario nao foi selecionado pela amostragem (samplingPercentage)
BLOCKED_BY_MAX_ATTEMPTSNumero maximo de tentativas atingido para esta experiencia
BLOCKED_BY_WIDGET_DISPLAY_ATTEMPT_INTERVALDentro do intervalo apos tentativa de exibicao
BLOCKED_BY_WIDGET_FIRST_ACCESS_INTERVALDentro do intervalo apos primeira visualizacao
BLOCKED_BY_WIDGET_DISPLAY_INTERVALDentro do intervalo apos exibicao
BLOCKED_BY_WIDGET_DISMISS_INTERVALDentro do intervalo apos fechamento
BLOCKED_BY_WIDGET_SUBMIT_INTERVALDentro do intervalo apos envio completo
BLOCKED_BY_WIDGET_PARTIAL_SUBMIT_INTERVALDentro do intervalo apos envio parcial

Fluxo Interno

App chama SoluCXWidget.create('KEY').setData({...}).show()
  |
  v
SoluCXWidgetHost recebe a configuracao
  |
  v
Widget monta e executa bootstrap():
  |
  +-- Se setOptions() FOI chamado --> usa opcoes locais
  +-- Se setOptions() NAO foi chamado --> busca opcoes da API (painel da jornada)
  |
  +-- shouldDisplayWidget() verifica enabled + maxAttemptsAfterDismiss + 6 regras de supressao
  +-- (validacao LOCAL, antes de chamar a API, para reduzir carga no servidor):
  |     +-- Se transaction_id ja respondido --> onBlocked('BLOCKED_BY_TRANSACTION_ALREADY_ANSWERED'), widget NAO exibe
  |     +-- Se enabled === false --> onBlocked('BLOCKED_BY_DISABLED'), widget NAO exibe
  |     +-- Sorteia baseado em samplingPercentage --> se nao selecionado, onBlocked('BLOCKED_BY_SAMPLING')
  |     +-- Se experiencia mudou --> reseta contador de tentativas
  |     +-- Se tentativas >= maxAttemptsAfterDismiss --> onBlocked('BLOCKED_BY_MAX_ATTEMPTS')
  |     +-- Para cada regra: timestamp do evento + dias de espera > agora?
  |     +-- Se QUALQUER regra bloqueia --> onBlocked(reason), widget NAO exibe
  |     +-- Se NENHUMA bloqueia --> continua
  |
  +-- Busca URL do formulario na API (preflight)
  |
  +-- Se EXIBE:
  |     +-- Incrementa contador de tentativas
  |     +-- Salva lastDisplay (e lastFirstAccess na primeira vez)
  |     +-- Renderiza WebView com o formulario
  |     +-- onOpened(userId)
  |
  +-- Eventos do usuario:
        +-- Fecha widget --> salva lastDismiss, onClosed()
      +-- Responde pergunta --> zera contador de tentativas, onQuestionAnswered()
    +-- Responde pesquisa --> zera contador de tentativas, salva transaction_id respondido, salva lastSubmit, onCompleted(userId)
    +-- Resposta parcial --> zera contador de tentativas, salva transaction_id respondido, salva lastPartialSubmit, onPartialCompleted(userId)

Compatibilidade

VersaoReact NativeExpoiOSAndroid
1.0.x0.70+50+11+API 21+

Licenca

Proprietario - SoluCX. Uso restrito a clientes licenciados.

FAQs

Package last updated on 11 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts