Kullanıcıları push bildirimlerine abone etme

Matt Gaunt

Push mesajları göndermek için önce kullanıcıdan izin almanız, ardından kullanıcının cihazını bir push hizmetine abone etmeniz gerekir. Bu işlemde, PushSubscription nesnesi almak için JavaScript API'si kullanılır. Ardından, bu nesneyi sunucunuza gönderirsiniz.

JavaScript API, bu süreci basit bir şekilde yönetir. Bu kılavuzda, özellik algılama, izin isteme ve abonelik sürecini yönetme dahil olmak üzere tüm akış açıklanmaktadır.

Özellik algılama

Öncelikle tarayıcının anlık mesajlaşmayı destekleyip desteklemediğini kontrol edin. Anlık bildirim desteğini iki kontrolle doğrulayabilirsiniz:

  • navigator nesnesinde serviceWorker olup olmadığını kontrol edin.
  • window nesnesinde PushManager olup olmadığını kontrol edin.
if (!('serviceWorker' in navigator)) {
  // Service Worker isn't supported on this browser, disable or hide UI.
  return;
}

if (!('PushManager' in window)) {
  // Push isn't supported on this browser, disable or hide UI.
  return;
}

Hem hizmet çalışanı hem de push mesajlaşma için tarayıcı desteği artıyor olsa da her iki özelliği de her zaman algılayın ve uygulamanızı kademeli olarak geliştirin.

Hizmet çalışanı kaydetme

Özellik algılamadan sonra, hizmet çalışanlarının ve push mesajlaşmanın desteklendiğini bilirsiniz. Ardından, hizmet çalışanınızı kaydedin.

Bir hizmet çalışanı kaydettiğinizde tarayıcıya hizmet çalışanı dosyanızın konumunu bildirirsiniz. Dosya bir JavaScript dosyasıdır ancak tarayıcı, dosyanın anlık mesajlaşma dahil olmak üzere service worker API'lerine erişmesine izin verir. Tarayıcı, dosyayı özellikle bir hizmet çalışanı ortamında çalıştırır.

Bir hizmet çalışanı kaydetmek için navigator.serviceWorker.register() işlevini çağırın ve dosyanızın yolunu iletin. Örneğin:

function registerServiceWorker() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function (err) {
      console.error('Unable to register service worker.', err);
    });
}

Bu işlev, tarayıcıya hizmet çalışanı dosyanızın konumunu bildirir. Burada, hizmet çalışanı dosyası /service-worker.js konumundadır. register() işlevini çağırdıktan sonra tarayıcı şu adımları uygular:

  1. Service worker dosyasını indirin.

  2. JavaScript'i çalıştırın.

  3. Dosya hatasız şekilde doğru çalışıyorsa register() tarafından döndürülen söz çözümlenir. Hata oluşursa söz reddedilir.

Not: register() reddederse Chrome Geliştirici Araçları'nda JavaScript'inizde yazım hatası veya hata olup olmadığını kontrol edin.

register() çözümlendiğinde ServiceWorkerRegistration döndürülür. Bu kaydı PushManager API'ye erişmek için kullanırsınız.

PushManager API tarayıcı uyumluluğu

Browser Support

  • Chrome: 42.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 16.

Source

İzin isteme

Service worker'ınızı kaydettirip izin aldıktan sonra kullanıcılardan push mesajı gönderme izni alın.

İzin alma API'si basittir. Ancak API yakın zamanda geri çağırma yerine Promise döndürecek şekilde değiştirildi. Tarayıcının hangi API sürümünü uyguladığını belirleyemediğiniz için her iki sürümü de uygulamanız ve yönetmeniz gerekir.

function askPermission() {
  return new Promise(function (resolve, reject) {
    const permissionResult = Notification.requestPermission(function (result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  }).then(function (permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error("We weren't granted permission.");
    }
  });
}

Önceki kodda, Notification.requestPermission() çağrısı kullanıcıya bir istem gösterir:

İzin istemi, masaüstü ve mobil Chrome'da gösterilir.

Kullanıcı, izin istemiyle etkileşime geçip İzin ver'i veya Engelle'yi seçtikten ya da istemi kapattıktan sonra sonucu dize olarak alırsınız: 'granted', 'default' veya 'denied'.

Örnek kodda, izin verilirse askPermission() tarafından döndürülen söz çözümlenir. Aksi takdirde, hata verilir ve söz reddedilir.

Kullanıcının Engelle düğmesini tıkladığı uç durumu ele alın. Bu durumda web uygulamanız, kullanıcıdan tekrar izin isteyemez. Kullanıcı, ayarlar panelinde izin durumunu değiştirerek uygulamanızın engellemesini manuel olarak kaldırmalıdır. İzin isteme zamanını ve yöntemini dikkatlice düşünün. Kullanıcı Engelle'yi tıklarsa bu kararı geri almak kolay olmaz.

Çoğu kullanıcı, uygulamanın neden izin istediğini anladığında izni verir.

Bu belgede, bazı popüler sitelerin izin isteme yöntemleri açıklanmaktadır.

PushManager ile kullanıcıyı abone yapma

Hizmet çalışanınızı kaydettirip izin aldıktan sonra registration.pushManager.subscribe() işlevini çağırarak kullanıcıları abone edebilirsiniz.

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

subscribe() yöntemini çağırdığınızda, zorunlu ve isteğe bağlı parametrelerden oluşan bir options nesnesi iletirsiniz.

Bu bölümde, iletebileceğiniz seçenekler açıklanmaktadır.

userVisibleOnly seçenekleri

Push mesajlaşma ilk kez tarayıcılara eklendiğinde geliştiriciler, bildirim göstermeden push mesajı gönderme konusunda tereddüt ediyordu. Bu işleme genellikle sessiz anlık bildirim adı verilir. Bunun nedeni, kullanıcının arka planda bir etkinlik gerçekleştiğini bilmemesidir.

Endişe, geliştiricilerin kullanıcının konumunu kullanıcının bilgisi olmadan sürekli olarak izleyebilmesiydi.

Bu senaryoyu önlemek ve spesifikasyon yazarlarının bu özelliği en iyi şekilde nasıl destekleyeceklerini düşünmelerini sağlamak için userVisibleOnly seçeneği eklendi. true değeri iletmek, web uygulamasının her push mesajı aldığında bildirim göstereceği (yani sessiz push olmayacağı) konusunda tarayıcıyla yapılan sembolik bir anlaşmadır.

true değerini geçirmeniz gerekir. userVisibleOnly anahtarını eklemezseniz veya false iletmezseniz aşağıdaki hatayı alırsınız:

Chrome currently only supports the Push API for subscriptions that will result
in user-visible messages. You can indicate this by calling
`pushManager.subscribe({userVisibleOnly: true})` instead. See
[https://goo.gl/yqv4Q4](https://goo.gl/yqv4Q4) for more details.

Chrome, Push API'yi yalnızca kullanıcı tarafından görülebilen mesajlarla sonuçlanan abonelikler için destekler. pushManager.subscribe({userVisibleOnly: true}) numaralı telefonu arayarak bunu belirtin. Daha fazla bilgi için https://goo.gl/yqv4Q4 adresini ziyaret edin.

Chrome'da genel sessiz anlık bildirim özelliğinin uygulanmayacağı anlaşılıyor. Bunun yerine, spesifikasyon yazarları, web uygulamalarının web uygulaması kullanımına göre belirli sayıda sessiz anlık bildirim göndermesine olanak tanıyan bir bütçe API'si üzerinde çalışıyor.

applicationServerKey seçeneği

Bu belgede daha önce uygulama sunucusu anahtarlarından bahsediliyordu. Bir push hizmeti, kullanıcıyı abone eden uygulamayı tanımlamak ve aynı uygulamanın kullanıcıya mesaj göndermesini sağlamak için uygulama sunucusu anahtarlarını kullanır.

Uygulama sunucusu anahtarları, uygulamanıza özgü bir genel ve özel anahtar çiftidir. Uygulamanızın özel anahtarını gizli tutun ve ortak anahtarı serbestçe paylaşın.

subscribe() çağrısına iletilen applicationServerKey seçeneği, uygulamanızın ortak anahtarıdır. Tarayıcı, kullanıcıyı abone ederken bu anahtarı bir push hizmetine iletir. Bu sayede push hizmeti, uygulamanızın genel anahtarını kullanıcının PushSubscription ile ilişkilendirebilir.

Aşağıdaki şemada bu adımlar gösterilmektedir.

  1. Web uygulamanızı bir tarayıcıya yükleyin ve subscribe() işlevini çağırarak herkese açık uygulama sunucusu anahtarınızı iletin.
  2. Ardından tarayıcı, bir push hizmetine ağ isteğinde bulunur. Bu hizmet bir uç nokta oluşturur, bu uç noktayı uygulamanızın ortak anahtarıyla ilişkilendirir ve uç noktayı tarayıcıya döndürür.
  3. Tarayıcı, bu uç noktayı PushSubscription'ya ekler. subscribe() sözü döndürülür.

Ortak uygulama sunucusu anahtarının `subscribe()` yönteminde nasıl kullanıldığını gösteren şema.

Push mesajı gönderdiğinizde, uygulama sunucunuzun özel anahtarıyla imzalanmış bilgileri içeren bir Authorization (Yetkilendirme) başlığı oluşturun. Push hizmeti, push mesajı gönderme isteği aldığında bu imzalı Authorization üstbilgisini, isteği alan uç noktayla bağlantılı ortak anahtarı arayarak doğrular. İmza geçerliyse push hizmeti, isteğin eşleşen özel anahtara sahip uygulama sunucusundan geldiğini bilir. Bu, başkalarının uygulamanızın kullanıcılarına mesaj göndermesini engelleyen bir güvenlik önlemidir.

Özel uygulama sunucusu anahtarının mesaj gönderirken nasıl kullanıldığını gösteren şema.

Teknik olarak applicationServerKey isteğe bağlıdır. Ancak Chrome'da en basit uygulama için bu gereklidir ve diğer tarayıcılarda da gelecekte gerekli olabilir. Firefox'ta isteğe bağlıdır.

VAPID spesifikasyonu, uygulama sunucusu anahtarını tanımlar. Uygulama sunucusu anahtarları veya VAPID anahtarlarıyla ilgili referanslar gördüğünüzde bunların aynı olduğunu unutmayın.

Uygulama sunucusu anahtarları oluşturma

web-push-codelab.glitch.me adresini ziyaret ederek veya anahtarları aşağıdaki gibi oluşturmak için web-push komut satırını kullanarak genel ve özel bir uygulama sunucusu anahtarı grubu oluşturabilirsiniz:

    $ npm install -g web-push
    $ web-push generate-vapid-keys

Bu anahtarları uygulamanız için yalnızca bir kez oluşturun ve özel anahtarı gizli tuttuğunuzdan emin olun.

İzinler ve subscribe()

Arama subscribe() özelliğinin bir yan etkisi vardır. Web uygulamanız, subscribe() işlevini çağırdığınızda bildirim gösterme iznine sahip değilse tarayıcı sizin için izin isteğinde bulunur. Kullanıcı arayüzünüz bu akışla çalışıyorsa bu yöntem kullanışlıdır. Ancak daha fazla kontrol istiyorsanız (çoğu geliştirici bunu ister) bu belgede daha önce bahsedilen Notification.requestPermission() API'yi kullanın.

PushSubscription'a genel bakış

subscribe()'ı arayıp seçenekleri geçiyorsunuz ve PushSubscription ile sonuçlanan bir söz alıyorsunuz. Örneğin:

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

PushSubscription nesnesi, ilgili kullanıcıya anlık bildirim göndermek için gereken tüm bilgileri içerir. İçerikleri JSON.stringify() kullanarak yazdırırsanız aşağıdakileri görürsünüz:

    {
      "endpoint": "https://some.pushservice.com/something-unique",
      "keys": {
        "p256dh":
    "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
        "auth":"FPssNDTKnInHVndSTdbKFw=="
      }
    }

endpoint, push hizmetinin URL'sidir. Anlık iletiyi tetiklemek için bu URL'ye bir POST isteği gönderin.

keys nesnesi, push mesajıyla gönderilen mesaj verilerini şifrelemek için kullanılan değerleri içerir. (Bu belgede ileti şifreleme konusu daha sonra ele alınacaktır.)

Sunucunuza abonelik gönderme

Push aboneliğiniz olduğunda bunu sunucunuza gönderin. Verileri nasıl göndereceğinizi siz belirlersiniz ancak abonelik nesnesinden gerekli tüm verileri ayıklamak için JSON.stringify() kullanmanız önerilir. Alternatif olarak, aynı sonucu manuel olarak da oluşturabilirsiniz. Örneğin:

const subscriptionObject = {
  endpoint: pushSubscription.endpoint,
  keys: {
    p256dh: pushSubscription.getKeys('p256dh'),
    auth: pushSubscription.getKeys('auth'),
  },
};

// The above is the same output as:

const subscriptionObjectToo = JSON.stringify(pushSubscription);

Aboneliği web sayfasından göndermek için aşağıdakileri kullanın:

function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(subscription),
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('Bad status code from server.');
      }

      return response.json();
    })
    .then(function (responseData) {
      if (!(responseData.data && responseData.data.success)) {
        throw new Error('Bad response from server.');
      }
    });
}

Node.js sunucusu bu isteği alır ve verileri daha sonra kullanılmak üzere bir veritabanına kaydeder.

app.post('/api/save-subscription/', function (req, res) {
  if (!isValidSaveRequest(req, res)) {
    return;
  }

  return saveSubscriptionToDatabase(req.body)
    .then(function (subscriptionId) {
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({data: {success: true}}));
    })
    .catch(function (err) {
      res.status(500);
      res.setHeader('Content-Type', 'application/json');
      res.send(
        JSON.stringify({
          error: {
            id: 'unable-to-save-subscription',
            message:
              'The subscription was received but we were unable to save it to our database.',
          },
        }),
      );
    });
});

Sunucunuzdaki PushSubscription ayrıntılarıyla kullanıcılarınıza istediğiniz zaman mesaj gönderebilirsiniz.

Aboneliğin süresinin dolmasını önlemek için düzenli olarak yeniden abone olun.

Push bildirimlerine abone olduğunuzda genellikle null PushSubscription.expirationTime alırsınız. Teoride bu, aboneliğin süresinin asla sona ermeyeceği anlamına gelir. (Buna karşılık, DOMHighResTimeStamp, geçerlilik bitiş zamanını tam olarak gösterir.) Ancak uygulamada tarayıcılar genellikle aboneliklerin süresinin dolmasına izin verir. Örneğin, uzun süre boyunca push bildirimi alınmadığında veya tarayıcı, kullanıcının push bildirimi izni olan bir uygulamayı kullanmadığını algıladığında bu durum oluşabilir. Bunu önlemek için kullanılabilecek bir yöntem, aşağıdaki snippet'te gösterildiği gibi, her bildirim alındığında kullanıcının yeniden abone olmasıdır. Bunun için, tarayıcının aboneliğin süresini otomatik olarak sona erdirmesini önleyecek sıklıkta bildirim göndermeniz gerekir. Aboneliğin süresinin dolmasını önlemek için kullanıcıya yalnızca istem dışı spam göndermeye karşı, meşru bildirim ihtiyaçlarının avantajlarını ve dezavantajlarını dikkatlice değerlendirmeniz gerekir. Sonuç olarak, tarayıcının kullanıcıyı uzun zaman önce unutulmuş bildirim aboneliklerinden koruma çabalarını atlatmaya çalışmamalısınız.

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

Sık sorulan sorular

Sık sorulan bazı soruları aşağıda bulabilirsiniz:

Tarayıcının kullandığı anlık bildirim hizmetini değiştirebilir misiniz?

Hayır, tarayıcı push hizmetini seçer. Bu belgede subscribe() çağrısıyla ilgili olarak belirtildiği gibi, tarayıcı PushSubscription öğesini oluşturan ayrıntıları almak için push hizmetine ağ istekleri gönderir.

Farklı push hizmetleri farklı API'ler mi kullanır?

Tüm anlık bildirim hizmetleri aynı API'yi bekler.

Web Push Protocol adı verilen bu ortak API, uygulamanızın push mesajını tetiklemek için yaptığı ağ isteğini açıklar.

Bir kullanıcıya masaüstünde abone olursam bu kullanıcı telefonda da abone olur mu?

Hayır. Kullanıcı, mesaj almak istediği her tarayıcıda anlık mesajlaşmaya kaydolmalıdır. Bunun için kullanıcının her cihazda izin vermesi gerekir.

Sonraki adımlar

Codelab uygulamaları