> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerix.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Angular — Push Notifications

> Configure standard Web Push (VAPID) delivery for your Angular app — no Firebase, no OneSignal required.

## Introduction

Lerix delivers push notifications to Angular apps using the standard
**Web Push protocol (VAPID)** — the same open standard Chrome, Firefox,
Edge, and modern Safari all implement natively. No Firebase project, no
OneSignal account — Lerix generates and manages the key pair for you.
After you complete the [Angular installation](/frameworks/angular/installation),
follow the steps below to enable push delivery.

<Note>
  Make sure you have registered the SDK with `provideLerix()` before configuring push notifications.
</Note>

## 1. Copy the service worker

Web Push requires a service worker file served from your app's own origin —
a package can't add this file to your app automatically. Copy it into your
`public` folder so it's reachable at your site's root:

```bash theme={"dark"}
cp node_modules/@lerix-dev/lerix-core/sw/lerix-sw.js your-app/public/lerix-sw.js
```

## 2. Generate a Web Push key

From the dashboard: **Notifications → Settings → Web Push → Generate keys**.
This is a one-click step — Lerix generates and stores the VAPID key pair
for the project; there's nothing to copy into your code.

## 3. Subscribe

```ts theme={"dark"}
import { Component, inject } from '@angular/core';
import { LerixService } from '@lerix-dev/lerix-angular';

@Component({ ... })
export class MyComponent {
  private readonly lerix = inject(LerixService);

  constructor() {
    this.lerix.notifications.setOnNotificationReceived((payload) => {
      // Fired while a tab is open.
      console.log(payload.title, payload.body);
    });

    this.lerix.notifications.setOnNotificationTapped((payload) => {
      // Fired when the user clicks the notification — including one that
      // opened the page from a fully closed tab.
      const screen = payload.metadata['screen'];
    });
  }

  async enablePush() {
    const subscribed = await this.lerix.notifications.subscribe();
  }
}
```

`subscribe()` prompts for notification permission, registers the service
worker, subscribes this browser to push, and registers the subscription
with the backend — one call for the whole flow.

## The notification payload

Both callbacks receive a `LerixNotificationPayload`:

```ts theme={"dark"}
interface LerixNotificationPayload {
  notificationId: string | null;
  title: string | null;
  body: string | null;
  metadata: Record<string, unknown>;
  imageUrl: string | null;
}
```

## Device identifiers

| Method | Returns | Use it for |
| - | - | - |
| `getRegisteredTokenId()` | Lerix's own id for this registered device | The value for the dashboard's/REST API's device-targeting field |
| `getDeviceToken()` | The raw `PushSubscription`, stringified | Rarely needed directly; diagnostics only |
| `getDeviceId()` | A locally generated identifier, unrelated to Lerix's backend | Local diagnostics only; **not** what the dashboard's send flow expects |

```ts theme={"dark"}
const tokenId = this.lerix.notifications.getRegisteredTokenId();
```

All three return `null` until `subscribe()` has completed at least once.

## Sending metadata

Attach arbitrary custom data with `metadata` (a JSON object) when sending —
from the dashboard's **Send notification** tab, or the REST API's
[`metadata` parameter](/api-reference/push-notifications). It's delivered
back to the page inside `payload.metadata`:

```json theme={"dark"}
{
  "title": "New message from John",
  "body": "Hey, are you free later?",
  "metadata": { "chatId": "456", "screen": "chat" }
}
```

```ts theme={"dark"}
this.lerix.notifications.setOnNotificationTapped((payload) => {
  const chatId = payload.metadata['chatId'];
});
```

## Sending an image

Set `imageUrl` when sending — from the dashboard's **Send notification**
tab, or the REST API's [`imageUrl` parameter](/api-reference/push-notifications).
This works automatically with no extra setup: the service worker renders
it directly as the notification's icon/image.

<Note>
  **Custom sound is not supported for web push.** The Web Notifications API
  doesn't expose a way to set a custom notification sound across browsers,
  so the dashboard/API's `sound` parameter is ignored for browser
  recipients — it only applies to iOS and Android.
</Note>

## Target a user on every device

If your product also ships on other platforms (web, mobile or desktop), add
them to the same project and link each install to your own user ID after
login. Your backend can then send to `externalUserIds` and reach that person
on every device in one request.

```ts theme={"dark"}
await this.lerix.setUser('user_123'); // after login
await this.lerix.clearUser();         // on logout
```

See [Identify users](/modules/users-identity) for identity verification and a
sending example.

## Topics

Instead of targeting specific device tokens, a device can subscribe to a
named topic — send one notification to the topic and every subscriber
receives it. A topic doesn't need to be created ahead of time; it's created
automatically the first time any device subscribes to it. You can also
view, create, and delete topics from the **Notifications → Topics** tab in
the dashboard.

```ts theme={"dark"}
await this.lerix.notifications.subscribeToTopic('promotions');
await this.lerix.notifications.unsubscribeFromTopic('promotions');
```

To send to a topic, use the dashboard's **Send notification** tab (select "Topic" as the audience), or call the [REST API](/api-reference/push-notifications) with `sendByTopic: true`.

## Browser support

Chrome, Firefox, and Edge support Web Push fully. Safari requires macOS 13+
or iOS 16.4+ — older Safari doesn't support the standard at all.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.