zaru / webpush

webpush, Encryption Utilities for Web Push protocol
MIT License
394 stars 73 forks source link

Low Delivery Issue #113

Open Rubioli opened 7 months ago

Rubioli commented 7 months ago

Hey

I've set up my webpush application, and subscription and all works fine (mostly mobile) but when sending the delivery % is low.

For instance today I sent 5,105 and only 777 was received. What could be the issue?

Versions:

ruby '3.0.3'
gem 'rails', '~> 6.1.4', '>= 6.1.4.6'
gem 'webpush', '~> 1.1'

Any help is much appreciated!

collimarco commented 6 months ago

How are you measuring the deliveries? Using fetch inside the push event is not very reliable / recommended.

Otherwise, if your web push list contains many old subscriptions, that can be the reason for low delivery rates.

Rubioli commented 6 months ago

Thanks @collimarco.

No the list doesn't contain many old subscribers. and for measuring Im using the serviceworker:

/* Version 1.1 */
/* eslint-env browser, serviceworker, es6 */
/* eslint no-console: ["warn", { allow: ["error"] }] */
"use strict";

/* Listen to the push event */
self.addEventListener("push", function(event) {
    if (!event.data) {
        return;
    }

    try {
        var notification_data = event.data.json();
        if (!notification_data || typeof notification_data !== 'object') {
            throw new Error("Invalid push data format");
        }

        var title = notification_data.title || "";
        var actions = notification_data.actions || [];
        var badge = notification_data.badge || "";
        var body = notification_data.body || "";
        var dir = notification_data.dir || "auto";
        var icon = notification_data.icon || "";
        var image = notification_data.image || "";
        var lang = notification_data.lang || "";
        var renotify = notification_data.renotify || false;
        var tag = notification_data.tag || "";
        var vibrate = notification_data.vibrate || [];

        if (notification_data.pid) {
            var pid = notification_data.pid;

            // Fetch data in the background
            event.waitUntil(
                fetch("https://site.com/data/show?pid=" + pid)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error("Network response was not ok");
                        }
                        return response;
                    })
                    .catch(error => console.error(error))
            );
        }

        return event.waitUntil(
            self.registration.showNotification(title, {
                actions: actions,
                badge: badge,
                body: body,
                dir: dir,
                icon: icon,
                image: image,
                lang: lang,
                renotify: renotify,
                tag: tag,
                vibrate: vibrate,
                data: notification_data,
                requireInteraction: true
            })
        );
    } catch (error) {
        console.error("Error processing push data:", error);
    }
});

self.addEventListener("notificationclick", function(event) {
    var notification = event.notification;
    var link = "";

    if (notification.data && notification.data.link) {
        link = notification.data.link;
    }

    event.notification.close();

    if (event.action != "close" && link != "") {
        if (notification.data && notification.data.pid) {
            var pid = notification.data.pid;

            // Fetch data in the background
            event.waitUntil(
                fetch("https://site.com/data/click?pid=" + pid)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error("Network response was not ok");
                        }
                        return response;
                    })
                    .catch(error => console.error(error))
            );
        }

        event.waitUntil(
            clients.openWindow(link)
        );
    }
});

self.addEventListener("notificationclose", function(event) {
    var notification = event.notification;
    var pid = 0;

    if (notification.data && notification.data.pid) {
        pid = notification.data.pid;
    }

    event.notification.close();

    // Fetch data in the background
    event.waitUntil(
        fetch("https://site.com/data/close?pid=" + pid)
            .then(response => {
                if (!response.ok) {
                    throw new Error("Network response was not ok");
                }
                return response;
            })
            .catch(error => console.error(error))
    );
});

And if I'm not mistaken this part handles it:

event.waitUntil(
                fetch("https://site.com/data/show?pid=" + pid)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error("Network response was not ok");
                        }
                        return response;
                    })
                    .catch(error => console.error(error))
            );

Appreciate any help :)

collimarco commented 6 months ago

Have you read my message above?

Using fetch inside the push event is not very reliable

Rubioli commented 6 months ago

Thanks for such a quick reply.

Then what would be the better way to do this? 😊