# Notification triggers (showTrigger)

> What Chrome's Notification Triggers proposal added to showNotification() behind a flag, the showTrigger option and TimestampTrigger, and why it ended.

Notification triggers were a Chrome proposal to schedule a persistent notification for a future
moment: `showNotification()` would accept a `showTrigger` option holding a `TimestampTrigger`, and
the browser would display the notification at that time with no page open and no push message.
Chrome's documentation states that development has ended, the feature remains behind the
experimental flag, and no other engine implemented it, so the option is absent from every
shipping browser.

## Syntax

```js
registration.showNotification(title, { showTrigger: new TimestampTrigger(timestamp) })
registration.getNotifications({ includeTriggered: true })
```

Both forms exist only in Chromium with `chrome://flags/#enable-experimental-web-platform-features`
enabled ([Notification Triggers](https://developer.chrome.com/docs/web-platform/notification-triggers),
developer.chrome.com). The feature's Chrome Platform Status entry reads "In developer trial (Behind
a flag)" ([chromestatus.com](https://chromestatus.com/feature/5133150283890688)); the origin trials
Chrome ran for it were not followed by a launch.

## Parameters

| Parameter | Type | Meaning |
|---|---|---|
| `showTrigger` | `TimestampTrigger` | When to display the notification. The constructor takes a `DOMTimeStamp` in milliseconds since the epoch, read back as `trigger.timestamp`. A time in the past displays immediately. |
| `includeTriggered` | boolean, on `getNotifications()` options | Include scheduled notifications that have not yet been displayed, so a page can list or cancel them with `notification.close()`. Default `false`. |

The proposal also discussed a `notificationclose` for cancelled triggers and a limit on how far
ahead a trigger may be set; neither was specified.

## Exceptions

None.

## Platform availability

No browser ships the option. Chromium keeps the implementation behind the experimental features
flag with the status above; Firefox and WebKit have no implementation, and MDN's reference for
`showNotification()` lists `actions`, `badge`, `body`, `data`, `dir`, `icon`, `image`, `lang`,
`navigate`, `renotify`, `requireInteraction`, `silent`, `tag`, `timestamp`, and `vibrate` without
`showTrigger`. The stated reason for stopping was the inability to provide consistent and
reliable behaviour across platforms, which is the same constraint that limits
[periodic background sync](/reference/notifications/periodic-background-sync/).

## Examples

The first two examples run with the flag enabled; the third is the only one that belongs in production code.

### Scheduling a reminder behind the flag

With the flag enabled, the trigger is one extra option. The `tag` lets a later call replace the
scheduled notification instead of adding a second one.

```js
async function scheduleReminder(registration, when, title) {
  await registration.showNotification(title, {
    tag: `reminder-${when}`,
    body: 'Starts in 10 minutes',
    showTrigger: new TimestampTrigger(when - 10 * 60 * 1000),
  });
}
```

Nothing happens at call time except storage of the request; the notification appears at the
trigger timestamp even if the browser was closed in between, which is the property no shipped
API offers.

### Cancelling a scheduled notification

`getNotifications({ includeTriggered: true })` returns scheduled entries alongside displayed
ones; closing one before its trigger cancels it.

```js
async function cancelReminder(registration, when) {
  const pending = await registration.getNotifications({ includeTriggered: true });
  for (const notification of pending) {
    if (notification.tag === `reminder-${when}`) notification.close();
  }
}
```

Without the flag the option object is ignored and `pending` contains only displayed
notifications, so the loop finds nothing to cancel.

### Detecting the option and falling back to server-side scheduling

The test is `'showTrigger' in Notification.prototype`, and in every shipping browser it is
`false`. The fallback is the only production path: store the schedule on the server and deliver
it with Web Push at the right time.

```js
async function remindAt(registration, when, title) {
  if ('showTrigger' in Notification.prototype) {
    return registration.showNotification(title, { showTrigger: new TimestampTrigger(when) });
  }
  // not supported anywhere without a flag: schedule on the server and deliver by Web Push
  await fetch('/api/reminders', { method: 'POST', body: JSON.stringify({ when, title }) });
}
```

The server-side path depends on connectivity at delivery time, which is the limitation the
proposal set out to remove and the reason it is still occasionally requested.

:::observed
In a stock Chrome profile without the experimental flag, `'showTrigger' in Notification.prototype`
returns `false` and `typeof TimestampTrigger` returns `"undefined"`; passing `showTrigger` to
`showNotification()` is silently ignored because unknown dictionary members are dropped, so the
notification displays immediately. With `chrome://flags/#enable-experimental-web-platform-features`
set to Enabled and the browser relaunched, both checks flip and the Platform Status entry's
"In developer trial (Behind a flag)" state ([chromestatus.com](https://chromestatus.com/feature/5133150283890688))
is what the page is exercising.
:::

## See also

- [Notification Triggers](https://developer.chrome.com/docs/web-platform/notification-triggers) (developer.chrome.com)
- [Notification Triggers explainer](https://github.com/beverloo/notification-triggers) (github.com)
- [Chrome Platform Status: Notification Triggers](https://chromestatus.com/feature/5133150283890688) (chromestatus.com)
- [Web Push and PushManager.subscribe()](/reference/notifications/web-push/)
- [Periodic background sync for content updates](/reference/notifications/periodic-background-sync/)
- [Notifications API](/reference/notifications/notifications-api/)