
De Tickets a Conversas: Aprimorando o Suporte ao Cliente com Gladly
Table of Contents
O suporte ao cliente é uma daquelas áreas onde o conjunto de ferramentas molda não apenas a eficiência do agente, mas toda a qualidade do relacionamento com o cliente. Quando a equipe de CS de um de nossos clientes de e-commerce decidiu que queria mudar para o Gladly, eles tinham uma visão clara: parar de gerenciar tickets e começar a ter conversas.
Fui trazido para lidar com toda a migração do lado da engenharia. Neste post, vou detalhar a implementação técnica, desde a incorporação do widget de chat ao vivo e a conexão de dados do cliente até a configuração da Central de Ajuda de autoatendimento, incluindo algumas pegadinhas que encontrei pelo caminho. Esteja você avaliando o Gladly para sua própria stack ou seja um desenvolvedor curioso sobre o que a integração realmente envolve, espero que isso seja útil.
Um aviso rápido antes de mergulharmos: este não é um anúncio do Gladly. Este é um relato honesto de uma migração específica, em um contexto específico. A relação custo-benefício e a adequação dos recursos podem variar dependendo do tamanho da sua equipe, do volume de suporte e da natureza do seu negócio; outras plataformas ainda são perfeitamente viáveis e podem, na verdade, ser a melhor escolha dependendo da sua situação. Como sempre, faça sua própria avaliação.
Por que Gladly?
As partes interessadas buscavam uma maneira melhor de gerenciar as solicitações de suporte ao cliente, a ferramenta atual não estava mais atendendo e eles queriam uma alternativa. O preço sempre faz parte da conversa nessas decisões, e pode variar bastante dependendo de qual plataforma você escolhe, mas esse não foi o principal motivador aqui. O que finalmente os convenceu a escolher o Gladly foi uma diferença de filosofia: em vez de gerenciar tickets, o Gladly é construído em torno de pessoas e conversas contínuas. Essa é uma mudança de paradigma significativa para uma equipe de CS e estava alinhada com a forma como eles queriam interagir com seus clientes.
O Widget de Chat ao Vivo: Glad App

Uma das partes mais visíveis da integração é o Glad App – o widget de chat ao vivo incorporável da Gladly. O conceito é simples: um pequeno script de configuração define window.gladlyConfig com seu appId, e um script de carregamento minificado busca e inicia o widget a partir do CDN da Gladly. Em HTML puro, você apenas colocaria ambas as tags “ na página e pronto.
Em uma aplicação Next.js, é um pouco mais complexo – e existem algumas armadilhas que vale a pena conhecer antes de começar. As nossas foram agravadas por um desafio extra: a aplicação estava no meio de uma migração do Pages Router para o App Router, o que significava que o componente Glad App precisava funcionar corretamente sob o App Router enquanto o código do Pages Router existente ainda estava presente.
O problema da execução de scripts
A coisa mais importante a entender ao incorporar scripts de terceiros em uma aplicação Next.js é esta: **um e anexado ao DOM. Todo o resto é inerte – aparece no inspetor, parece correto e silenciosamente não faz nada. Sem erro, sem stack trace, apenas ausência. element inserted into the DOM via innerHTML — or React's dangerouslySetInnerHTML — does not execute.** This is defined in the HTML spec. The browser only runs scripts that are either present during initial HTML parsing or explicitly created with document.createElement('script')
É aqui que o Pages Router e o App Router divergem de uma maneira não óbvia.
Sob o Pages Router, next/script possui um runtime maduro e testado em batalha. Para um script inline afterInteractive, ele não depende do React pintando o elemento no DOM – o próprio runtime de cliente do Next pega o conteúdo do script e o injeta como um nó createElement/appendChild real após a hidratação. Portanto, o código inline realmente é executado. É por isso que o GladApp.tsx original funcionava sem problemas: o Next estava lidando com os requisitos do navegador nos bastidores.
O App Router conta uma história diferente. next/script é consideravelmente mais fraco para scripts inline, especialmente quando o componente está localizado profundamente na árvore – o que quase sempre acontece com um widget de chat. beforeInteractive scripts inline só funcionam quando colocados no layout raiz; afterInteractive e lazyOnload scripts inline no App Router frequentemente são renderizados no DOM, mas nunca executados. Então o elemento aparecia no inspetor, parecia perfeitamente correto, e window.gladlyConfig nunca era definido. O widget de chat falhava silenciosamente na inicialização – sem erro, sem stack trace.
É por isso que a abordagem ingênua falha:
// Renders fine in the DOM under the App Router, but never executes
<script dangerouslySetInnerHTML={{ __html: `window.gladlyConfig = { appId: '...' }` }} />window.gladlyConfig permanece undefined, o loader não tem nada para inicializar e o widget de chat nunca aparece.
A Solução: Injeção Imperativa de Script via useEffect
Uma vez que o problema ficou claro, a solução seguiu naturalmente: parar de confiar em next/script e fazer explicitamente o que o runtime do Pages Router fazia implicitamente. Construir os elementos de script manualmente dentro de um useEffect proporciona o comportamento do navegador que você realmente precisa:
useEffect(() => {
if (featureDisabled) return
if (document.getElementById('gladly-sdk')) return // idempotency guard
const config = document.createElement('script')
config.textContent = `window.gladlyConfig = { appId: '${APP_ID}' };`
document.body.appendChild(config) // executes immediately on append
const loader = document.createElement('script')
loader.textContent = `!function(c,n,r,t){...}(window,document,'Gladly','PROD')`
document.body.appendChild(loader) // executes after config
}, [])createElement + appendChild executa código inline. Anexar o script de configuração antes do loader respeita a ordem de inicialização que o snippet da Gladly assume. Ambos os elementos de script recebem atributos id explícitos antes de serem anexados, e é isso que torna a guarda getElementById eficaz: em qualquer renderização subsequente ou mudança de rota, a verificação encontra o elemento existente e interrompe o processo precocemente, evitando a injeção duplicada.
Isso contorna completamente next/script e reproduz em APIs simples de DOM exatamente o que o snippet HTML do fornecedor espera: carregamento de scripts síncrono, ordenado e com execução ao anexar. Isso se generaliza bem além da Gladly; qualquer integração de terceiros que assuma o mundo ordenado e de execução ao analisar do HTML simples é melhor manipulada desta forma ao trabalhar com o App Router.
Customização via Dashboard

Uma vez que o widget está funcionando, a operação é bem simples. Praticamente todas as customizações, cores do widget, posicionamento de botões e visibilidade por página – são gerenciadas pelo Dashboard da Gladly, sem a necessidade de alterações no código do front-end. Quer que o chat apareça apenas em páginas específicas? Feito no Dashboard. Mudança de marca e precisa atualizar a cor de destaque? Dashboard. Esta é uma vitória significativa para equipes que não são de engenharia, que podem iterar na experiência do chat de forma independente, sem abrir um ticket.
Nosso aplicativo de lojas é compartilhado entre vários publishers, e nem todo publisher precisa do widget de chat ativado. Usamos uma feature flag para controlar a visibilidade por publisher no nível do aplicativo; o componente a verifica na montagem e ignora completamente a injeção do SDK se a funcionalidade estiver desligada, mantendo as coisas limpas sem o carregamento de scripts desnecessários.
Outro comportamento nativo que vale destacar: o widget se oculta automaticamente fora do horário de atendimento, quando não há agentes disponíveis. O agendamento é totalmente configurável no Dashboard, e a Gladly cuida de toda a lógica de visibilidade – sem cron jobs, sem necessidade de lógica de negócio customizada do nosso lado.
Finalmente, para páginas onde o posicionamento padrão do widget se sobrepõe à navegação inferior em telas menores, injetamos um pequeno override de CSS com escopo para movê-lo para cima. Ele é aplicado condicionalmente com base na rota atual e removido na navegação, um padrão organizado para ajustes de widget específicos por rota.
Conectando Dados do Cliente: O Lookup Adapter
A parte tecnicamente mais interessante da integração foi conectar o Gladly aos dados de pedidos do nosso cliente por meio do Lookup Adapter – o mecanismo do Gladly para puxar dados externos de clientes e transações diretamente para a visualização do agente.
O Lookup Adapter é uma camada de middleware que o Gladly chama via HTTP GET quando um agente abre o perfil de um cliente. Em vez de fazer com que o Gladly acessasse nossa API principal diretamente, roteamos as solicitações através do nosso aplicativo dedicado de Integrations. O pipeline funciona assim:

O app de Integrations fica no meio por um bom motivo: ele gerencia o limite de taxa (rate limiting), o gerenciamento de desempenho e a segurança, mantendo nossa API protegida de acesso externo direto e nos dando um local limpo para gerenciar autenticação, controle de solicitações e formatação de respostas.
Quando um agente visualiza o perfil de um cliente no Gladly, o Lookup Adapter busca e exibe automaticamente tudo o que a equipe de CS precisa para resolver uma solicitação de suporte, sem trocar de abas ou pesquisar em um sistema separado:
- Dados do perfil do cliente: nome, endereço de e-mail, número de telefone e endereço de entrega
- Detalhes do pedido: número do pedido e status atual do pedido
- Informações do produto: nomes dos produtos adquiridos
- Dados de envio: transportadora e número de rastreamento para produtos físicos
- Atributos de produtos digitais: uma marca customizada indicando se um código de produto digital foi resgatado
Esse último é um ótimo exemplo do recurso de atributos personalizados da Gladly; você pode estender o perfil padrão do cliente com quaisquer dados específicos do domínio que seus agentes precisem. Para o negócio de bens digitais do nosso cliente, saber rapidamente se um cliente já resgatou seu código é a diferença entre uma resolução rápida e idas e vindas desnecessárias.
A Gladly também suporta vinculação automática – quando chega um novo contato, ela pode associar automaticamente o cliente a um registro no seu sistema de registro com base nos identificadores disponíveis, portanto, os agentes geralmente têm o contexto completo do pedido antes mesmo de dizerem olá.
Notas de Implementação
Uma limitação que vale a pena sinalizar: a Gladly impõe uma janela de resposta rigorosa nas chamadas do Lookup Adapter. Se a resposta não retornar a tempo, a requisição expira e o agente não vê nada. Dado que os dados do cliente abrangem múltiplas tabelas – usuários, pedidos, itens de linha, rastreamentos de envio, metadados de venda e mais. Vale a pena ser deliberado sobre como os dados são buscados e montados no lado da API.
Essas são as práticas que mantiveram as coisas funcionando sem problemas.
1. Carregar antecipadamente todo o grafo de associação
O adaptador precisa percorrer uma árvore consideravelmente profunda: usuário → pedidos → itens de linha → rastreamentos de envio → detalhes de venda. Sem o carregamento antecipado (eager loading), cada acesso a associações mais profundas nessa travessia dispara sua própria consulta por registro, o clássico problema N+1. Carregar todas as associações antecipadamente com LEFT JOINs resolve todo o grafo em um conjunto limitado de consultas, em vez de uma por registro.
Na prática, isso se parece com:
User.left_joins(
:profile,
orders: [
:status_transitions,
{ line_items: [:shipment_trackings, { product: :metadata }] }
]
)O construtor de resposta acessa todos os níveis dessa árvore ao construir o payload, detalhes de rastreamento de envio, nomes de produtos, sinalizadores de resgate, estados do pedido, portanto, nenhum desses acessos deve disparar consultas adicionais.
2. Memoizar valores que são usados mais de uma vez
Durante o processo de construção da resposta, diversos valores são computados ou consultados em múltiplos locais. A memoização ao nível da instância (o padrão ||= em Ruby) garante que cada um seja resolvido apenas no primeiro acesso e reutilizado depois disso:
- A própria busca do usuário é memoizada:
performverifica se algum usuário correspondeu, então os construtores de atributos iteram sobre a mesma coleção, tudo a partir de uma única consulta resolvida. - Os pedidos são armazenados em cache por usuário, então, se o mesmo usuário aparecer em múltiplos caminhos de busca, a lista de pedidos não é buscada novamente.
- As URLs das imagens dos produtos são armazenadas em cache por produto — quando o mesmo produto aparece em múltiplos itens de linha, a URL é computada apenas uma vez.
3. Use caminhos rápidos para buscas de registro único
A Gladly normalmente busca um cliente por um único identificador, um endereço de e-mail ou um ID interno. Em vez de sempre emitir uma consulta IN (...) projetada para buscas de múltiplos valores, o adaptador trata esses cenários comuns de registro único com uma consulta LIMIT 1 (find_by no ActiveRecord). O caminho de múltiplos valores ainda existe para casos excepcionais, mas o caminho comum é o mais enxuto possível.
4. Agrupe na memória em vez de fazer viagens de ida e volta ao banco de dados
Ao construir as seções de produtos e cumprimentos da resposta, os dados precisam ser agrupados, por produto e por número de rastreamento, respectivamente. Como os itens de linha já estão carregados na memória a partir da etapa de eager load, esse agrupamento é feito em Ruby (group_by) em vez de emitir consultas GROUP BY adicionais ao banco de dados.
👉 Documentação do Lookup Adapter
FAQs de Autoatendimento: A Central de Ajuda

O terceiro pilar da integração é a Central de Ajuda – o widget de FAQ e base de conhecimento incorporável da Gladly. Assim como o Glad App, ele depende de dois scripts: um script de configuração inline que define window.gladlyHCConfig e um script de carregamento externo obtido do CDN da Gladly (hcl.js). O widget é montado em um elemento DOM específico na página (no nosso caso, um <div id="gladly-help-center" />), cujo seletor faz parte da própria configuração.
O componente GladlyHelpCenter reside no Pages Router, onde o next/script lida com scripts inline de forma confiável, portanto as armadilhas de execução descritas na seção do Glad App não aparecem aqui. A configuração e o carregador externo são ambos declarados com strategy="afterInteractive", que o runtime do Pages Router processa corretamente.
window.gladlyHCConfig especifica o endpoint da API, ID da organização, ID da marca, URL base do CDN e o seletor DOM onde deve ser montado. Suportamos múltiplas marcas na mesma plataforma, cada uma com seu próprio brandId, e alternar entre elas é apenas uma prop.
A verdadeira beleza aqui, novamente, é a independência operacional que isso dá às equipes que não são de engenharia. Todo o conteúdo da Central de Ajuda, seções, FAQs, texto de resposta, colunas de layout e o texto do marcador de pesquisa são gerenciados através do Dashboard da Gladly. Adicionar uma nova categoria de FAQ, atualizar uma resposta após uma mudança de política ou remover conteúdo desatualizado requer zero envolvimento do front-end. A Central de Ajuda também herda o CSS do site anfitrião, portanto ela se integra naturalmente ao design existente sem qualquer trabalho extra de estilização.
👉 Documentação de configuração da Central de Ajuda
Os Resultados: Uma Equipe de CS (e Clientes) Mais Feliz
A integração completa foi concretizada sem problemas, e o feedback da equipe de CS foi imediatamente positivo. Alguns destaques:
A migração de e-mail foi tranquila. O Gladly torna simples o redirecionamento de e-mails recebidos de uma plataforma anterior, então a equipe não perdeu o contexto histórico nem precisou gerenciar duas ferramentas em paralelo durante a transição.
A experiência de CS tornou-se genuinamente mais dinâmica. Em vez de uma fila de e-mail estática, os agentes agora têm chat ao vivo pelo Glad App, uma Central de Ajuda de autoatendimento que reduz o volume de tickets para perguntas comuns e contexto total do pedido via Lookup Adapter — tudo em uma interface unificada. Os clientes recebem um suporte mais rápido e informado. Os agentes gastam menos tempo procurando informações.
O envolvimento da engenharia permaneceu mínimo após o lançamento. Como grande parte da configuração do Gladly fica no Dashboard, a equipe de CS pode ajustar e iterar em suas ferramentas sem esperar por um ciclo de desenvolvimento. Isso é uma vitória para todos.
Se você está considerando uma migração semelhante, o trabalho de integração é mais acessível do que você pode imaginar. A documentação é sólida, as APIs são bem estruturadas e, desde que você esteja ciente das peculiaridades específicas do framework abordadas acima, não há muitas surpresas. Se o Gladly é a escolha certa depende da sua equipe e das suas necessidades, mas se o modelo focado em conversas faz sentido, vale a pena analisar com seriedade.
Fontes
- Gladly Competitors Comparison
- Get Started with Glad App
- Introduction to Lookup Adaptor
- Create and Configure a Help Center
We want to work with you. Check out our Services page!



