Ajouter des notifications push à une application Web

1. Présentation

Les messages push constituent un moyen simple et efficace de susciter de nouveau l'intérêt de vos utilisateurs. Dans cet atelier de programmation, vous apprendrez à ajouter des notifications push à votre application Web.

Points abordés

  • Abonner un utilisateur aux messages push et le désabonner de celui-ci
  • Gérer les messages push entrants
  • Afficher une notification
  • Répondre aux clics sur les notifications

Prérequis

  • Chrome 52 ou version ultérieure
  • Serveur Web pour Chrome ou le serveur Web de votre choix
  • Un éditeur de texte
  • Connaissances de base sur HTML, CSS et JavaScript, ainsi que sur les outils pour les développeurs Chrome
  • L'exemple de code (voir "Configuration")

2. Configuration

Télécharger l'exemple de code

Il existe deux façons d'obtenir l'exemple de code pour cet atelier de programmation:

  • Clonez le dépôt Git :
git clone https://github.com/GoogleChrome/push-notifications.git
  • Téléchargez le fichier ZIP:

Si vous téléchargez la source en tant que fichier ZIP, vous obtiendrez un dossier racine push-notifications-master.

Installer et vérifier le serveur Web

Bien que vous soyez libre d'utiliser votre propre serveur Web, cet atelier de programmation est conçu pour fonctionner correctement avec l'application de serveur Web pour Chrome. Si l'application n'est pas encore installée, vous pouvez la télécharger depuis le Chrome Web Store:

Après avoir installé l'application de serveur Web pour Chrome, cliquez sur le raccourci Applications dans la barre des favoris:

946bcaaad66e5c8e.png

Dans la fenêtre "Apps" (Applications), cliquez sur l'icône de serveur Web:

9f3c21b2cf6cbfb5.png

La boîte de dialogue suivante s'affiche. Elle vous permet de configurer votre serveur Web local:

73543edeb27c3d6f.png

Cliquez sur le bouton Sélectionner un dossier, puis sélectionnez le dossier app dans le dossier push-notifications que vous avez téléchargé. Cela vous permet de diffuser votre travail en cours via l'URL affichée dans la section URL des serveurs Web de la boîte de dialogue.

Sous Options, cochez la case Afficher automatiquement index.html comme indiqué ci-dessous:

5ac11bca86ce7369.png

Ensuite, arrêtez et redémarrez le serveur en faisant glisser le bouton Web Server: STARTED (Serveur Web : DÉMARRÉ) vers la gauche, puis vers la droite.

d42f87972f9fec24.png

Cliquez sur l'URL du serveur Web pour accéder à votre site dans votre navigateur Web. Une page semblable à la suivante doit s'afficher, bien que l'adresse indiquée dans votre version soit 127.0.0.1:8887:

00-push-codelab.png

Toujours mettre à jour le service worker

Pendant le développement, il est utile de s'assurer que votre service worker est toujours à jour et dispose des dernières modifications.

Pour configurer cela dans Chrome:

  1. Accédez à l'onglet Déployer l'atelier de programmation.
  2. Ouvrez les outils de développement: Ctrl+Maj+I sous Windows et Linux, Cmd+Option+I sous macOS.
  3. Sélectionnez le panneau Application, cliquez sur l'onglet Service workers, puis cochez la case Update on Reload (Mettre à jour lors de l'actualisation). Lorsque cette case est cochée, le service worker est mis à jour de force chaque fois que la page est actualisée.

e7d384fb77885b99.png

3. Enregistrer un service worker

Code terminé

Dans votre répertoire app, notez que vous avez un fichier vide nommé sw.js. Ce fichier sera votre service worker. Pour l'instant, il peut rester vide. Vous y ajouterez du code plus tard.

Commencez par enregistrer ce fichier en tant que service worker.

Votre page app/index.html charge scripts/main.js. Vous enregistrez votre service worker dans ce fichier JavaScript.

Ajoutez le code suivant à 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';
}

Ce code vérifie si les service workers et les messages push sont compatibles avec votre navigateur. Si elles sont compatibles, le code enregistre votre fichier sw.js.

Essayer

Vérifiez les modifications en actualisant l'onglet Push Codelab (Atelier de programmation push) dans le navigateur.

Recherchez un Service Worker is registered message dans la console dans les outils pour les développeurs Chrome:

5d7ad383d6f235d5.png

Obtenir des clés de serveur d'applications

Pour suivre cet atelier de programmation, vous devez générer des clés de serveur d'applications. Pour ce faire, accédez au site associé: web-push-codelab.glitch.me.

Ici, vous pouvez générer une paire de clés publique et privée.

push-codelab-04-companion.png

Copiez votre clé publique dans scripts/main.js à la place de la valeur <Your Public Key>:

const applicationServerPublicKey = '<Your Public Key>';

Important: Vous ne devez jamais insérer votre clé privée dans votre application Web.

4. Initialiser l'état

Code terminé

Pour le moment, le bouton Activer de l'application Web est désactivé et ne peut pas être cliqué. En effet, il est recommandé de désactiver le bouton push par défaut et de l'activer une fois que vous savez que les messages push sont compatibles avec le navigateur et que vous pouvez vérifier si l'utilisateur est actuellement abonné ou non à la messagerie.

Vous devez créer deux fonctions dans scripts/main.js:

  • initializeUI, pour vérifier si l'utilisateur est actuellement abonné
  • updateBtn, pour activer votre bouton et modifier le texte selon que l'utilisateur est abonné ou non ;

Ajoutez une fonction initializeUI à main.js comme ceci:

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();
  });
}

La nouvelle méthode utilise le swRegistration de l'étape précédente, obtient la propriété pushManager à partir de celui-ci et appelle getSubscription().

pushManager getSubscription() renvoie une promesse qui se résout avec l'abonnement actuel, le cas échéant. Sinon, il renvoie null. Vous pouvez ainsi vérifier si l'utilisateur est déjà abonné, définir la valeur de isSubscribed, puis appeler updateBtn() pour mettre à jour le bouton.

Ajoutez la fonction updateBtn() à main.js:

function updateBtn() {
  if (isSubscribed) {
    pushButton.textContent = 'Disable Push Messaging';
  } else {
    pushButton.textContent = 'Enable Push Messaging';
  }

  pushButton.disabled = false;
}

Cette fonction active le bouton et modifie son texte selon que l'utilisateur est abonné ou non.

La dernière chose à faire est d'appeler initializeUI() lorsque votre service worker est enregistré dans main.js:

navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
  console.log('Service Worker is registered', swReg);

  swRegistration = swReg;
  initializeUI();
})

Essayer

Actualisez l'onglet Push Codelab (Atelier de programmation push). Le bouton Activer le message push devrait maintenant être activé (vous pouvez cliquer dessus) et User is NOT subscribed devrait s'afficher dans la console.

a1553f4a0483d227.png

À mesure que vous progresserez dans cet atelier de programmation, le texte du bouton devrait changer à chaque abonnement ou désabonnement.

5. Abonner l'utilisateur

Code terminé

Pour le moment, le bouton Activer les messages push ne sert pas à grand-chose. Résolvons ce problème.

Dans la fonction initializeUI(), ajoutez un écouteur de clics pour votre bouton:

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();
  });
}

Lorsque l'utilisateur clique sur le bouton, vous désactivez ce bouton uniquement pour empêcher l'utilisateur de cliquer une deuxième fois, car l'abonnement aux messages push peut prendre un certain temps.

Vous appelez ensuite subscribeUser() si l'utilisateur n'est pas abonné. Pour ce faire, vous devez coller le code suivant dans 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();
  });
}

Voyons ce que fait ce code et comment il abonner l'utilisateur aux messages push.

Tout d'abord, prenez la clé publique du serveur d'applications, qui est encodée en base64 pour les URL, et convertissez-la en UInt8Array, car il s'agit de l'entrée attendue de l'appel subscribe(). La fonction urlB64ToUint8Array() se trouve en haut de scripts/main.js.

Après avoir converti la valeur, appelez la méthode subscribe() sur le pushManager de votre service worker, en transmettant la clé publique du serveur d'applications et la valeur userVisibleOnly: true.

const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: applicationServerKey
})

Le paramètre userVisibleOnly vous permet d'afficher une notification chaque fois qu'un message push est envoyé. Actuellement, cette valeur est obligatoire et doit être vraie.

L'appel de subscribe() renvoie une promesse qui sera résolue après les étapes suivantes:

  1. L'utilisateur a autorisé l'affichage des notifications.
  2. Le navigateur a envoyé une requête réseau à un service push pour obtenir les données nécessaires à la génération d'un PushSubscription.

La promesse subscribe() sera résolue avec une erreur PushSubscription si ces étapes ont réussi. Si l'utilisateur n'accorde pas son autorisation ou s'il rencontre un problème pour s'abonner, la promesse est refusée par un message d'erreur. Vous obtenez la chaîne de promesses suivante dans votre atelier de programmation:

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();
});

Vous obtenez ainsi un abonnement et traitez l'utilisateur comme abonné, ou vous interceptez une erreur et l'enregistrez dans la console. Dans les deux cas, vous appelez updateBtn() pour vous assurer que le bouton est réactivé et qu'il contient le texte approprié.

Dans une application réelle, la fonction updateSubscriptionOnServer() vous permet d'envoyer vos données d'abonnement à un backend. Pour cet atelier de programmation, il vous suffit d'afficher l'abonnement dans votre interface utilisateur. Ajoutez la fonction suivante à 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');
  }
}

Essayer

Accédez à l'onglet Push Codelab (Déployer l'atelier de programmation), actualisez la page, puis cliquez sur le bouton. Vous devriez voir une invite d'autorisation semblable à celle-ci:

fcc61267a0194e81.png

Si vous accordez l'autorisation, User is subscribed devrait être consigné dans la console. Le texte du bouton est remplacé par Désactiver le message push, et l'abonnement s'affiche sous forme de données JSON en bas de la page.

5c5505f2ead037c.png

6. Autorisation de gestion refusée

Code terminé

Une chose que vous n'avez pas encore gérée est ce qui se passe si l'utilisateur bloque la demande d'autorisation. Cela nécessite une attention particulière. En effet, si l'utilisateur bloque l'autorisation, votre application Web ne pourra pas afficher à nouveau l'invite d'autorisation et ne pourra pas abonner l'utilisateur. Vous devez au moins désactiver le bouton-poussoir pour que l'utilisateur sache qu'il ne peut pas être utilisé.

La fonction updateBtn() est l'endroit évident pour gérer ce scénario. Il vous suffit de vérifier la valeur Notification.permission, comme suit:

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;
}

Vous savez que si l'autorisation est denied, l'utilisateur ne peut pas s'abonner et vous ne pouvez rien faire de plus. La désactivation définitive du bouton est donc la meilleure approche.

Essayer

Comme vous avez déjà autorisé votre application Web à accéder à votre application Web lors de l'étape précédente, vous devez cliquer sur l'icône i dans un cercle de la barre d'adresse, puis définir l'autorisation Notifications sur Utiliser les paramètres généraux par défaut (Demander).

54495592074f10ae.png

Après avoir modifié ce paramètre, actualisez la page, cliquez sur le bouton Activer le message push et sélectionnez Bloquer dans la boîte de dialogue d'autorisation. Le bouton est désactivé et affiche le texte Messages push bloqués.

d4cf22468f6defda.png

Avec cette modification, vous pouvez désormais abonner l'utilisateur, après avoir traité les scénarios d'autorisation possibles.

7. Gérer un événement push

Code terminé

Avant d'apprendre à envoyer un message push à partir de votre backend, vous devez réfléchir à ce qui se passe réellement lorsqu'un utilisateur abonné reçoit un message push.

Lorsque vous déclenchez un message push, le navigateur le reçoit, détermine le service worker concerné par l'envoi, active ce service worker et envoie un événement push. Vous devez écouter cet événement et afficher une notification en conséquence.

Ajoutez le code suivant au fichier 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));
});

Examinons ce code. Vous écoutez les événements push dans votre service worker en ajoutant un écouteur d'événements:

self.addEventListener('push', ... );

(À moins que vous n'ayez joué avec Web Workers auparavant, self est probablement nouveau. Dans un fichier de service worker, self référence le service worker lui-même.)

Lorsqu'un message push est reçu, l'écouteur d'événements est appelé, et vous créez une notification en appelant showNotification() sur la propriété registration du service worker. showNotification() nécessite un title. Vous pouvez également lui attribuer un objet options pour définir un message, une icône et un badge. Au moment de la rédaction de ce document, le badge n'est utilisé que sur Android.

const title = 'Push Codelab';
const options = {
  body: 'Yay it works.',
  icon: 'images/icon.png',
  badge: 'images/badge.png'
};
self.registration.showNotification(title, options);

La dernière chose à aborder dans la gestion des événements push est event.waitUntil(). Cette méthode prend une promesse pour permettre au navigateur de maintenir votre service worker actif jusqu'à ce que la promesse transmise soit résolue.

Pour rendre le code ci-dessus un peu plus facile à comprendre, vous pouvez le réécrire comme suit:

const notificationPromise = self.registration.showNotification(title, options);
event.waitUntil(notificationPromise);

Maintenant que vous avez passé en revue l'événement push, vérifions un événement push.

Essayer

Grâce à la gestion des événements push dans le service worker, vous pouvez déclencher un faux événement push pour tester ce qui se passe lorsqu'un message est reçu.

Dans votre application Web, abonnez-vous aux messages push et assurez-vous que User IS subscribed s'affiche dans la console. Dans le panneau Application des outils de développement, sous l'onglet Service workers, cliquez sur le bouton Push:

1ee499267eeccd1c.png

Une fois que vous avez cliqué sur Push, vous devriez voir une notification semblable à celle-ci:

379105dfb0ea56d8.png

Remarque: Si cette étape ne fonctionne pas, essayez d'annuler l'enregistrement de votre service worker à l'aide du lien Unregister situé dans le panneau d'application des outils de développement. Attendez que le service worker soit arrêté, puis actualisez la page.

8. Clic sur la notification

Code terminé

Si vous cliquez sur l'une de ces notifications, vous remarquerez que rien ne se passe. Vous pouvez gérer les clics sur les notifications en écoutant les événements notificationclick dans votre service worker.

Commencez par ajouter un écouteur notificationclick dans 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')
  );
});

Lorsque l'utilisateur clique sur la notification, l'écouteur d'événements notificationclick est appelé.

Le code ferme d'abord la notification sur laquelle l'utilisateur a cliqué:

event.notification.close();

Une nouvelle fenêtre ou un nouvel onglet s'ouvre alors et charge l'URL https://developers.google.com/web. N'hésitez pas à le modifier.

event.waitUntil(
    clients.openWindow('https://developers.google.com/web/')
  );

event.waitUntil() garantit que le navigateur n'arrête pas le service worker avant que la nouvelle fenêtre ou le nouvel onglet ne s'affiche.

Essayer

Essayez à nouveau de déclencher un message push dans les outils de développement, puis cliquez sur la notification. La notification se ferme et un nouvel onglet s'ouvre.

9. Envoyer des messages push

Vous avez vu que votre application Web pouvait afficher une notification à l'aide des outils de développement et avez vu comment fermer la notification en un clic. L'étape suivante consiste à envoyer un véritable message push.

Normalement, cela nécessite l'envoi d'un abonnement à partir d'une page Web vers un backend. Le backend déclenche ensuite un message push en effectuant un appel d'API vers le point de terminaison dans l'abonnement.

Ce point n'est pas abordé dans cet atelier de programmation, mais vous pouvez utiliser le site associé ( web-push-codelab.glitch.me) pour déclencher un véritable message push. Collez l'abonnement en bas de votre page:

bb202867962a0249.png

Collez ensuite ceci dans le site compagnon, dans la zone de texte Abonnement à envoyer à:

a0dd93bc33a9e8cf.png

Sous Texte à envoyer, ajoutez la chaîne que vous souhaitez envoyer avec le message push.

Cliquez sur le bouton Envoyer un message push.

a5e8e89411ec034.png

Vous devriez alors recevoir un message push. Le texte que vous avez utilisé sera consigné dans la console.

f6815a356d4f9aaa.png

Cela devrait vous permettre de tester l'envoi et la réception de données, et de manipuler les notifications en conséquence.

L'application associée est simplement un serveur de nœuds qui envoie des messages à l'aide de la bibliothèque web-push. Il peut être utile de consulter l'organisation web-push-libs sur GitHub pour voir quelles sont les bibliothèques disponibles pour envoyer des messages push. Cela gère de nombreux détails pour déclencher des messages push.

Pour consulter l'intégralité du code du site associé, cliquez ici.

10. Désabonner l'utilisateur

Code terminé

La seule chose qui manque, c'est la possibilité de désabonner un utilisateur du push. Pour ce faire, vous devez appeler unsubscribe() sur un PushSubscription.

De retour dans le fichier scripts/main.js, modifiez l'écouteur de clics pushButton dans initializeUI() comme suit:

pushButton.addEventListener('click', function() {
  pushButton.disabled = true;
  if (isSubscribed) {
    unsubscribeUser();
  } else {
    subscribeUser();
  }
});

Notez que vous allez maintenant appeler une nouvelle fonction unsubscribeUser(). Dans cette fonction, vous obtenez l'abonnement actuel et appelez unsubscribe() dessus. Ajoutez le code suivant à 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();
  });
}

Examinons cette fonction.

Tout d'abord, vous obtenez l'abonnement actuel en appelant getSubscription():

swRegistration.pushManager.getSubscription()

Cette commande renvoie une promesse qui se résout avec une PushSubscription, le cas échéant. Sinon, elle renvoie null. S'il existe un abonnement, vous appelez unsubscribe() sur celui-ci, ce qui rend le PushSubscription non valide.

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);
})

Appeler unsubscribe() renvoie une promesse, car son exécution peut prendre un certain temps. Vous renvoyez cette promesse. Le then() suivant de la chaîne attend donc que unsubscribe() se termine. Vous pouvez également ajouter un gestionnaire d'interception au cas où l'appel de unsubscribe() générait une erreur. Vous pouvez ensuite mettre à jour votre interface utilisateur.

.then(function() {
  updateSubscriptionOnServer(null);

  console.log('User is unsubscribed.');
  isSubscribed = false;

  updateBtn();
})

Essayer

Vous devriez pouvoir appuyer sur Activer le message push ou Désactiver le message push dans votre application Web. Les journaux indiqueront que l'utilisateur est abonné ou désabonné.

81a07119235b53da.png

11. Terminé

Félicitations ! Vous avez terminé cet atelier de programmation.

Cet atelier de programmation vous a montré comment ajouter des notifications push à votre application Web. Pour en savoir plus sur les fonctionnalités des notifications Web, consultez ces documents.

Si vous souhaitez déployer des notifications push sur votre site, nous vous conseillons d'ajouter la prise en charge d'anciens navigateurs ou de navigateurs non conformes aux normes qui utilisent GCM. En savoir plus

Complément d'informations

Articles de blog pertinents