Вот PHP часть.

$data = [
            "title" => 'hello11',
            "text" => 'text',
            "icon" => 'https://icons8.com/iconizer/files/DOT_pictograms/orig/usd_dollar_money_cash.png',
            "tag" => 'tag1',
            "data" => ['url' => 'https://google.com']
        ];
        $notifications = [
            [
                'subscription' => Subscription::create(['endpoint' => $item->endpoint, 'contentEncoding' => 'aesgcm']),
                'payload' => json_encode($data)
            ]
        ];


$webPush = new WebPush($auth);

        // send multiple notifications with payload
        foreach ($notifications as $notification) {
            $webPush->sendNotification(
                $notification['subscription'],
                $notification['payload']
            );
        }




foreach ($webPush->flush() as $report) {
            $endpoint = $report->getRequest()->getUri()->__toString();
            if ($report->isSuccess()) {
                echo "[v] Message sent successfully for subscription {$endpoint}.";
            } else {
                echo "[x] Message failed to sent for subscription {$endpoint}: {$report->getReason()}";
            }
        }






///////////////////////////////////////////////////////////////////////////////////////

Вот SW.JS


self.addEventListener('push', function (event) {
    var pushData = event.data.json();
    var title = pushData.title;
    var message = pushData.text;
    var icon = pushData.icon;
    var notificationTag = pushData.tag;
    event.waitUntil(self.registration.showNotification(title, {
        body: message,
        icon: icon,
        tag: notificationTag,
        requireInteraction: true,
        vibrate: [200, 100, 200, 100],
        data: pushData
    })
    );
});