Pushpad
Articles › Technical Insights, Web Push Notifications

The Push API and its wild unsubscription mechanism

  • # permission
  • # push-api

The working draft of the Push API currently doesn't offer a good way to manage unsubscriptions.

The problems arise in the following scenarios:

  • The user blocks the notifications from the browser preferences
  • The endpoint is replaced because it has expired

You don't know when the user revokes permission

Currently the event pushsubscriptionchange (tested on Firefox 46) is not called when the user blocks the notifications from the browser preferences.

Consider the following scenario:

  1. The user allows push notifications
  2. The user blocks push notifications from the browser preferences

In this case there is no way to know if the user has unsubscribed. You realize that the endpoint has expired only when you try to push a message to it.

However in many cases you would like to know if an endpoint has expired before sending it a message:

  • For analytics you want to know exactly when the user has unsubscribed
  • For providing a fallback method (like an email) you want to know in advance if the user can be reached using push notifications (usually you use a worker for the delivery job, and it's difficult to provide the fallback asynchronously after the worker has realized that the endpoint has expired).

UPDATE: As pointed out in the comments, there is currently a discussion on Github about firing an event when the permission is revoked. Now the browser MAY trigger the pushsubscriptionchange event when the subscription is revoked.

You don't get the expired endpoint as an argument of the callback

Consider the following scenario:

  1. The user subscribes to push notifications
  2. The browser manufacturer server replaces the token with a new one (for its own reasons)

The documentation says that pushsubscriptionchange is triggered. However you don't get the expired endpoint; you can only try to register a new one.

The problem is that the endpoint is usually stored on the server together with other data (the user which it belongs to, tags, etc.). You cannot just create a new endpoint and delete the old one (when you realize that it has expired). You would like update the subscription on the server to preserve the data associated to the endpoint. To do that you need both the old endpoint and the new one.

Currently the only solution to achieve that is to use cookies or local storage to memorize the last endpoint. However you are responsible for keeping them in sync, they can be blocked (e.g. EU Cookie Law scripts) and they can also disappear (e.g. clear history). So it appears as a dirty hack.

It would be reasonable that when the browser manufacturer server invalidates a token, you receive the token that has been invalidated as an argument of pushsubscriptionchange.

The same arguments exposed here would be also valid for the scenario where the user blocks the notifications and invalidates the endpoint (however in this case pushsubscriptionchange is not even called at the moment).

UPDATE: Now this is fixed in the new definition of pushsubscriptionchange. You can use event.oldSubscription and event.newSubscription to get both the endpoints in the same callback: you can then replace the old endpoint with the new one in your application server and keep the attached data (e.g. tags).

Other worries

  • What happens when a user clears the browser cache? Does it affect push subscriptions? Is an event triggered to manage that unsubscription?