Pular para o conteúdo
Todos os artigos

Guias do produto

Como adicionar prova social a um app Next.js

Como instalar as notificações de compra da Provedly e um contador de visitantes ao vivo em um app Next.js, lidar com mudanças de rota e enviar o id do visitante à Stripe.

Equipe Provedly··6 min de leitura

A Provedly roda em um app Next.js com uma única tag de script, carregada uma vez no layout raiz. O widget é renderizado dentro de um Shadow DOM, então não interfere no seu Tailwind nem nos seus CSS Modules, e o loader é idempotente entre mudanças de rota no cliente. O único trabalho específico do Next é decidir onde colocar a tag e, se você quiser atribuição, repassar o id do visitante para o seu checkout.

A instalação em uma linha

Crie um widget no dashboard, copie o token e adicione o script ao layout raiz. Com o App Router, next/script é o jeito mais limpo de fazer isso.

// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({
    children,
}: {
    children: React.ReactNode;
}) {
    return (
        <html lang="en">
            <body>
                {children}
                <Script
                    src="https://provedly.app/w/widget.js"
                    data-token="pp_your_token"
                    strategy="afterInteractive"
                />
            </body>
        </html>
    );
}

afterInteractive carrega o script depois da hidratação, que é o equilíbrio certo para um elemento não crítico. Não use beforeInteractive; nada em uma notificação de compra precisa bloquear a página. O bundle tem cerca de 6 KB com gzip e o loader busca a configuração do widget em GET /api/w/{token}/config, que retorna as configurações e até 30 registros recentes.

Se você ainda usa o Pages Router, coloque o mesmo <Script> em pages/_app.tsx. O comportamento é idêntico.

Mudanças de rota e o problema das SPAs

As notificações seguem limites por sessão: por padrão, 3 segundos de espera inicial, 6 segundos na tela, 30 segundos de intervalo e no máximo 5 notificações por sessão. Esses limites são controlados pelo widget, não pela página, então um visitante que navega por cinco páginas de produto não ganha cinco ciclos novos. Isso é intencional. Uma notificação que dispara de novo a cada navegação é o caminho mais rápido para ser ignorada como spam.

O loader verifica se já existe uma instância antes de inicializar, então mesmo que o seu layout remonte a tag de script, nada é renderizado duas vezes. Se preferir montá-lo a partir de um client component, o padrão documentado é este:

'use client';
import { useEffect } from 'react';

export function ProofWidget() {
    useEffect(() => {
        if (document.querySelector('script[data-token="pp_your_token"]'))
            return;
        const s = document.createElement('script');
        s.src = 'https://provedly.app/w/widget.js';
        s.dataset.token = 'pp_your_token';
        s.async = true;
        document.body.appendChild(s);
    }, []);
    return null;
}

Renderize <ProofWidget /> uma única vez, no layout raiz. A segmentação por URL (todas as páginas, só estas, todas exceto) é configurada no dashboard, então você não precisa de renderização condicional no React para manter o widget fora de, por exemplo, /account.

Estilo: o que você controla e o que não controla

Como o widget vive em um Shadow DOM, o seu CSS global não o alcança e o CSS dele não alcança você. Isso elimina as colisões de nomes de classe e as surpresas de z-index de sempre. Em vez disso, você escolhe o visual no dashboard: um de cinco temas (Clean white, Deep ocean, Midnight, Electric violet, Sunset blaze), o formato do nome, o formato da localização e a posição. Leia Shadow DOM: por que o widget não consegue quebrar o seu CSS se quiser os detalhes.

Se você usa uma Content Security Policy rígida, libere https://provedly.app em script-src e connect-src. O widget faz requisições aos endpoints de config, track e presence nessa origem e em nenhuma outra.

Como tornar as compras "verificadas"

Uma notificação que diz "Compra verificada" é uma notificação que chegou por um webhook assinado. Para um app Next.js que cobra pelo Stripe Checkout, isso significa registrar https://provedly.app/api/hooks/stripe/{token} como endpoint de webhook para checkout.session.completed e colar o segredo de assinatura na aba Data do widget. O passo a passo completo está em Webhooks da Stripe para compras verificadas.

Se você cobra pelo seu próprio backend, ou por um provedor sem webhook da Provedly, envie os registros a partir de um Route Handler ou server action:

// app/api/orders/route.ts, after payment is confirmed
await fetch('https://provedly.app/api/v1/widgets/pp_your_token/records', {
    method: 'POST',
    headers: {
        Authorization: 'Bearer ' + process.env.PROVEDLY_API_KEY,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        name: order.customerName,
        city: order.shipping.city,
        country: order.shipping.countryCode,
        product_name: order.lines[0].title,
        price: order.totalFormatted,
        external_id: order.id,
        visitor: order.provedlyVisitor,
    }),
});

Registros enviados assim são exibidos, mas com o rótulo "Imported", nunca "Verified". Essa é a regra de honestidade: só um evento assinado criptograficamente pelo provedor de pagamento ganha o selo. Veja Como usar a Records API para compras do seu próprio backend.

Atribuição: repasse o id do visitante

O dashboard mostra os pedidos assistidos pela prova social, ou seja, um comprador que viu uma notificação antes de comprar, identificado pelo id do visitante dentro de uma janela de 30 dias. Para que essa correspondência aconteça, a compra precisa levar o id. No cliente, leia-o com window.Provedly?.visitorId() e envie-o ao seu código de checkout. Com a Stripe, passe-o como metadata.provedly_visitor ao criar a Checkout Session. Com a Records API, envie-o no campo visitor.

Etapa Onde O que enviar
Ler o id client component no checkout window.Provedly?.visitorId()
Stripe Checkout servidor, criação da sessão metadata: { provedly_visitor: id }
Records API servidor, depois do pagamento "visitor": id

Sem id, sem atribuição. O dashboard nunca faz estimativas.

Checklist antes de publicar

  • Script no layout raiz com strategy="afterInteractive".
  • Domínio de produção adicionado aos domínios permitidos do site; adicione explicitamente os hosts de preview e staging, porque os previews *.vercel.app não correspondem ao seu domínio de produção.
  • CSP atualizada, se você tiver uma.
  • Webhook registrado (Stripe) ou Records API integrada (backend próprio).
  • Id do visitante repassado no checkout.

Perguntas frequentes

O widget funciona com React Server Components?

Sim. A tag de script é HTML puro gerado pelo layout; ela não precisa de um client boundary. O componente opcional ProofWidget só é um client component porque usa useEffect.

A notificação vai causar mudança de layout?

Não. O widget tem posição fixa dentro do próprio shadow root e não ocupa espaço no fluxo do documento, então não contribui para o CLS.

Posso exibi-lo só nas páginas de marketing e não dentro do app?

Sim. Use a segmentação por URL no dashboard ("all except" com /app/*, ou "only these" com os caminhos de marketing) em vez de renderização condicional.

Comece no plano Free, que inclui compras verificadas e 2.000 impressões por mês: crie uma conta.

next.jsinstalaçãoreact
CompartilharXLinkedInFacebookRedditHacker News

Receba novos artigos por e-mail

Prova social honesta, compras verificadas e o que realmente aumenta a conversão. No máximo alguns e-mails por mês; saia com um clique.

Enviamos um e-mail para confirmar. Seu endereço é usado só para esta newsletter; veja a política de privacidade (em inglês).

Mostre provas que você pode sustentar.

Plano gratuito, um site, 2,000 impressões por mês e compras verificadas incluídas. No plano gratuito, o selo leva para a sua página de verificação, e a ideia é justamente essa.