Comments 64
Прямо стало интересно, почему не доходят. Посмотрел весь код, наскоком ничего не обнаружил, надо повторять всё разбираться.

У меня сомнения что всё это не работает, потому что в случае с OneSignal это как-то отрабатывает. Банально ставишь плагин уведомлений к Wordpress, жмёшь «Send test notification» и оно приходит.

Как гипотеза, js api от firebase выдает не тот токен (он может и клиентский, да не тот).
У Firefox вообще свой пуш- сервис. Firebase проксирует через себя запрос и бага где то на стороне этого проксирования. Мы шлем напрямую в Mozilla Push Service и все приходит. При этом не используем payload, а запрашиваем уведомления с сервера, что позволяет еще в дальнейшем показывать лишь те, что пользователь не видел на других платформах.

Интересно было бы услышать более детально как вы всё реализовали у себя в PushAll

ужас как бесят эти пуш-уведомления. ощущение, что их специально кто-то проталкивает. в гугл хроме при включенной галочке на «отказаться от пуш-уведомлений», пуш сообщения отдельных гениальных сайтов красавцев все равно проходят (вести ру к примеру). на других сайтах приходится при каждом заходе на страничку отказываться, отказываться и отказываться от подписок на сайт. ff пока держит защиту с dom.push.enabled false
вы не думайте, я не против прогресса. но ситуация как с рекламой — когда ею начали злоупотреблять, то нашлись всеми рекламодателями нелюбимые контрмеры. я бы даже как-нибудь сел, да и запилил пост-фидбек по всему этому новому лицу интернета, что раньше было удобнее, а что сейчас.
А всё потому что технология очень удобна если использовать по назначению, но народ не знает о ней, народу надо показать что да как. Аналогия с мелкомягким когда обучали пользоваться мышью.

Ещё, кажется, так они(Гугл, в основном) стараются разрабов Apple(см. iOS, Service Workers) подтолкнуть внедрить push у себя в браузере и чему я рад, так как не хватает сильно в работе, связанной с темой умных домов.
та же история, что и с открытием ссылок в новом окне: разумное в отдельных случаях поведение стали массово использовать для накрутки пользователей

Полагаю, что часто это выглядит так. Заказчик, далекий от IT открывает для себя PUSH и сразу озвучивает свою хотелку. На все уверения о том что многих будет бесить, что нужно запрашивать разрешение только по клику отвечает: "Хочу чтобы работало сразу при заходе на сайт".

У нас как-то вирус был. Он патчил хром и добавлял уведомления с их сайтов и естественно эти уведомления нельзя было нигде выключить. После удаления хрома и установки заново, день работал без проблем и потом по-новой. Пока все не почистили от вирусов.
Спасибо за статью, как раз возникла потребность разобраться (есть мысль реализовать для внутрикорпоративного сайта), а тут уже все есть.

Подскажите, пожалуйста, каким образом можно кастомизировать окно с предложением подписаться? Видел на нескольких сайтах нестандартные диалоги подписки, но беглый гуглинг ответа не дал.

Видел и задавался тем же вопросом. В документации не описаны какие либо методы по кастомизации окна. Подозреваю что это делается через какие-то костыли и хуки. Не советую вам это делать. Единообразие интерфейса не есть плохо

Это кастомное окно после клика по нему откроет стандартное браузерное, скорее всего.
Так и есть. В случае со стандартной всплывашкой — отказываешься один раз и больше не видишь. Поэтому крупные сайты делают свою всплывашку после которой будет стандартная.
UFO landed and left these words here
Их можно отключить. Что касается push уведомлений, вполне себе неплохо работает OneSignal. Правда, есть одна подковырка — они прямо говорят, что анализируют их содержание. Однако с ними можно договориться о платной подписке. К слову, тарифы на платную подписку у них существенно ниже, чем у конкурентов.
1. Если использовать push api напрямую, а не через firebase.js — то все замечательно приходит в фаерфокс. Кода от этого больше не становится.
2. Если использовать push api напрямую, то VAPID и надо шифровать payload.
3. >не самая дешевая операция
Да, если делать это (multi)curl'ом на похопе (~250 пушей в минуту). На golang с concurency=200 (столько хочет гугловый http2) получается ~1000 пушей в секунду.
4. Стандарт до сих пор не утвержден. И лучше не изобретать свой велосипед, а использовать один из кучи готовых сервисов, которые и о передрягах стандарта позаботятся и поддержку iOS/Safari обеспечат.
Ах да, https нужен только для service-worker. Отправку можно делать откуда угодно. При этом картинки для нотификаций тоже должны отдаваться с https.

Отправлять можно откуда угодно, а вот получать уведомления на клиенте без Service Worker нельзя. Уведомления без Service Worker уже не push-уведомления. Это неразделимое целое. Потому я и говорю в статье что push-уведомления это не одна технология, а целый набор.

3. не самая дешевая операция
Да, если делать это (multi)curl'ом на похопе (~250 пушей в минуту). На golang с concurency=200 (столько хочет гугловый http2) получается ~1000 пушей в секунду.

окей. А теперь представим что у вас 5000 подписчиков. Это значит что страница у вас будет открываться на 5 секунд дольше обычного и пользователи будут отказываться от вашего ресурса из-за ожидания, не смотря на то что вы используете супер продвинутый Go. Поставить же событие в очередь займет милисикунды, а разбирать очередь можете на чем угодно в фоне, хоть на PHP, хоть на Go, хоть на C.


4. Стандарт до сих пор не утвержден. И лучше не изобретать свой велосипед, а использовать один из кучи готовых сервисов, которые и о передрягах стандарта позаботятся и поддержку iOS/Safari обеспечат.

А кто изобретает велосипед? Как раз напротив. Я пытаюсь показать как реализовать уведомления используя стандартные средства (в данном случае средствами представленными Google), не прибегая к сторонним сервисам. Сторонние сервисы плохи тем что:


  • они получают полный доступ к нашему контенту который может содержать конфеденциальную информацию;
  • они встраивают рекламу в уведомления и им нужно отдельно платить за то, чтоб они этого не делали;
  • большинство имеют ограничение на количество подписчиков и уведомлений. После выхода за лимит начинают требовать деньги;
  • сторонние сервисы вообще живут за счет того, что просят деньги за свои услуги.

Внимание вопрос. Зачем платить за то что можно сделать бесплатно? Причем абсолютно легально и стандартизировано.


Я не хочу сказать, что сторонние сервисы это зло. В своем личном, некоммерческом проекте я скорей всего воспользуюсь их услугами. А вот серьезные организации, которым важен престиж и конфиденциальность, такой вариант не рассматривают.


PS: я уже обсуждал тему осмысленности сторонних сервисов для отправки push-уведомлений с автором проекта PushAll BupycNet и не хотел бы возвращаться к этой теме.

1. Заметь, я же нигде не говорил, что очередь не нужна. Но даже в фоне разбирать события курлом — плохой вариант.
2. firebase api — это не стандартное средство. Стандартное — webpush api. Гугл его целиком и полностью поддерживает.
1. Заметь, я же нигде не говорил, что очередь не нужна. Но даже в фоне разбирать события курлом — плохой вариант.

Надо было так и говорит. "Не используйте cURL." Я вас неправильно понял.


2. firebase api — это не стандартное средство. Стандартное — webpush api.

Хорошо. Назовем это так — Библиотека/обертка над нативным интерфейсом. Что в этом плохого?
Согласен, лучше это решать нативными средствами.
Может вы поделитесь с обществом своим опытом в этой сфере?

1. Мы с тобой несколько лет вместе работали, можно и на «ты», хех
2. У Мозиллы есть несколько довольно подробных и понятных заметок с примерами, они работают и для хрома (с добавлением FCM-ключа и манифеста) https://developer.mozilla.org/en/docs/Web/API/Push_API#See_also
Для хрома стоит прочесть https://developers.google.com/web/updates/2015/03/push-notifications-on-the-open-web (не смотря на пометку об устаревании) и минимально-рабочий пример https://github.com/chrisdavidmills/push-api-demo

1. Заметь, я же нигде не говорил, что очередь не нужна. Но даже в фоне разбирать события курлом — плохой вариант.

Раз пошла такая тема. Нужно определится на чем написан сайт и бизнес логика проекта. Бизнес логика это самое важное в проекте и она определяет как отреагировать на то или иное событие.


Если проект написан на Go, то логично и уведомления отправлять через Go.


Если проект написан на PHP (как это часто бывает), то можно завести вторую очередь. Первая хранит события, а вторая уже готовые уведомления которые нужно отправить. А вот в качестве транспорта для отправки уведомлений из второй очереди, можно в этом случае использовать микросервисы на Go.


В этом случае мы можем потерять в производительности из-за 2 очередей, но зато логика будет прозрачной.

У нас сейчас проект просто отсылает сообщение в апишечку на похопе, которая кладет в очередь. А сервис на го уже берет из очереди и рассылает.
Стандарт до сих пор не утвержден. И лучше не изобретать свой велосипед, а использовать один из кучи готовых сервисов, которые и о передрягах стандарта позаботятся и поддержку iOS/Safari обеспечат.

Да, спецификация W3C Push API не утверждена в том смысле, что ещё пока не достигла статуса рекомендации W3C, но её уже можно активно использовать. Куда более важна поддержка спецификации различными браузерами: http://caniuse.com/#feat=push-api. Более детальные сведения: https://github.com/web-push-libs/web-push#browser-support. Хотя эти сведения тоже неполные — нет деления на платформы, что важно, так как, например, на iOS все браузеры вынуждены использовать движок WebKit со всеми вытекающими из этого последствиями в виде поддержки спецификаций.


Многие спецификации, например Service Workers и Web Components до сих пор не получили статус рекомендации W3C, но это не повод их не использовать.

Честно говоря больше интересует, как можно реализовать свой собственный сервер уведомлений, а не использовать сторонние.

Краткий ответ: никак
Длинный ответ: ServiceWorker+ Fetch/Streams. И свой костыль для fingerprinting'а клиента, подписки, отписки и всего вот этого. Сделать свой, совместимый с WebPush API сервер не представляется возможным, поскольку их адреса вшиты в коде браузеров и не доступны к изменению из js.
Кхм, мне это кажется странным… Браузер, зависящий от внешнего сервера? Получается что все сайты, желающие воспользоваться этим ОТКРЫТЫМ API, должны тоже зависеть от этих серверов? Либо костылять что-то своё нестандартное? Что-то тут неправильно.
Ну, в гугле, например, это в том числе ради более точной идентификации клиента (привязка к гугловой учетке)
А так, мне в целом стандарт странным кажется. Несмотря на наличие firebase и мозилловскиго сервера нужен все равно свой для рассылки. Куда логичней были бы каналы подписки и апи для отравки сообщения сразу всем подписанным клиентам, поскольку задача «отправить одно сообщение сразу всем» возникает гораздо чаще, нежели «отправить кому-то конкретному».
В итоге мне кажется накостылять что-то своё будет проще и эффективней как ни странно… Больше ресурсозатрат конечно будет на стороне своего сервера, но как бонус снимается зависимость от непонятных внешних сервисов, на которых никакого влияния нет и которые предоставляются as-is.

Все тут правильно, Вы не задумывались как будете слать уведомления со своего сервера браузеру? Ответ весьма прост никак. Первой преградой будет динамический ip, а второй и непреодолимой это НАТ. Ну да ладно живем-то во времена НАТа, пускай браузер сам подключаться к 100500 сайтам, на которые подписан пользователь. В результате что мы имеем? 100500 бессмысленных постоянных соединений с сайтами на клиенте и то же самое на другом конце провода. Как результат бессмысленная трата ресурсов. В данном случае единый/е сервера к которым подключаются браузер имея 1 соединение и сайты которые ему шлют свои уведомления. Речь идет, разумеется, об уведомления при закрытом сайте/браузере, так как при открытой вкладке с браузером можно использовать WebSocket, что в данном случае оправдано (когда человек на сайте).
 
За последнее время мы так привыкли ко всем этим API, что забываем как это работает на низком уровне, а ведь ничего особо не изменилось.
 
P.S. Я надеюсь я правильно Вас понял.

Добавьте в минусы, что на данном этапе тестирование уведомлений никак не автоматизируется.

Ну как сказать не автоматизируется. Уведомления это как email сообщения. Они работают через сторонние сервисы. Вопрос осмысленности такого тестирования я не поднимаю.


Некоторые тестируют отправляемые и доставляемые email сообщения поднимая тестовый SMTP сервер. Так и тут. Никто не мешает, при желании, поднять тестовый Service Worker и тестировать уведомления через него.


Тестировать работу самого Service Worker-а уже сложнее так как он работает вне контекста текущей страницы.

Спасибо, попробую в этом направлении копать.
Пока что я видел двухлетней давности инструкцию по отладке уведомлений в Хроме от developers.google, которая не работает. И велосипеды с прокси сервером, через который идет трафик браузера, но тут вопрос чтения содержимого из-за обязательного https.
Тестировать работу сервис-воркера не сложно. Можно через Selenium в браузере — события элементарно эмулируются через self.dispatchEvent. Юнит-тестирование проводится на моках.
Подскажите, есть ли c++ библиотеки для реализации отправки сообщений?
Отправка сообщений делается обычным хттп-запросом, никакой магии.
Вводить в заблуждение читателей о бесплатности использования Firebase довольно подлое занятие. И я это вижу практически в каждой статье про всякие Амазоны, Гуглы и прочие платформы. А тем не менее бесплатными являются только некий мизерный объем услуг. У Firebase к примеру это 100 одновременных подключений к их сервису. Т.е. бесплатным будем только период тестирования и первые дни запуска проекта. Как только у проекта появляется хоть какая-то небольшая популярность, эти бесплатности начинает активно кушать деньги. Вот сейчас сижу изучаю проект обильно напичканный этими бесплатностями, которые съедает 70% прибыли. В год он приносит 5 млн рублей, но на всякие CDN, PUSH, ELASTIC и прочие плюшки тратится 3.5 млн. рублей. При этом анализ нагрузки показывает, что все эти условно-бесплатные услуги можно будет перевести на собственные выделенные серверы, и сумма расходов на бесплатные услуги снизится в 10 раз.
Так что статью надо было назвать «Web PUSH Notifications быстро и просто, но очень дорого!», а потом показать что существуют действительно полностью бесплатные решения.

push-уведомления через Firebase бесплатные. Не знаю с чего вы взяли что за них нужно платить. Если использовать сторонние сервисы для отправки уведомлений такие как OneSignal и PushAll, то естественно это будет стоит денег, о чем я писал в одном из комментариев.


CDN естественно стоит денег. Если вы разместите статику на своих серверах, то это уже будет не CDN, а если вы начнете строить свою сеть CDN, то это выйдет дороже для большинства проектов.

Почему вы так упорно называете бесплатным то, за что придется платить? И как минимум $25. Как я уже сказал бесплатен только тарифный план SPARK, который поддерживает только 100 одновременных клиентских соединений с сервером. Это очень мало. Как говорят в google «Щедрые ограничения для любителей». Их хватает только на период разработки, тестирования и несколько дней после запуска проекта. Как только начинается коммерческая эксплуатация проекта, включается тарифный план FLAME $25 per month просто в силу того, что с проектом работает больше 100 пользователей одновременно. А через месяц-другой, ваш проект уже на тарифном плане BLAZE просто потому что у вас превысились лимиты по трафику или по объему занятого места. Поэтому уместно писать бесплатный сервис для разработчиков. но никак не для владельцев проекта.

На официальном сайте Firebase, в разделе цены, вполне четко описано какие услуги платные, а какие нет


Included Free
Analytics, App Indexing, Authentication, Cloud Messaging, Crash Reporting, Dynamic Links, Invites, Notifications & Remote Config

push-уведомления относятся к категории бесплатных услуг.
Еще раз. С чего вы решили что уведомления платные?

Насчет оплаты OneSignal и PushAll. OneSignal по сути по поводу отправки бесплатен, но скорость на нем ограничена, опытным путем коллег из Медузы было выяснено, что скорость там примерно 500 уведомлений в секунду.
Насчет наших цен, мы у себя описали некие ограничения скорости в 100 в секунду на бесплатном тарифе, 500 на платном и выше если будет нужно. На деле же эти ограничения практически не действуют, даже на бесплатном тарифе сейчас можно более 3000 уведомлений FCM отправить за 1,5 секунды при условии что это массовая рассылка. Более того для интересных проектов мы предоставляем услуги бесплатно и делаем фичи если им это необходимо, надо лишь мне написать.

Также отвечу на предположение выше о 100 соединениях. Хорошо, 100 соединений, в среднем при открытом TLS соединении с гуглом 1000 уведомлений отправляется за 1 секунду. 100 соединений дает нам 100 000 уведомлений в секунду. Куда вам столько?
Да если вы шлете индивидуальные уведомления то гугл их обрабатывает значительно быстрее, примерно на уровне пинга до гугла.
У нас по логам 1 сообщение при существующем хендшейке ушло за 0.04 секунды. На один поток выходит 50 уведомлений в секунду. На 100 потоков это 5000 уведомлений в секунду. Это 18 миллионов уведомлений в час. Даже если каждый пользователь принимает 10 уведомлений в час это 1.8 миллионов активных пользователей.

Но коннекты на FCM не ограничены, также у гугла есть отправка через XMPP, которая должна быть в разы быстрее.

Отвечу сразу на несколько комментариев разных людей одним сообщением.


Нельзя отправить сообщение с клиента. То есть отправить запрос с помощью AJAX или веб-формы на сервер, чтобы тот отправил push-уведомление нам на клиентскую сторону. Не работает.

Можно. Работает: https://gauntface.github.io/simple-push-demo/.


Не смотря на заявленную поддержку Firefox, в нем уведомления не работают.

Работают. Проверял на Windows и Android.


Честно говоря больше интересует, как можно реализовать свой собственный сервер уведомлений, а не использовать сторонние.

Смотря что подразумевается под сервером.


См.: https://github.com/mozilla-services/autopush.


Есть отличный учебник по Web Push — https://web-push-book.gauntface.com.


К этой книге прилагается демонстрационный проект на Node.js: https://github.com/gauntface/web-push-book/tree/master/src/demos/node-server.


Использовать Firebase Cloud Messaging не обязательно, есть Web Push Libraries. Для Node.js: https://github.com/web-push-libs/web-push, для PHP: https://github.com/web-push-libs/web-push-php.


Библиотека Firebase скрывает в себе много тайн и её исследование могло бы дать ответы на некоторые вопросы, но это уже выходит за рамки этой статьи.

А жаль, там много интересного. ) Думаю, я созрел для своей первой статьи для Хабра. :)

Можно. Работает: https://gauntface.github.io/simple-push-demo/.
Работают. Проверял на Windows и Android.

Как мне уже объяснил iSage и я сам об этом подозревал — это Firebase не может отправлять уведомления, а если реализовывать push-уведомления нативными средствами, то все работает. Что у вас и сделано.


А жаль, там много интересного. ) Думаю, я созрел для своей первой статьи для Хабра. :)

Я вижу что описанного материала многим недостаточно. И хотел бы написать статью/продолжение в которой описать больше технических тонкостей и альтернативных реализаций.
Готов уступить вам эту тему.

Форкнул репозиторий и открыл на GitHub Pages. Протестировал через curl в Chrome и Firefox на Windows. Результат, мягко говоря, ошеломляет.


В Chrome все доходит как и должно и уведомление отображается. В Firefox уведомление тоже доходит, но не отображается. Отрабатывает метод messaging.onMessage() на странице и печатает тело уведомления в блоке #messages. Через fetch я получил тот же результат. В Chrome этот метод не отрабатывает.


Получается в Firefox нужно использовать метод messaging.onMessage() и в нем реализовывать показ уведомления вручную. Поскольку этот метод реализован на странице, а не в Service Worker, то мы сталкиваемся с рядом проблем:


  • Нельзя получить уведомление если сайт не открыт в данный момент;
  • Нельзя получить уведомление при закрытом браузере;
  • Если сайт открыт в нескольких вкладках, то скрипт отрабатывает во всех вкладках.

Это лишь результаты беглого осмотра. Возможно я что-то упустил. У вас другие результаты?


И спасибо за ссылку. Добавил в статью.


PS: Странно то что у меня и без messaging.onMessage() в Firefox уведомления иногда отображались.

В Chrome этот метод не отрабатывает.

Какой именно метод?


К этому проекту прилагается видео https://youtu.be/BsCBCudx58g, в котором подробно объясняется, что к чему.


Обратите особое внимание на примечание о фокусе на странице https://github.com/firebase/quickstart-js/tree/master/messaging:


When the app has the browser focus, the received message is handled through the onMessage callback in index.html. When the app does not have browser focus then the setBackgroundMessageHandler callback in firebase-messaging-sw.js is where the received message is handled.

The browser gives your app focus when both:
  1. Your app is running in the currently selected browser tab.
  2. The browser tab's window currently has focus, as defined by the operating system.

Следует также принять во внимание, что поведение одного и того же браузера на разных платформах может различаться. Например, Firefox для Android и Mac могут после закрытия работать в фоновом режиме и, соответственно, принимать push-уведомления, а Firefox для Windows — нет.


Можно передавать сообщения из service worker'а на страницу: https://web-push-book.gauntface.com/chapter-05/04-common-notification-patterns/#message-page-from-a-push-event


Советую всё-таки прочитать книгу https://web-push-book.gauntface.com полностью, в ней есть ответы почти на все вопросы о web push. ;)

Точно. Вся проблема была в messaging.onMessage(). Теперь я понял почему не работало без него. Добавил обработчик и сразу все, везде заработало.


Спасибо большое.

// регистрируем пустой ServiceWorker каждый раз
navigator.serviceWorker.register('messaging-sw.js');

// запрашиваем права на показ уведомлений если еще не получили их
Notification.requestPermission(function(result) {

Регистрировать каждый раз ещё один пустой service worker со своим собственным жизненным циклом только для того, чтобы показать уведомление — костыль. Так как мы используем Firebase Cloud Messaging, то в момент вызова messaging.onMessage у нас уже должен быть зарегистрирован service worker firebase-messaging-sw.js с областью видимости /firebase-cloud-messaging-push-scope, и можно использовать его.


Насколько я понимаю, запрашивать права на показ уведомлений в messaging.onMessage тоже не нужно.


Таким образом, messaging.onMessage должен выглядеть как-то так:


messaging.onMessage((payload) => {
  navigator.serviceWorker.getRegistration('/firebase-cloud-messaging-push-scope').then((registration) => {
    registration.showNotification(payload.notification.title, payload.notification);
  });
});
Есть ли способ узнать статистику доставленных сообщений? Analytics вроде может такое, но он просит привязать Android-приложение.

На сколько мне известно, нет возможности посмотреть статистику по доставке сообщений.

Можно узнать сколько push-сообщений были потенциально отправлены (например смотря ответ после отправки и статус доставки). Клики можно отслеживать с помощью TDS или миллионов «сокращалок».

Можно узнать, сколько push-уведомлений было доставлено, открыто и закрыто, добавив в service worker обработчики событий push, notificationclick и notificationclose (пример: service-worker.js) и отправляя данные в Google Analytics с помощью протокола передачи статистических данных Measurement Protocol (пример: analytics-sw.js).

Нашел глюк в опере. С FF и в Хроме такого нет.
На основе этого кода сделал уведомления на своем сайте. Заметил, что в опере уведомления не приходят, хотя ошибки при отправке нет.
Вернулся сюда, открыл демо-проект, получаю токен, жму Send и тут начинают прихоодить уведомления с моего сайта, ну и последним приходит тестовое.
Копаю дальше и нашел закономерность: если после получения токена закрыть браузер и затем открыть, токен уже имеется, но уведомления не приходят. Если удалить токен и нажать «Register» для получения нового, то получаю ошибку «Error An error occurred while retrieving token.».
После перезагрузки браузера и нажатия «Register» новый токен получается и уведомления успешно приходят до тех пор, пока опять браузер не перезагрузишь.
Ну и каждый раз, когда получаю новый токен, доходят запоздавшие уведомления с моего сайта, если они были в это время.
У кого-нибудь еще такое в опере наблюдается?
Написал простенький php класс для отправки webpush -ей
вдруг комуто актуально)
работает вообще без зависимостей и строних библиотек
но нужен доступ к proc_open() и работающий бинарник
bin/openssl
для парсинга asn.

вот код:
github.com/aaarkadev/simpl_webpush/commit/9b277414bc3e6a1885f8ec9da5ee5c54271b92c6

пример:
```
$wpObj=new simpl_webpush();
echo $wpObj->get_curl_cmd('https://updates.push.services.mozilla.com/wpush/v2/gAAAAABZ1M11111111_h2hs47YE6u6dYJ3JN90HhF11111ORtCnJfASwcKZZYulq5ZgS');
```
Залез посмотреть в ленту. В общем, случайно меня занесло. Короче, это говнокод, даже для php. Удачи.
Пример из статьи отлично работает. Но заметил странное поведение в Chrome под Windows 10.
В момент, когда уведомление вылетело на экран. По нему можно кликнуть и откроется страница браузера. Но если попытаться кликнуть по уведомлению из шторки уведомлений Windows, то оно просто пропадает, а страница не открывается. Есть идеи как это исправить?
>> Web PUSH Notifications быстро и просто
>> будем использовать PHP с расширением cURL

это было больно

А что, cURL это сложно? Или вы имеете что-то против конкретно PHP?
Приведенный пример легко портируется на любой популярный язык программирования будь то Python, Java, Node.js или Go. Можно и через bash пуши отправлять (пример).

Only those users with full accounts are able to leave comments. Log in, please.