> ## Documentation Index
> Fetch the complete documentation index at: https://docs.octasend.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Push

> Notificações no navegador pelo Firebase Cloud Messaging, instaladas pela tag do site (OctaTag) ou por script próprio

O canal **Web Push** entrega notificações no navegador das pessoas que visitam o seu site, pelo Firebase Cloud Messaging (FCM). Ele usa um projeto Firebase **seu**. A instalação no site pode ser feita pela [tag do site (OctaTag)](https://docs.octasend.com.br/plataforma/octatag.md) ou por um script próprio.

**Nenhuma informação da pessoa é coletada antes**: o navegador é registrado com o identificador dela no seu sistema (`user_id`), e é esse mesmo identificador que você usa depois para enviar.

## 1. Configurar o Firebase

Em **Configurações → Canais → Push Notification (Navegador)**, preencha:

| Campo | Onde encontrar |
| - | - |
| Firebase Project ID | ID do projeto no console do Firebase |
| Firebase API Key | Chave de API pública do app web |
| Firebase Auth Domain | Domínio de autenticação (`<projeto>.firebaseapp.com`) |
| Firebase Messaging Sender ID | Sender ID do Cloud Messaging |
| Firebase App ID | ID do app web registrado no projeto |
| Firebase VAPID Key (Web Push) | Chave pública gerada em **Cloud Messaging → Web configuration** |
| Service Account JSON | Credencial de servidor do projeto, usada para enviar as notificações |

* **Testar Conexão** confere a Service Account no Google (exige Project ID e Service Account JSON). Erros comuns: *"Service Account JSON inválido — verifique se o arquivo está correto"* e *"Service Account inválida ou sem permissão no projeto"*.
* Clique em **Salvar Configuração**. Enquanto Project ID, API Key e VAPID Key não estiverem salvos, o guia da tela mostra um aviso para preencher o Firebase antes de instalar no site.
* A Service Account nunca vai para o navegador: o site recebe só as credenciais públicas do Firebase, buscadas da OctaSend no momento do registro. Credenciais já salvas voltam mascaradas na tela — deixe o campo como está para manter o valor.
* Abaixo do formulário fica a seção **Verificação de identidade**, explicada mais adiante nesta página.

## 2. Instalar no site

> [tab] Com a tag do site (OctaTag)
>
> Se a [tag do site](https://docs.octasend.com.br/plataforma/octatag.md) já está instalada, faltam duas coisas: o arquivo do service worker e um botão que peça a permissão.
>
> > [!NOTE]
> >
> > O push pela tag é um **módulo opcional** — fale com a OctaSend para ativar. Ele também depende do canal Web Push configurado e ativo.
>
> **1. Criar o arquivo do service worker**
>
> Crie o arquivo `firebase-messaging-sw.js` na **raiz pública** do seu site (ex.: `https://seusite.com/firebase-messaging-sw.js`) com uma única linha. A tela do canal mostra essa linha pronta, com a chave da sua tag — copie de lá:
>
> ```javascript theme={null}
> importScripts('https://api.octasend.com.br/functions/v1/web-push-sw?t=CHAVE_DA_SUA_TAG')
> ```
>
> Se a tag ainda não estiver instalada, a tela avisa *"Instale a tag da loja para ver a sua chave aqui."* A chave fica em **Configurações → Instalação**.
>
> **2. Pedir a permissão num clique**
>
> O navegador só mostra o pedido de permissão depois de um gesto da pessoa. Chame `registerWebPush` no clique de um botão, com o identificador dela no seu sistema e o `userHash` calculado no seu servidor — nunca na abertura da página:
>
> ```javascript theme={null}
> botao.onclick = () => window.registerWebPush && window.registerWebPush(idDoUsuario, userHash)
> ```
>
> A função só existe quando a tag está carregada e o push está ativo para a conta — por isso o teste antes da chamada. O `userHash` é explicado em **Verificação de identidade**, abaixo. Se você não passar o segundo argumento, a tag usa o `userHash` informado em `octasend('identify', { userId, userHash })`, desde que seja do mesmo `userId`.
>
> Depois que a pessoa aceita, a tag lembra o identificador naquele navegador e refaz o registro sozinha nas visitas seguintes, sem novo pedido de permissão. Se a pessoa recusar, nada é registrado.
>
> > [!NOTE]
> >
> > O push da tag respeita os **domínios autorizados** da conta, a mesma lista dos outros recursos da [tag do site](https://docs.octasend.com.br/plataforma/octatag.md). Num site fora da lista, o navegador não é registrado. Com a lista vazia, o push funciona em qualquer site.
>
> > [!WARNING]
> >
> > Se o site ainda tem o script antigo de push, retire-o depois de instalar a tag: enquanto ele estiver na página, é ele que registra os navegadores, e a tag não interfere.

> [tab] Com script próprio
>
> **1. Criar o arquivo do service worker**
>
> Crie o arquivo `firebase-messaging-sw.js` na **raiz pública** do site com uma linha. A tela do canal mostra essa linha pronta, com o endereço correto — copie de lá e troque apenas `SEU_CLIENT_ID` pelo `client_id` de um OAuth Client (em **Configurações → OAuth Clients**):
>
> ```javascript theme={null}
> importScripts('https://api.octasend.com.br/functions/v1/web-push-sw?t=SEU_CLIENT_ID')
> ```
>
> Não carregue esse arquivo com `<script src>`: ele precisa ser um arquivo estático na raiz. Em Next.js e Create React App, coloque em `/public/firebase-messaging-sw.js`; em outros frameworks, na pasta de arquivos estáticos.
>
> **2. Colar o script de registro**
>
> Copie o **script de registro** do guia na tela do canal e cole no `<head>` ou antes do `</body>` do site, trocando apenas `SEU_CLIENT_ID`.
>
> > [!WARNING]
> >
> > Use só o `client_id`, que é público. **Nunca** coloque o `client_secret` no código do site.
>
> **3. Registrar a pessoa**
>
> Depois do login, chame com o identificador da pessoa e o `userHash` calculado no seu servidor (veja **Verificação de identidade**, abaixo):
>
> ```javascript theme={null}
> registerWebPush('id-do-usuario-123', 'HASH_CALCULADO_NO_SEU_SERVIDOR')
> ```
>
> O script pede a permissão ao navegador, obtém o token do Firebase e registra o vínculo entre o navegador e o `user_id`. O console do navegador mostra *"\[WebPush] Dispositivo registrado com sucesso"* ou, quando o registro é recusado, *"\[WebPush] Registro recusado:"* seguido do código do erro. O registro usa o endpoint [Registrar dispositivo Web Push](https://docs.octasend.com.br/api-reference/web-push-register.md).
>
> > [!WARNING]
> >
> > Um script de registro copiado antes da verificação de identidade chegar ao web push não repassa o `userHash`: o segundo argumento é descartado, sem nenhum erro. Copie de novo o **script de registro** da tela do canal antes de passar o `userHash` e antes de ligar **Exigir verificação de identidade**. Senão, com a exigência ligada, todo registro feito por esse script é recusado.
> >
> > Para saber qual você tem, procure no script por `window.registerWebPush = function (userId, userHash)`. Se aparecer só `function (userId)`, é o antigo. O script antigo mostra *"\[WebPush] Dispositivo registrado com sucesso"* no console mesmo quando o registro é recusado. Isso vale só para o script próprio: a tag do site se atualiza sozinha.

> [!TIP]
>
> Mudou o arquivo do service worker e a notificação continua igual? O navegador pode estar usando a versão antiga em cache. No DevTools, abra **Application → Service Workers → Unregister** e recarregue a página.

## Regras do registro

* **Um navegador por `user_id`**: cada novo registro de uma pessoa substitui o anterior. A notificação vai para o navegador registrado por último.
* **Um `user_id` por navegador**: se outra pessoa registrar o mesmo navegador, o vínculo passa para ela, e a anterior deixa de receber ali.
* O registro só é aceito com o canal Web Push configurado e ativo na conta.
* O registro confere o `userHash` conforme a **Verificação de identidade** da conta, descrita abaixo.
* Quando o Firebase informa que o token de um navegador deixou de valer (a pessoa revogou a permissão ou limpou os dados), o registro é apagado na primeira falha de envio. A pessoa volta a receber quando registrar de novo.

## Verificação de identidade

O identificador da pessoa fica no código do seu site. A verificação de identidade garante que só o próprio usuário registra o navegador dele: o seu servidor assina o `userId` com um segredo da conta, e o site envia essa assinatura, o `userHash`, junto com o `userId`.

O segredo e a exigência são **os mesmos das [notificações in-app](https://docs.octasend.com.br/api-reference/widget-in-app.md)**: um só por conta. A seção **Verificação de identidade** aparece na tela do canal Web Push e na do canal In-app, e o que você fizer numa vale para a outra.

> [!NOTE]
>
> Só usuários **MASTER** da conta veem o segredo, geram um novo e ligam ou desligam a exigência. Para os demais, a seção mostra apenas o aviso *"Só usuários MASTER veem o segredo e ligam a exigência de verificação. Peça a um usuário MASTER da sua conta."* Veja os níveis de acesso em [Configurações](https://docs.octasend.com.br/plataforma/configuracoes.md).

**1. Gere o segredo**

Na seção **Verificação de identidade**, clique em **Gerar segredo**. O segredo aparece mascarado, com um botão para copiar. Guarde-o só no seu servidor, por exemplo numa variável de ambiente. Nunca coloque o segredo no código do site.

**2. Calcule o userHash no seu servidor**

O `userHash` é o HMAC-SHA256 do `userId`, com o segredo como chave, em hexadecimal. Calcule sobre o `userId` exatamente como o site vai enviar, sem espaços no início ou no fim:

```javascript Node.js theme={null}
const crypto = require('crypto')

const userHash = crypto
  .createHmac('sha256', process.env.OCTASEND_IN_APP_SECRET)
  .update(userId)
  .digest('hex')
```

```php PHP theme={null}
<?php
$userHash = hash_hmac('sha256', $userId, getenv('OCTASEND_IN_APP_SECRET'));
```

```python Python theme={null}
import hashlib, hmac, os

user_hash = hmac.new(
    os.environ['OCTASEND_IN_APP_SECRET'].encode(),
    user_id.encode(),
    hashlib.sha256,
).hexdigest()
```

**3. Passe o userHash no registro**

Entregue o valor à página junto com o `userId` e passe como segundo argumento: `registerWebPush(userId, userHash)`. Vale para a tag e para o script próprio. Se o seu site usa o script próprio copiado antes da verificação de identidade, copie de novo o **script de registro** da tela do canal: o antigo descarta o `userHash` (veja **Registrar a pessoa**, na aba **Com script próprio**).

**4. Ligue a exigência**

Quando o seu site já estiver enviando o `userHash`, ligue **Exigir verificação de identidade** na mesma seção. A chave só fica disponível depois que o segredo é gerado.

| Situação | Exigência desligada (padrão) | Exigência ligada |
| - | - | - |
| Sem `userHash` | Registrado | Recusado |
| `userHash` certo | Registrado | Registrado |
| `userHash` errado (de outro `userId` ou de um segredo antigo) | Recusado | Recusado |

* Um `userHash` enviado é sempre conferido, mesmo com a exigência desligada.
* Com `userHash`, o `userId` é usado exatamente como veio. Um `userId` com espaço no início ou no fim é recusado.
* **Gerar novo segredo** invalida na hora todo `userHash` calculado com o anterior. Até o seu servidor usar o segredo novo, o web push não registra navegadores e o sino in-app não carrega. O painel pede confirmação antes de trocar.
* Com o script próprio, a recusa aparece no console como *"\[WebPush] Registro recusado:"* com o código: `user_hash_required` (falta o `userHash` com a exigência ligada), `invalid_user_hash` (o `userHash` não confere) ou `user_id_has_surrounding_whitespace` (o `userId` tem espaço no início ou no fim). Com a tag, o navegador simplesmente não é registrado.

> [!WARNING]
>
> Ligue **Exigir verificação de identidade** só depois que o seu site enviar o `userHash`. Com a exigência ligada, todo registro sem ele é recusado, e o sino in-app dos seus usuários também deixa de carregar sem o `userHash`.

> [!TIP]
>
> Use em `userId` um identificador opaco, como um UUID, e não um número sequencial ou o e-mail.

## 3. Criar o template

No template Web Push de cada [comunicação](https://docs.octasend.com.br/plataforma/comunicacoes.md):

| Campo | Obrigatório | Descrição |
| - | - | - |
| Título | Sim | Título da notificação |
| Corpo | Sim | Texto principal |
| URL de destino | Não | Página aberta ao clicar. Sem URL, o clique abre a raiz do site |
| Ícone | Não | URL do ícone (192×192 px recomendado) |
| Imagem de destaque | Não | URL de uma imagem grande (440×240 px recomendado) |

Todos os campos aceitam variáveis `{{var}}`. Ao clicar, se já houver uma aba aberta na URL de destino, ela ganha o foco em vez de abrir outra.

## 4. Enviar

```bash theme={null}
curl -X POST https://api.octasend.com.br/functions/v1/send-message \
  -H "Authorization: Bearer SEU_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "communication_slug": "nova-promocao",
    "recipient": { "user_id": "id-do-usuario-123" },
    "channels": ["web_push"]
  }'
```

Informe `recipient.user_id` (o mesmo usado em `registerWebPush`) ou, se você mesmo guarda o token, `recipient.fcm_token`. Se a pessoa não tem navegador registrado, o envio falha com *"No FCM token found — provide recipient.user\_id or recipient.fcm\_token"*. Veja todos os parâmetros em [Enviar Mensagens](https://docs.octasend.com.br/api-reference/enviar-mensagens.md).

## 5. Acompanhar

O service worker avisa a OctaSend quando a notificação **chega ao navegador** e quando é **clicada** (o clique também conta como entrega). As duas marcas aparecem em [Logs de Mensagens](https://docs.octasend.com.br/plataforma/logs-de-mensagens.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.