Skip to content

Future Notification Clicked Spec

Jason Pang edited this page Mar 30, 2017 · 2 revisions

Notification Click Spec

API:

  • OneSignal.on/once('notificationPendingClick', callback)

    Occurs when a notification has just been clicked, but before the notification clicked action takes place.

    This event fires on all open site tabs, and the event specifies the default action to take place (e.g. open a new window, or focus tab #3), and allows each open tab to intercept and modify the final outcome.

  • OneSignal.on/once('notificationClick', callback)

    Occurs after event notificationPendingClick, after the notification clicked action takes place.

    Only the tab that is the target of the notification clicked action will receive this event.

Motivation

Some problems with the older way of listening to a notification click event via addListenerForNotifiationOpened()was:

  • addListenerForNotificationOpened() wasn't flexible enough for power users, and made assumptions for the developer:

    • addListenerForNotificationOpened() fires on only one tab if multiple tabs are present. But we can't know which tab it appropriate. For example, a user might have 2 sites open to a chatting site, where 1 is open to the home page, and the other is open to the chat window. Only the developer knows which tab to take action on.
    • The developer had to choose between a notification click action of navigating or focusing, using a special init flag notificationClickHandlerMatch which is an awkward option label. Some corner cases were not covered.
    • Whether a notification.clicked event was fired, was based on whether the notification's URL matched the page's URL exactly. For home page URLs like https://site.com, this is actually reported by the browser as https://site.com/ when you call location.href or document.URL. Until recently, we did not check if the URL had an extra trailing slash.
    • Because an HTTP site is undiscoverable to the controlling service worker (the service worker only knows about the OneSignal iFrame to https://subdomain.onesignal.com), the HTTP page reports its actual page URL by placing a value in IndexedDB called lastKnownHostUrl. A web push bug is that if multiple HTTP sites are open, the last opened site tab will overwrite lastKnownHostUrl with its value. The effect of this is as follows. If a user opens http://site.com/a, http://site.com/b, and http://site.com/c, the lastKnownhostUrl will only be http://site.com/c. When a notification is sent with the launch URL to http://site.com/b, and notificationClickHandlerMatch is exact and notificationClickHandlerAction is navigate, the existing http://site.com/b tab will not be focused, and a new tab will be opened instead. This is because the service worker does not know that tab http://site.com/b exists.
    • Awkward magical strings like _osp=do_not_open, javascript:void(0);, do_not_open in the notification's launch URL to specify not opening a URL. (Note: This may still be required if no existing tab is open)
  • The method name addListenerForNotificationOpened() isn't consistent with other OneSignal event names like OneSignal.on('<event-name>')

  • addListenerForNotificationOpened() only worked once, and had to be called again after each invocation. This is an unnecessary exception.

Overview

This event occurs when the user clicks a displayed notification's body or action button. Clicking X to dismiss the notification does not trigger this event.

Structures

interface WindowClient {
  /**
  	Describes whether the browser tab is the active tab amongst other browser tabs.
  	Natively supported on HTTPS and provided by the service worker.
  	On HTTP, retrieved via a combination of Window.onfocus, Window.onblur, and the Page Visiblity API.
  */
  focused: Boolean,
  visibilityState: String,
  id: UUID,
  /**
    The current URL of the window.
  */
  url: String
}

interface NotificationPendingClickEvent {
  /**
  	The currently displaying notification.
  */
  notification: Notification,
  /**
  	A list of other windows that received the same event.
  */
  targets: WindowClient[],
  shouldFocusWindow: Boolean,
  urlPendingNavigation: String
  shouldOpenNewWindow: Boolean
}

interface NotificationClickEvent {
  notification: Notification
}

Specification

The service worker has just received a notificationclick event.

  1. Close the notification.

    We should never allow the developer to leave a notification open, because this would be confusing to the end-user.

  2. If event.action exists, get the action button that was called.

HTTPS

Procedure

  1. Build a NotificationPendingClickEvent for each WindowClient.
    1. Set shouldFocusWindow, urlPendingNavigation, and shouldOpenNewWindow based on the Default Action.
  2. Emit the NotificationPendingClickEvent to each WindowClient and await a response.
    1. Users can use event.waitUntil() to complete an async operation like checking IndexedDb before responding to the event.
    2. The response times out after 3 seconds. Until the client responds, in a worst case example, end users will see the notification dismiss on click, but will wait 3 seconds before a new window opens or before an existing tab is focused. It's important to limit perceived lag.
    3. If a specific WindowClient does not have any listeners for the notificationPendingClick event (most common case), we can detect this immediately and ignore that client (default action).
  3. Execute the action specified in each returned NotificationPendingClickEvent.
    1. Navigate each WindowClient to the event's urlPendingNavigation value. Do not navigate if urlPendingNavigation is null or undefined.
    2. If multiple events specify shouldFocusWindow, pick one at random (the first).
    3. Do not open a new window if at least one response sets openNewWindow to false. Typically, a window should be opened, so if a response has explicitely set openNewWindow to false, there is probably a specific reason other tabs aren't aware of.

Default Action

  • No Existing Tabs
    • Example: User logs on to computer, receives a new notification
    • Always open a new tab to the notification's URL
  • 1 or Multiple Tabs
    • If any tab shares an identical URL to the notification, focus that tab and quit
    • Notification URL Same-Origin, but different
    • Notification URL Same-Origin, and identical
      • Focus the existing tab, do not open a new tab
  • Multiple existing tabs, Notification URL

HTTP