Untuk mengirim pesan push, Anda harus mendapatkan izin dari pengguna terlebih dahulu, lalu mendaftarkan perangkat mereka ke layanan push. Hal ini melibatkan penggunaan JavaScript API untuk mendapatkan objek PushSubscription, yang kemudian Anda kirim ke server.
JavaScript API mengelola proses ini secara langsung. Panduan ini menjelaskan seluruh alur, termasuk deteksi fitur, permintaan izin, dan pengelolaan proses langganan.
Deteksi fitur
Pertama, periksa apakah browser mendukung pesan push. Anda dapat memeriksa dukungan push dengan dua pemeriksaan:
- Periksa
serviceWorkerpada objeknavigator. - Periksa
PushManagerpada objekwindow.
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;
}
Meskipun dukungan browser untuk service worker dan pesan push terus meningkat, selalu deteksi kedua fitur tersebut dan tingkatkan aplikasi Anda secara progresif.
Mendaftarkan pekerja layanan
Setelah deteksi fitur, Anda tahu bahwa pekerja layanan dan pesan push didukung. Selanjutnya, daftarkan pekerja layanan Anda.
Saat mendaftarkan pekerja layanan, Anda memberi tahu browser lokasi file pekerja layanan Anda. File tersebut adalah file JavaScript, tetapi browser memberinya akses ke API pekerja layanan, termasuk pesan push. Secara khusus, browser menjalankan file di lingkungan pekerja layanan.
Untuk mendaftarkan service worker, panggil navigator.serviceWorker.register() dan teruskan jalur ke file Anda. Contoh:
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);
});
}
Fungsi ini memberi tahu browser lokasi file pekerja layanan Anda. Di sini, file pekerja layanan berada di /service-worker.js. Setelah Anda memanggil register(), browser akan melakukan langkah-langkah berikut:
Download file pekerja layanan.
Jalankan JavaScript.
Jika file berjalan dengan benar tanpa error, promise yang ditampilkan oleh
register()akan di-resolve. Jika terjadi error, promise akan ditolak.
Catatan: Jika register() menolak, periksa JavaScript Anda untuk menemukan kesalahan ketik atau error di Chrome DevTools.
Saat register() di-resolve, metode ini akan menampilkan ServiceWorkerRegistration. Anda menggunakan pendaftaran ini untuk mengakses PushManager API.
Kompatibilitas browser PushManager API
Meminta izin
Setelah mendaftarkan pekerja layanan dan mendapatkan izin, dapatkan izin dari pengguna untuk mengirim pesan push.
API untuk mendapatkan izin sangatlah sederhana. Namun, API tersebut baru-baru ini berubah dari mengambil callback menjadi menampilkan Promise. Karena Anda tidak dapat menentukan versi API yang diterapkan browser, Anda harus menerapkan dan menangani kedua versi tersebut.
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.");
}
});
}
Dalam kode sebelumnya, panggilan ke Notification.requestPermission() menampilkan perintah kepada pengguna:

Setelah pengguna berinteraksi dengan dialog izin dengan memilih Izinkan, Blokir, atau menutupnya, Anda akan menerima hasilnya sebagai string: 'granted', 'default', atau 'denied'.
Dalam kode contoh, promise yang ditampilkan oleh askPermission() akan diselesaikan jika izin diberikan; jika tidak, promise akan menampilkan error dan ditolak.
Menangani kasus ekstrem saat pengguna mengklik tombol Blokir. Jika hal ini terjadi, aplikasi web Anda tidak dapat meminta izin pengguna lagi. Pengguna harus membatalkan pemblokiran aplikasi Anda secara manual dengan mengubah status izinnya di panel setelan. Pertimbangkan dengan cermat kapan dan cara meminta izin, karena jika pengguna mengklik Blokir, keputusan tersebut tidak mudah dibatalkan.
Sebagian besar pengguna memberikan izin jika mereka memahami alasan aplikasi memintanya.
Dokumen ini membahas cara beberapa situs populer meminta izin di bagian selanjutnya dalam dokumen ini.
Mendaftarkan pengguna dengan PushManager
Setelah mendaftarkan pekerja layanan dan mendapatkan izin, Anda dapat membuat pengguna berlangganan dengan memanggil registration.pushManager.subscribe().
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;
});
}
Saat memanggil metode subscribe(), Anda meneruskan objek options yang terdiri dari parameter wajib dan opsional.
Bagian ini menjelaskan opsi yang dapat Anda teruskan.
Opsi userVisibleOnly
Saat pesan push pertama kali ditambahkan ke browser, developer tidak yakin apakah akan mengirim pesan push tanpa menampilkan notifikasi. Hal ini biasa disebut sebagai push senyap karena pengguna tidak mengetahui bahwa suatu peristiwa terjadi di latar belakang.
Kekhawatirannya adalah developer dapat melacak lokasi pengguna secara terus-menerus tanpa sepengetahuan pengguna.
Untuk menghindari skenario ini dan memungkinkan penulis spesifikasi mempertimbangkan cara terbaik untuk mendukung fitur ini, opsi userVisibleOnly ditambahkan. Meneruskan nilai true adalah perjanjian simbolis dengan browser bahwa aplikasi web menampilkan notifikasi setiap kali menerima pesan push (yaitu, tidak ada push senyap).
Anda harus meneruskan nilai true. Jika Anda tidak menyertakan kunci userVisibleOnly atau meneruskan false, Anda akan menerima error berikut:
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 hanya mendukung Push API untuk langganan yang menghasilkan pesan yang terlihat oleh pengguna. Tunjukkan hal ini dengan memanggil pushManager.subscribe({userVisibleOnly: true}). Untuk mengetahui informasi selengkapnya, lihat https://goo.gl/yqv4Q4.
Tampaknya push senyap menyeluruh tidak akan diterapkan di Chrome. Sebagai gantinya, penulis spesifikasi sedang mempelajari API anggaran yang memungkinkan aplikasi web mengirim sejumlah pesan push senyap berdasarkan penggunaan aplikasi web.
Opsi applicationServerKey
Dokumen ini sebelumnya menyebutkan kunci server aplikasi. Layanan push menggunakan kunci server aplikasi untuk mengidentifikasi aplikasi yang berlangganan pengguna dan untuk memastikan bahwa aplikasi yang sama mengirim pesan kepada pengguna tersebut.
Kunci server aplikasi adalah pasangan kunci publik dan pribadi yang unik untuk aplikasi Anda. Jaga kerahasiaan kunci pribadi untuk aplikasi Anda, dan bagikan kunci publik secara bebas.
Opsi applicationServerKey yang diteruskan ke panggilan subscribe() adalah kunci publik aplikasi Anda. Browser meneruskan kunci ini ke layanan push saat membuat langganan untuk pengguna, sehingga layanan push dapat mengaitkan kunci publik aplikasi Anda dengan PushSubscription pengguna.
Diagram berikut menggambarkan langkah-langkah ini.
- Muat aplikasi web Anda di browser dan panggil
subscribe(), dengan meneruskan kunci server aplikasi publik Anda. - Browser kemudian membuat permintaan jaringan ke layanan push, yang menghasilkan endpoint, mengaitkan endpoint ini dengan kunci publik aplikasi Anda, dan menampilkan endpoint ke browser.
- Browser menambahkan endpoint ini ke
PushSubscription, yang ditampilkan oleh promisesubscribe().
Saat Anda mengirim pesan push, buat header Authorization yang berisi informasi yang ditandatangani dengan kunci pribadi server aplikasi Anda. Saat layanan push menerima permintaan untuk mengirim pesan push, layanan tersebut akan memvalidasi header Authorization yang ditandatangani ini dengan mencari kunci publik yang ditautkan ke endpoint yang menerima permintaan. Jika tanda tangan valid, layanan push akan mengetahui bahwa permintaan berasal dari server aplikasi dengan kunci pribadi yang cocok. Ini adalah tindakan keamanan yang mencegah orang lain mengirim pesan ke pengguna aplikasi Anda.
Secara teknis, applicationServerKey bersifat opsional. Namun, penerapan paling sederhana di Chrome memerlukannya, dan browser lain mungkin memerlukannya pada masa mendatang. Tindakan ini opsional di Firefox.
Spesifikasi VAPID menentukan kunci server aplikasi. Jika Anda melihat referensi ke kunci server aplikasi atau kunci VAPID, ingatlah bahwa keduanya sama.
Membuat kunci server aplikasi
Anda dapat membuat kumpulan kunci server aplikasi publik dan pribadi menggunakan command line web-push untuk membuat kunci sebagai berikut:
$ npm install -g web-push
$ web-push generate-vapid-keys
Buat kunci ini hanya sekali untuk aplikasi Anda, dan pastikan Anda menjaga kerahasiaan kunci pribadi.
Izin dan subscribe()
Memanggil subscribe() memiliki satu efek samping. Jika aplikasi web Anda tidak memiliki izin untuk menampilkan notifikasi saat Anda memanggil subscribe(), browser akan meminta izin untuk Anda. Hal ini berguna jika UI Anda berfungsi dengan alur ini, tetapi jika Anda menginginkan kontrol lebih (yang dilakukan sebagian besar developer), gunakan Notification.requestPermission() API yang telah dibahas dalam dokumen ini sebelumnya.
Ringkasan PushSubscription
Anda memanggil subscribe(), meneruskan opsi, dan menerima promise yang di-resolve ke PushSubscription. Contoh:
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;
});
}
Objek PushSubscription berisi semua informasi yang diperlukan untuk mengirim pesan push ke pengguna tersebut. Jika Anda mencetak konten menggunakan JSON.stringify(), Anda akan melihat hal berikut:
{
"endpoint": "https://some.pushservice.com/something-unique",
"keys": {
"p256dh":
"BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
"auth":"FPssNDTKnInHVndSTdbKFw=="
}
}
endpoint adalah URL layanan push. Untuk memicu pesan push, buat permintaan POST ke URL ini.
Objek keys berisi nilai yang digunakan untuk mengenkripsi data pesan yang dikirim dengan pesan push. (Dokumen ini akan membahas enkripsi pesan nanti.)
Mengirim langganan ke server Anda
Setelah Anda memiliki langganan push, kirimkan ke server Anda. Anda dapat menentukan cara mengirimkannya, tetapi sebaiknya gunakan JSON.stringify() untuk mengekstrak semua data yang diperlukan dari objek langganan. Atau, Anda dapat menyusun hasil yang sama secara manual, misalnya:
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);
Untuk mengirim langganan dari halaman web, gunakan kode berikut:
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.');
}
});
}
Server Node.js menerima permintaan ini dan menyimpan data ke database untuk digunakan nanti.
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.',
},
}),
);
});
});
Dengan detail PushSubscription di server, Anda dapat mengirim pesan kepada pengguna kapan saja.
Berlangganan lagi secara rutin untuk mencegah masa berlaku habis
Saat berlangganan notifikasi push, Anda sering menerima PushSubscription.expirationTime dari null. Secara teori, ini berarti langganan tidak pernah berakhir. (Sebaliknya, DOMHighResTimeStamp menunjukkan waktu habis masa berlaku yang tepat.) Namun, dalam praktiknya, browser biasanya membiarkan langganan berakhir. Misalnya, hal ini dapat terjadi jika tidak ada notifikasi push yang diterima dalam waktu lama, atau jika browser mendeteksi bahwa pengguna tidak menggunakan aplikasi yang memiliki izin notifikasi push. Salah satu pola untuk mencegah hal ini adalah dengan mendaftarkan ulang pengguna setiap kali notifikasi diterima, seperti yang ditunjukkan dalam cuplikan berikut. Hal ini mengharuskan Anda mengirim notifikasi cukup sering untuk mencegah browser mengakhiri langganan secara otomatis. Anda harus mempertimbangkan dengan cermat keuntungan dan kerugian dari kebutuhan notifikasi yang sah dibandingkan dengan mengirim spam kepada pengguna secara tidak sengaja hanya untuk mencegah masa berlaku langganan berakhir. Pada akhirnya, Anda tidak boleh mencoba mengakali upaya browser untuk melindungi pengguna dari langganan notifikasi yang sudah lama terlupakan.
/* 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);
});
}
Pertanyaan umum (FAQ)
Berikut beberapa pertanyaan umum:
Dapatkah Anda mengubah layanan push yang digunakan browser?
Tidak, browser memilih layanan push. Seperti yang dibahas dalam dokumen ini dengan panggilan subscribe(), browser membuat permintaan jaringan ke layanan push untuk mengambil detail yang membentuk PushSubscription.
Apakah layanan push yang berbeda menggunakan API yang berbeda?
Semua layanan push mengharapkan API yang sama.
API umum ini, yang disebut Protokol Push Web, menjelaskan permintaan jaringan yang dibuat aplikasi Anda untuk memicu pesan push.
Jika Anda membuat pengguna berlangganan di desktop, apakah mereka juga berlangganan di ponsel?
Tidak. Pengguna harus mendaftar untuk pesan push di setiap browser tempat mereka ingin menerima pesan. Hal ini juga mengharuskan pengguna memberikan izin di setiap perangkat.
Langkah berikutnya
- Ringkasan Notifikasi Push Web
- Cara kerja pesan push
- Mendaftarkan pengguna
- Pengalaman pengguna terkait izin
- Mengirim pesan dengan library push web
- Protokol Push Web
- Menangani peristiwa push
- Menampilkan notifikasi
- Perilaku notifikasi
- Pola notifikasi umum
- Pertanyaan umum (FAQ) tentang notifikasi push
- Masalah umum dan pelaporan bug