As mensagens push são uma maneira simples e eficaz de reengajar os usuários. Neste codelab, você vai aprender a adicionar notificações push ao seu app da Web.
O que você vai aprender
- Como inscrever e cancelar a inscrição de um usuário para mensagens push
- Como lidar com mensagens push recebidas
- Como mostrar uma notificação
- Como responder a cliques de notificação
O que é necessário
- Chrome 52 ou mais recente
- Servidor da Web para Chrome ou seu próprio servidor da Web
- Um editor de texto
- Conhecimento básico de HTML, CSS, JavaScript e Chrome DevTools
- O exemplo de código (consulte "Preparar")
Baixe o exemplo de código
Você tem duas opções para receber o exemplo de código deste codelab:
- Clone o repositório Git:
git clone https://github.com/GoogleChrome/push-notifications.git
- Faça o download do arquivo ZIP:
Fazer o download do código-fonte
Se você baixar a fonte como um arquivo ZIP, ao descompactá-la, uma pasta raiz push-notifications-master será criada.
Instalar e verificar o servidor da Web
Embora você possa usar seu próprio servidor da Web, este codelab foi projetado para funcionar bem com o app Web Server for Chrome. Se você ainda não tiver esse app instalado, faça o download na Chrome Web Store:
Instalar o servidor da Web para Chrome
Depois de instalar o app Web Server para Chrome, clique no atalho Apps na barra de favoritos:

Na janela "Apps", clique no ícone do servidor da Web:

Você verá esta caixa de diálogo, que permite configurar seu servidor da Web local:

Clique no botão Escolher pasta e selecione a pasta app na pasta push-notifications que você baixou. Isso permite que seu trabalho seja detalhado pelo URL mostrado na seção URLs do servidor da Web da caixa de diálogo.
Em Opções, marque a caixa ao lado de Mostrar automaticamente index.html, conforme mostrado abaixo:

Em seguida, pare e reinicie o servidor deslizando a chave Servidor da Web: INICIADO para a esquerda e depois para a direita.

Clique no URL do servidor da Web para acessar seu site no navegador da Web. Você vai ver uma página parecida com esta, mas sua versão pode mostrar 127.0.0.1:8887 como endereço:

Sempre atualizar o service worker
Durante o desenvolvimento, é útil garantir que o service worker esteja sempre atualizado e com as mudanças mais recentes.
Para configurar isso no Chrome:
- Acesse a guia Codelab de push.
- Abra o DevTools: Ctrl-Shift-I no Windows e no Linux, Cmd-Option-I no macOS.
- Selecione o painel Application, clique na guia Service Workers e marque a caixa de seleção Update on Reload. Quando essa caixa de seleção está marcada, o service worker é atualizado à força sempre que a página é recarregada.

No diretório app, observe que há um arquivo vazio chamado sw.js. Esse arquivo será o service worker. Por enquanto, ele pode ficar vazio. Você vai adicionar código a ele mais tarde.
Primeiro, registre esse arquivo como seu service worker.
Sua página app/index.html é carregada scripts/main.js. Você registra o service worker nesse arquivo JavaScript.
Adicione o código a seguir a scripts/main.js:
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push are supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
}Esse código verifica se os service workers e as mensagens push são compatíveis com seu navegador. Se forem compatíveis, o código vai registrar seu arquivo sw.js.
Fazer um teste
Atualize a guia Push Codelab no navegador para verificar as mudanças.
Verifique o console no Chrome DevTools para um Service Worker is registered message, assim:

Receber chaves do servidor de aplicativos
Para trabalhar com este codelab, você precisa gerar chaves do servidor de aplicativos. Você pode fazer isso no site complementar: web-push-codelab.glitch.me
Aqui, você pode gerar um par de chaves pública e privada.

Copie sua chave pública em scripts/main.js, substituindo o valor <Your Public Key>:
const applicationServerPublicKey = '<Your Public Key>';Importante: nunca coloque sua chave privada no app da Web.
No momento, o botão Ativar do web app está desativado e não pode ser clicado. Isso porque é uma boa prática desativar o botão push por padrão e ativá-lo depois de saber que as mensagens push são compatíveis com o navegador e que é possível verificar se o usuário está inscrito ou não.
Você precisará criar duas funções em scripts/main.js:
initializeUI, para verificar se o usuário está inscrito no momentoupdateBtn, para ativar o botão e mudar o texto dependendo se o usuário é assinante ou não.
Adicione uma função initializeUI a main.js desta forma:
function initializeUI() {
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}Seu novo método usa o swRegistration da etapa anterior, recebe a propriedade pushManager dele e chama getSubscription() nele.
pushManager. getSubscription() retorna uma promessa que é resolvida com a assinatura atual, se houver uma. Caso contrário, ele retorna null. Assim, é possível verificar se o usuário já é assinante, definir o valor de isSubscribed e chamar updateBtn() para atualizar o botão.
Adicione a função updateBtn() a main.js:
function updateBtn() {
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}Essa função ativa o botão e muda o texto dele dependendo se o usuário é inscrito ou não.
Por fim, chame initializeUI() quando o service worker for registrado em main.js:
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg);
swRegistration = swReg;
initializeUI();
})Fazer um teste
Atualize a guia Push Codelab. O botão Ativar mensagens push agora está ativado (você pode clicar nele), e User is NOT subscribed aparece no console.

Ao longo deste codelab, o texto do botão vai mudar sempre que você se inscrever ou cancelar a inscrição.
No momento, o botão Ativar mensagens push não faz muita coisa. Vamos corrigir isso.
Na função initializeUI(), adicione um listener de clique ao botão:
function initializeUI() {
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
// TODO: Unsubscribe user
} else {
subscribeUser();
}
});
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
updateSubscriptionOnServer(subscription);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}Quando o usuário clicar no botão, desative-o para garantir que ele não possa clicar uma segunda vez, já que a assinatura de mensagens push pode levar algum tempo.
Em seguida, chame subscribeUser() se o usuário não estiver inscrito. Para isso, cole o seguinte código em scripts/main.js:
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(error) {
console.error('Failed to subscribe the user: ', error);
updateBtn();
});
}Vamos analisar o que esse código está fazendo e como ele está inscrevendo o usuário para mensagens push.
Primeiro, pegue a chave pública do servidor de aplicativos, que é codificada em Base64 seguro para URLs, e converta em um UInt8Array, porque essa é a entrada esperada da chamada subscribe(). A função urlB64ToUint8Array() está na parte de cima de scripts/main.js.
Depois de converter o valor, chame o método subscribe() no pushManager do service worker, transmitindo a chave pública do servidor de aplicativos e o valor userVisibleOnly: true.
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})O parâmetro userVisibleOnly garante que uma notificação será mostrada sempre que uma mensagem push for enviada. No momento, esse valor é obrigatório e precisa ser "true".
Chamar subscribe() retorna uma promessa que será resolvida após as seguintes etapas:
- O usuário concedeu permissão para mostrar notificações.
- O navegador enviou uma solicitação de rede para um serviço de push e recebeu os dados necessários para gerar um
PushSubscription.
A promessa subscribe() será resolvida com um PushSubscription se essas etapas forem concluídas. Se o usuário não conceder permissão ou se houver algum problema ao assinar, a promessa será rejeitada com um erro. Isso resulta na seguinte cadeia de promessas no seu codelab:
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
updateBtn();
});Com isso, você recebe uma assinatura e trata o usuário como assinante ou captura um erro e o registra no console. Em ambos os cenários, chame updateBtn() para garantir que o botão seja reativado e tenha o texto adequado.
Em um aplicativo real, a função updateSubscriptionOnServer() é onde você enviaria os dados de assinatura para um back-end, mas, para o codelab, basta mostrar a assinatura na interface. Adicione a seguinte função a scripts/main.js:
function updateSubscriptionOnServer(subscription) {
// TODO: Send subscription to application server
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}Fazer um teste
Acesse a guia Push Codelab, atualize a página e clique no botão. Você vai ver uma solicitação de permissão como esta:

Se você conceder a permissão, User is subscribed vai aparecer no console. O texto do botão vai mudar para Desativar mensagens push, e você poderá ver a inscrição como dados JSON na parte de baixo da página.

Uma coisa que você ainda não processou é o que acontece se o usuário bloquear a solicitação de permissão. Isso exige uma consideração exclusiva porque, se o usuário bloquear a permissão, o web app não poderá mostrar novamente a solicitação de permissão nem inscrever o usuário. É necessário desativar o botão de pressão para que o usuário saiba que ele não pode ser usado.
O lugar óbvio para lidar com esse cenário é a função updateBtn(). Basta verificar o valor de Notification.permission, assim:
function updateBtn() {
if (Notification.permission === 'denied') {
pushButton.textContent = 'Push Messaging Blocked';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;
}
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}Se a permissão for denied, o usuário não poderá se inscrever, e não há mais nada que você possa fazer. Portanto, desativar o botão permanentemente é a melhor abordagem.
Fazer um teste
Como você já concedeu permissão para seu web app na etapa anterior, clique no i em um círculo na barra de URL e mude a permissão de Notificações para Usar padrão global (perguntar).

Depois de mudar essa configuração, atualize a página, clique no botão Ativar mensagens push e selecione Bloquear na caixa de diálogo de permissão. O botão vai ficar desativado e mostrar o texto Mensagens push bloqueadas.

Com essa mudança, agora é possível inscrever o usuário, já tendo cuidado com os possíveis cenários de permissão.
Antes de aprender a enviar uma mensagem push do seu back-end, considere o que vai acontecer quando um usuário inscrito receber uma mensagem push.
Quando você aciona uma mensagem push, o navegador a recebe, descobre para qual service worker ela é, ativa esse service worker e envia um evento push. É necessário detectar esse evento e mostrar uma notificação como resultado.
Adicione o seguinte código ao arquivo sw.js:
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
event.waitUntil(self.registration.showNotification(title, options));
});Vamos analisar esse código. Você está detectando eventos push no service worker ao adicionar um listener de eventos:
self.addEventListener('push', ... );A menos que você já tenha usado Web Workers, self provavelmente é novo. Em um arquivo de service worker, self faz referência ao próprio service worker.)
Quando uma mensagem push é recebida, o listener de eventos é chamado, e você cria uma notificação chamando showNotification() na propriedade registration do service worker. O showNotification() exige um title. Você também pode fornecer um objeto options para definir uma mensagem no corpo, um ícone e um selo. (O selo só é usado no Android no momento da redação.)
const title = 'Push Codelab';
const options = {
body: 'Yay it works.',
icon: 'images/icon.png',
badge: 'images/badge.png'
};
self.registration.showNotification(title, options);A última coisa a abordar no seu processamento de eventos push é event.waitUntil(). Esse método usa uma promessa para permitir que o navegador mantenha o service worker ativo e em execução até que a promessa transmitida seja resolvida.
Para facilitar um pouco a compreensão do código acima, você pode reescrevê-lo assim:
const notificationPromise = self.registration.showNotification(title, options);
event.waitUntil(notificationPromise);Agora que você já passou pelo evento de push, vamos testar um.
Fazer um teste
Com o processamento de eventos push no service worker, você pode acionar um evento push falso para testar o que acontece quando uma mensagem é recebida.
No app da Web, inscreva-se para receber mensagens push e verifique se User IS subscribed aparece no console. No painel Application das DevTools, na guia Service Workers, clique no botão Push:

Depois de clicar em Enviar, você vai receber uma notificação como esta:

Observação: se esta etapa não funcionar, tente cancelar o registro do service worker com o link Cancelar registro no painel "Application" do DevTools. Aguarde a interrupção do service worker e recarregue a página.
Se você clicar em uma dessas notificações, nada vai acontecer. Você pode processar cliques em notificações detectando eventos notificationclick no service worker.
Comece adicionando um listener notificationclick em sw.js:
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click received.');
event.notification.close();
event.waitUntil(
clients.openWindow('https://developers.google.com/web')
);
});Quando o usuário clicar na notificação, o listener de eventos notificationclick será chamado.
Primeiro, o código fecha a notificação clicada:
event.notification.close();Em seguida, uma nova janela ou guia é aberta, carregando o URL https://developers.google.com/web. Você pode mudar isso.
event.waitUntil(
clients.openWindow('https://developers.google.com/web/')
);event.waitUntil() garante que o navegador não encerre o service worker antes que a nova janela ou guia seja exibida.
Fazer um teste
Tente acionar uma mensagem push no DevTools novamente e clique na notificação. A notificação será fechada, e uma nova guia será aberta.
Você já viu que seu app da Web é capaz de mostrar uma notificação usando o DevTools e aprendeu a fechar a notificação com um clique. A próxima etapa é enviar uma mensagem push real.
Normalmente, isso exigiria o envio de uma assinatura de uma página da Web para um back-end. Em seguida, o back-end acionaria uma mensagem push fazendo uma chamada de API para o endpoint na assinatura.
Isso está fora do escopo deste codelab, mas você pode usar o site complementar (web-push-codelab.glitch.me) para acionar uma mensagem push real. Cole a assinatura na parte de baixo da página:

Em seguida, cole na área de texto Assinatura do Send To do site complementar:

Em Texto para enviar, adicione a string que você quer enviar com a mensagem push.
Clique no botão Enviar mensagem push.

Você vai receber uma mensagem push. O texto usado será registrado no console.

Isso vai permitir que você teste o envio e o recebimento de dados, além de manipular as notificações.
O app complementar é apenas um servidor de nós que usa a biblioteca web-push para enviar mensagens. Vale a pena analisar a organização web-push-libs no GitHub (link em inglês) para saber quais bibliotecas estão disponíveis para enviar mensagens push. Isso lida com muitos detalhes para acionar mensagens push.
A única coisa que falta é a capacidade de cancelar a inscrição de um usuário nas notificações push. Para fazer isso, chame unsubscribe() em um PushSubscription.
De volta ao arquivo scripts/main.js, mude o listener de clique pushButton em initializeUI() para o seguinte:
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
unsubscribeUser();
} else {
subscribeUser();
}
});Agora você vai chamar uma nova função unsubscribeUser(). Nessa função, você recebe a assinatura atual e chama unsubscribe() nela. Adicione o código a seguir à scripts/main.js:
function unsubscribeUser() {
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
});
}Vamos analisar essa função.
Primeiro, chame getSubscription() para receber a assinatura atual:
swRegistration.pushManager.getSubscription()Isso retorna uma promessa que é resolvida com um PushSubscription se houver um. Caso contrário, retorna null. Se houver uma assinatura, chame unsubscribe() nela, o que invalida o PushSubscription.
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
// TODO: Tell application server to delete subscription
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})Chamar unsubscribe() retorna uma promessa, já que pode levar algum tempo para ser concluída. Você retorna essa promessa para que o próximo then() na cadeia aguarde a conclusão de unsubscribe(). Você também adiciona um manipulador de captura caso a chamada de unsubscribe() resulte em um erro. Depois disso, você pode atualizar a interface.
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
})Fazer um teste
Você poderá pressionar Ativar mensagens push ou Desativar mensagens push no seu web app, e os registros vão mostrar o usuário se inscrevendo e cancelando a inscrição.

Parabéns por concluir este codelab!
Este codelab mostrou como adicionar notificações push ao seu web app. Se quiser saber mais sobre o que as notificações da Web podem fazer, confira estes documentos.
Se você quiser implantar notificações push no seu site, talvez seja interessante adicionar suporte a navegadores mais antigos ou não compatíveis com padrões que usam o GCM. Saiba mais aqui.
Leia mais
- Notificação push da Web: documentação sobre fundamentos da Web.
- Bibliotecas de push na Web: bibliotecas de push na Web, incluindo Node.js, PHP, Java, Python, C e C#.