Usando Push Notifications en tu web

Jose Ignacio Andres
Finizens Engineering
6 min readDec 14, 2017

Update 2020: La mayoría del contenido del post sigue siendo útil aunque es posible que algunas líneas de código ya no sirvan exactamente igual.

Si quieres ver que otras cosas interesantes estoy haciendo ahora, echa un vistazo a esto.

Una de las cosas que más podemos echar de menos cuando estamos desarrollando en entorno web, si lo comparamos con el desarrollo nativo, es la posibilidad de enviar notificaciones push.

Las notificaciones push pueden tener diferentes usos, desde avisar de algo urgente, favorecer que el usuario interactúe de nuevo con tu web y así mejorar tu conversión, avisar de que ha terminado una transacción que se ejecuta en segundo plano o simplemente utilizarlas como otro canal de marketing. No cabe duda de que es una tecnología muy útil que casi todas las apps y webs pueden aprovechar de un modo u otro.

¿Cómo funcionan?

  • Cuando un usuario visita tu web, le aparece un pop-up pidiendo permiso para enviar notificaciones. Este “pop-up” se mostrará dependiendo del sistema operativo y navegador del usuario.
  • Para esto, durante la carga de la página debemos registrar un “service worker”, es decir, un programa que se ejecuta en segundo plano y que será el encargado de gestionar la comunicación.
  • Si el usuario da permiso, el navegador generará un id de suscripción para ese dispositivo en concreto.
  • En este punto lo habitual es guardar este id en nuestro backend, típicamente asociándolo al usuario si es que lo conocemos, añadiendo fechas u otros datos que puedan sernos de utilidad.
  • Cuando queramos enviar una notificación, tendremos que recuperar el id de la suscripción y enviar un mensaje a través del servidor de notificaciones que utilice cada navegador.

Centrándonos en plano tecnológico las web push notifications se basan principalmente en dos APIs del navegador de las que podemos intuir sus nombres sin ser Sherlock Holmes: “push” y “notifications”. Aunque se suelen usar combinadas, son dos tecnologías diferentes pero que se complementan a la maravilla.

Además de estas dos especificaciones, para poner en marcha nuestra solución debemos tener en cuenta que necesitaremos:

  • HTTPS para evitar ataques. Se puede llegar a implementar en HTTP, pero con ciertos hacks.
  • Compatibilidad con Service Workers
  • Un servidor de notificaciones

Para entender mejor esto podemos concluir que existen dos conceptos: Mensajes Push y Notificaciones Push. El mensaje sería simplemente la información enviada desde el servidor de notificaciones al cliente web y la notificación sería una notificación web generada a partir del mensaje push.

Compatibilidad

Al usar Service Workers estaremos limitados en cuanto a los navegadores que lo soportan. Mientras se escriben estas líneas existe un soporte estable del 65%, básicamente Chrome y Firefox, por lo que nos centraremos en implementar soluciones para estos dos navegadores.

Aprendiendo a generar notificaciones

Paso 1 — Solo notificaciones

Empezaremos enviando notificaciones, sin hacer push, para que sea más sencillo.

En nuestra web añadiremos el código mínimo para solicitar permiso y emitir notificaciones. En este ejemplo solo utilizaremos la api de “Notification” sin involucrar en absoluto la comunicación push ni los service workers.

Asumimos para nuestro ejemplo que siempre se acepta la solicitud de permiso, obviamente de lo contrario no funcionará.

Si un usuario no da permiso, no se le volverá a preguntar a menos que él mismo, manualmente, cambie esta configuración en su dispositivo.

Una notificación contiene un título y una serie de opciones. Debemos tener en cuenta que dependiendo del sistema operativo estas opciones pueden surtir un efecto sustancialmente diferente a nivel de interfaz de usuario. Este sería un ejemplo básico, pero puedes ver más detalles aquí: https://developers.google.com/web/fundamentals/push-notifications/

Para simplificar los ejemplos al máximo los siguientes ejemplos no contendrán opciones.

Paso 2 — Notificaciones y Service Worker

Ahora vamos a mover la notificación para que, en vez de enviarse desde el thread principal del navegador, esta se emita desde el service worker. Buscamos este cambio debido a que más adelante, cuando enviemos un mensaje vía push, deberá ser el service worker el encargado de lanzar la notificación.

Primero creamos nuestro archivo service-worker.js y lo ponemos en la raíz de nuestro proyecto, ha de estar disponible en http://localhost/service-worker.js para funcionar. Por ahora dejaremos este archivo vacío.

Y avanzamos con nuestro código para pasar a esto:

Paso 3 — Añadimos la API Push

La API de Push nos da acceso a PushManager, que nos permite recibir mensajes desde un servidor de terceros.

Dependiendo de cada navegador, este servidor de terceros puede requerir una configuración determinada, en el caso de Chrome nos exige es definir un archivo de manifiesto de nuestra webapp que contenga un “gcm_sender_id”. Puedes leer más aquí si te interesa https://developers.google.com/web/fundamentals/web-app-manifest/.

Y actualizamos nuestro código js:

Como vemos, hemos dejado de usar la api de Notification. Ya no nos hace falta solicitar el permiso explícitamente ya que pushManager.subscribe lo hace por nosotros.

Bien, pero hasta ahora no hemos involucrado ningún servidor externo, vamos a ver como hacerlo.

Enviando mensajes push

Paso 1 — Localizando el destinatario

Lo primero para poder enviar un mensaje push es conocer el destinatario, para esto vamos a alterar un poco nuestro último ejemplo para que nos permita conocer el endpoint asociado al dispositivo donde más tarde deberemos enviar nuestro mensaje.

Ejecutando este código obtendremos una URL del tipo https://android.googleapis.com/gcm/send/{id} o https://updates.push.services.mozilla.com/wpush/v1/{id} dependiendo del navegador.

Depende de nuestro caso de uso, deberíamos enviar este endpoint a nuestro servidor o guardarlo dónde más nos interese ya que lo necesitaremos más adelante.

Paso 2 — Reaccionando a los mensajes

Como hemos visto antes, cuando enviémos nuestro mensaje push este llegará a nuestro Service Worker. Para poder lanzar notificaciones, tenemos que añadir un listener al evento “push” en nuestro archivo service-worker.js

Nota: event.waitUntil se utiliza para indicarle al service-worker que hay un proceso en progreso y que debe esperar a que se resuelva la promesa antes de ponerse en stand-by.

Paso 3 — Enviando mensajes

Dependiendo del servidor de mensajes que utilicemos, los detalles para enviar un mensaje pueden variar. Para simplificar nuestro ejemplo vamos a ver como se enviaría mediante cURL tanto para Chrome como para Firefox.

Chrome

Firefox

¡Listo! Ya hemos enviado nuestra primera notificación push.

Sin embargo la solución dista mucho aún de estar lista para ponerla en producción. La llamada cURL es algo rudimentario y, por otro lado, hasta ahora solo hemos enviado un mensaje push sin información. Si queremos un sistema de notificaciones deberíamos poder personalizar el mensaje, el título, las opciones, etc…

Añadiendo un payload a nuestras notificaciones

Para poder enviar un payload es necesario encriptar la comunicación entre el cliente y el servidor.

Paso 1 — Generando las claves

Para simplificar este proceso vamos a utilizar la librería web-push que nos facilitará la generación del par de claves que necesitamos. Tan sencillo como:

npm install web-push -gweb-push generate-vapid-keys

Paso 2 — Añadiendo la clave pública a nuestra web app

El primer paso es añadir nuestra clave pública al proceso de suscripción de nuestra web app. Para poder hacer esto, debemos indicarla al invocar pushManager.subscribe();

Es necesario realizar algunas conversiones a formato Uint8Array por lo que en el ejemplo usaremos algunas funciones auxiliares que puedes encontrar aquí.

Igual que antes, lo ideal sería reemplazar este console.log y enviar estos 3 valores al servidor para usarlos posteriormente.

Paso 3 — Enviando payloads en nuestros mensajes push

Al involucrar encriptación, lo más sencillo para enviar nuestros payload es utilizar alguna librería que lo gestione por nosotros.

Como en Finizens usamos Symfony hemos utilizado este bundle, que simplifica enormemente el proceso. En cualquier caso deberemos especificar la clave pública, la privada y nuestro identificado de gcm, el mismo que añadimos en el manifiesto de nuestra webapp.

Paso 4 — Adaptando las notificaciones mediante el payload

Ya solo nos quedaría editar nuestro fichero service-worker.js para leer la información del payload. Un ejemplo sencillo sería el siguiente:

¡Ahora si! Tenemos listo y funcionando nuestro propio sistema de notificaciones push vía web.

UPDATE 2019: Si has leído hasta aquí te animo a que eches un vistazo a mi nuevo proyecto, nailted.com :)

Fuentes:

--

--