Notifications API, web sayfasının işletim sisteminin kendi bildirim sistemiyle kullanıcıya bildirim göstermesini sağlar. Önce bir kullanıcı hareketi (örneğin düğme tıklaması) içinde Notification.requestPermission() ile izin istenir; izin "granted" ise sayfadan new Notification("Başlık", { body: "..." }) ile ya da service worker kaydı üzerinden registration.showNotification() ile bildirim gösterilir. Mobil cihazları hedefliyorsanız ikinci yol zorunludur.
Bu yazıda kalıcı ve kalıcı olmayan bildirim farkını, izin durumlarını, bildirim seçeneklerini, tag ile bildirimleri değiştirmeyi, olayları ve service worker tarafında notificationclick işlemeyi MDN belgelerine göre anlatıyoruz. Sunucudan gelen push mesajlarıyla bildirim göndermek ayrı bir konudur ve push bildirim yazısında ele alınıyor. Tüm Web API konuları için Web API öğrenme rehberine bakabilirsiniz.
Web bildirimi nedir?
Web bildirimi, bir web uygulamasında olan bir olayı kullanıcıya haber veren mesaj kutusudur. İşletim sisteminin yerel bildirim sistemi tarafından çizildiği için platformdaki diğer uygulamaların bildirimleriyle aynı görünür. Sayfanın görüntü alanının dışında gösterildiğinden kullanıcı başka bir sekmeye ya da uygulamaya geçmiş olsa bile görünebilir. MDN'in tipik örneği, kullanıcı başka bir işle meşgulken yeni mesaj geldiğini bildirmesi gereken web tabanlı bir e-posta ya da sohbet uygulamasıdır.
Görünüm ve tam işlevsellik platformdan platforma değişir; API, çoğu sistem bildirim mekanizmasıyla uyumlu olacak kadar genel tasarlanmıştır. Bu yüzden bir seçeneğin her platformda aynı etkiyi yaratacağını varsaymamak gerekir; MDN örneğin dir seçeneğinin çoğu tarayıcıda yok sayıldığını not eder.
Kalıcı ve kalıcı olmayan bildirimler

API iki tür bildirim tanır. Kalıcı olmayan (non-persistent) bildirimler bir sayfada ya da sekmede Notification() kurucusuyla oluşturulur; ömürleri sayfanın ömrüne bağlıdır, sayfa kapanınca artık etkileşime girilemez ve click gibi olaylar doğrudan Notification nesnesinde tetiklenir. Kalıcı (persistent) bildirimler ise service worker kaydı üzerinden showNotification() ile oluşturulur, tek bir sayfanın ömrünü aşarak etkileşimli kalabilir ve olaylarını (notificationclick, notificationclose) service worker'ın global kapsamında alır.
| Özellik | Kalıcı olmayan | Kalıcı |
|---|---|---|
| Oluşturma | new Notification(title, options) | registration.showNotification(title, options) |
| Nerede çalışır | Sayfa veya sekme | Service worker kaydı |
| Ömür | Sayfa kapanınca etkileşim biter | Sayfanın ömrünü aşabilir |
| Tıklama olayı | Notification nesnesinde click | Service worker kapsamında notificationclick |
| Mobil | Kurucu çoğu mobil tarayıcıda TypeError fırlatır | Mobilde kullanılması gereken yol |
İzin istemek: Notification.requestPermission()
Bildirim göstermek için kullanıcının geçerli origin'e izin vermiş olması gerekir. Mevcut durum salt okunur Notification.permission özelliğinden okunur ve üç değerden biridir: "default" (kullanıcıya henüz sorulmadı, bildirim gösterilmez), "granted" (kullanıcı izin verdi) ve "denied" (kullanıcı açıkça reddetti). "default" durumunda tarayıcı izin reddedilmiş gibi davranır.
Notification.requestPermission() bir promise döndürür ve bu promise kullanıcının seçtiği değerle çözülür. Eski geri çağırma (callback) biçimi de vardır ama MDN onu kullanımdan kaldırılmış (deprecated) olarak işaretler. İzin istemi her zaman bir kullanıcı hareketine yanıt olarak açılmalıdır; MDN bunun yalnızca iyi uygulama olmadığını, tarayıcıların kullanıcı hareketi olmadan yapılan bildirim izni isteklerini açıkça engellemeye yöneldiğini anlatır. Kullanıcı etkinliği ve izinle ilgili hataların genel anlatımı için Web API hata yazısına bakın.
<button id="enable">Bildirimleri aç</button>const notificationBtn = document.querySelector("#enable");
function askNotificationPermission() {
if (!("Notification" in window)) {
console.log("This browser does not support notifications.");
return;
}
Notification.requestPermission().then((permission) => {
// İzin verildiyse düğmeyi gizle, reddedildiyse fikrini değiştirebilsin diye göster
notificationBtn.style.display = permission === "granted" ? "none" : "block";
});
}
notificationBtn.addEventListener("click", askNotificationPermission);MDN'in rehberine göre Chrome ve Firefox güvenli bağlam (HTTPS) olmayan sitelerde bildirim izni istenmesine hiç izin vermez ve çapraz origin iframe içinden izin istenemez. Kullanıcının verdiği karar genellikle oturum boyunca korunur. Bu nedenle sayfa açılır açılmaz izin istemek yerine kullanıcının bildirimin değerini anlayacağı bir anda, kendi düğmenizle istemek hem kullanıcı deneyimi hem de tarayıcı kuralları açısından doğru yoldur. HTTPS kurulumu için HTTPS rehberine bakabilirsiniz.
Bildirim oluşturmak
Kalıcı olmayan bildirim için Notification kurucusu bir başlık ve isteğe bağlı bir seçenek nesnesi alır. MDN'in yapılacaklar listesi örneği, süresi geçen bir görev için gövde metni ve simge içeren bir bildirim oluşturur:
if (Notification.permission === "granted") {
const img = "/img/icon-128.png";
const text = `"${title}" görevinin süresi doldu.`;
const notification = new Notification("Yapılacaklar", { body: text, icon: img });
}Kalıcı bildirimde ise önce etkin bir service worker gerekir. navigator.serviceWorker.ready etkin worker'a sahip kaydı verir; showNotification() bu kayıt üzerinden çağrılır ve undefined ile çözülen bir promise döndürür. Service worker'ın durumu activating ya da activated değilse ya da kullanıcı izni açıkça reddetmişse TypeError fırlatılır.
navigator.serviceWorker.register("sw.js");
async function showNotification() {
const result = await Notification.requestPermission();
if (result === "granted") {
const registration = await navigator.serviceWorker.ready;
registration.showNotification("Yeni sipariş", {
body: "1042 numaralı sipariş alındı.",
icon: "/icons/192.png",
tag: "siparis",
data: { url: "/siparis/1042" },
});
}
}Bildirim seçenekleri

showNotification() ve Notification() kurucusu benzer bir seçenek nesnesi alır. MDN'in showNotification() sayfasındaki listeden en sık kullanılanlar şunlardır; bazıları (örneğin actions ve navigate) yalnızca belirli bağlamlarda ya da tarayıcılarda geçerlidir, desteği MDN uyumluluk tablosundan kontrol edin.
| Seçenek | Anlamı | Varsayılan |
|---|---|---|
| body | Başlığın altında görünen gövde metni | Boş dize |
| icon | Başlık ve gövdenin yanında görünen küçük resim (logo, gönderen fotoğrafı) | Yok |
| image | İçerikte gösterilen büyük resim; üç resim seçeneği arasında en yüksek görsel önceliğe sahip | Yok |
| badge | Yer dar olduğunda (durum çubuğu gibi) uygulamayı temsil eden küçük simge | Yok |
| tag | Bildirimi tanımlayan etiket; aynı etiketli bildirimler birbirinin yerine geçer | Boş dize |
| renotify | Yeni bildirim eskisinin yerine geçtiğinde kullanıcı yeniden uyarılsın mı; true ise tag zorunlu | false |
| requireInteraction | Kullanıcı tıklayana ya da kapatana kadar açık kalsın mı | false |
| silent | Ses ve titreşim olmasın mı; true ise vibrate verilemez | null (cihaz ayarı) |
| vibrate | Titreşim deseni; silent true ise kullanılamaz | Yok |
| data | Bildirimle ilişkilendirilen ve structured clone ile kopyalanabilen herhangi bir veri | null |
| timestamp | Bildirimin ilgili olduğu zaman, Unix milisaniye | Yok |
| actions | Bildirimde gösterilecek eylem düğmeleri (action, title, icon) | Boş dizi |
| navigate | Bildirim etkinleştirilince gidilecek adres; click ve notificationclick yerine geçer | Yok |
Seçenekler arasındaki iki kural showNotification() için ayrıca TypeError nedeni olarak listelenir: silent true iken vibrate vermek ve renotify true iken tag değerini boş bırakmak. data seri hâle getirilemezse DataCloneError alınır. Bu kuralları bildirimi göstermeden önce yakalamak için küçük bir denetim fonksiyonu yazdık ve Node.js 24 ile çalıştırdık; data için kullanılan structured clone algoritmasını Web Workers yazısında anlattık.
// showNotification() için MDN'de TypeError nedeni olarak sayılan iki seçenek kuralı
function secenekSorunlari(secenekler) {
const sorunlar = [];
if (secenekler.silent === true && "vibrate" in secenekler) {
sorunlar.push("silent true iken vibrate verilemez");
}
if (secenekler.renotify === true && !secenekler.tag) {
sorunlar.push("renotify true ise tag boş olamaz");
}
return sorunlar;
}
console.log(JSON.stringify(secenekSorunlari({ body: "Yeni sipariş", tag: "siparis" }))); // []
console.log(JSON.stringify(secenekSorunlari({ renotify: true, silent: true, vibrate: [200] })));
// ["silent true iken vibrate verilemez","renotify true ise tag boş olamaz"]
const veri = structuredClone({ siparisNo: 1042, url: "/siparis/1042" });
console.log(veri.url); // /siparis/1042Bildirimleri tag ile değiştirmek
Kısa sürede çok sayıda bildirim kullanıcıyı rahatsız eder. Bunu önlemek için bildirime bir tag verilir. Aynı etikete sahip ve henüz gösterilmemiş bir bildirim varsa yeni bildirim onun yerine geçer; aynı etiketli bildirim zaten gösterilmişse eskisi kapatılır ve yenisi gösterilir. MDN'in örneğinde 200 milisaniye arayla on bildirim aynı tag ile oluşturulur ve kullanıcı yalnızca sonuncusunu görür. Yer değiştirmede kullanıcının yeniden sesli ya da titreşimli uyarılmasını istiyorsanız renotify: true kullanırsınız.
let i = 0;
const interval = setInterval(() => {
// Aynı tag sayesinde yalnızca son bildirim görünür
new Notification(`Mesaj ${i}`, { tag: "mesajlar" });
if (i === 9) {
clearInterval(interval);
}
i++;
}, 200);Bildirim olayları ve close()
Kalıcı olmayan bildirimde Notification nesnesinde dört olay tetiklenir: kullanıcı tıkladığında click, bildirim kapandığında close, bildirim gösterilemediğinde error, gösterildiğinde show. Notification bir EventTarget olduğu için bunlar onclick gibi özelliklerle ya da addEventListener() ile dinlenebilir; olay dinleyicilerinin ayrıntıları addEventListener yazısında. MDN önemli bir uyarı ekler: close olayı geldiğinde bildirimi kullanıcının kapattığının garantisi yoktur, platform da kapatmış olabilir.
Kullanıcı için artık anlamsız olan bir bildirimi close() ile kaldırabilirsiniz; örneğin kullanıcı mesajı sayfada zaten okuduysa. MDN, modern tarayıcıların bildirimleri birkaç saniye sonra (yaklaşık dört saniye) kendiliğinden kapattığını ve bunun kullanıcıya ve tarayıcıya bırakılması gerektiğini belirtir. close() bildirimi bildirim tepsisinden de kaldırdığı için, onu yalnızca sabit bir süre sonra ekrandan kaldırmak amacıyla kullanmamak gerekir.
const n = new Notification("Yeni şarkı çalıyor");
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
// Sekme görünür oldu, bildirim artık gereksiz
n.close();
}
});visibilitychange olayı ve sayfa yaşam döngüsünün diğer olayları sayfa yaşam döngüsü yazısında anlatılıyor.
Service worker tarafında notificationclick
Kalıcı bildirime tıklandığında service worker kapsamında notificationclick olayı tetiklenir; olay NotificationEvent türündedir, ExtendableEvent arayüzünden türediği için waitUntil() kullanılabilir, iptal edilemez ve kabarcıklanmaz. event.notification tıklanan bildirimi, event.action ise tıklanan eylem düğmesinin kimliğini verir. Aşağıdaki örnek MDN'den uyarlandı: önce bildirimi kapatır, sonra açık bir uygulama penceresi varsa ona odaklanır, yoksa yeni pencere açar.
// sw.js
self.addEventListener("notificationclick", (event) => {
event.notification.close();
if (event.action === "archive") {
// Kullanıcı "Arşivle" düğmesine bastı
return;
}
event.waitUntil(
clients.matchAll({ type: "window" }).then((clientList) => {
for (const client of clientList) {
if (client.url === new URL("/", self.location.origin).href && "focus" in client) {
return client.focus();
}
}
if (clients.openWindow) return clients.openWindow("/");
}),
);
});waitUntil() çağrısı, pencere açma ya da odaklama işi bitene kadar service worker'ın sonlandırılmamasını sağlar. Bildirim navigate seçeneğiyle oluşturulduysa tarayıcı bu olayı tetiklemek yerine doğrudan o adrese gider; bu seçeneğin desteği için MDN uyumluluk tablosuna bakın. Aynı kayıt üzerinden gösterilen bildirimlerin listesi registration.getNotifications() ile alınabilir; { tag } seçeneği listeyi etikete göre süzer. Aynı origin'deki farklı kapsamlı service worker'lar birbirinin bildirimlerini göremez.
Eylem düğmeleri: actions
Kalıcı bildirimlere actions seçeneğiyle düğmeler eklenebilir. Her öğe benzersiz bir action kimliği ve kullanıcıya gösterilecek title metni taşır, isteğe bağlı olarak icon da alır. Kullanıcı bir düğmeye bastığında notificationclick işleyicisinde event.action o kimliği verir; kullanıcı bir düğme dışında bir yere tıkladıysa ya da bildirimde düğme yoksa değer boş dizedir ve yukarıdaki örnekte olduğu gibi varsayılan yola düşülür. Tarayıcılar bir bildirimde gösterecekleri eylem sayısını genellikle sınırlar; bu üst sınır Notification.maxActions statik özelliğinden okunur. MDN'in örneği bir e-posta bildirimine "Archive" düğmesi ekler:
navigator.serviceWorker.ready.then((registration) => {
registration.showNotification("New mail from Alice", {
actions: [
{
action: "archive",
title: "Archive",
},
],
});
});Sık yapılan hatalar

- Sayfa yüklenir yüklenmez
requestPermission()çağırmak. İzin bir kullanıcı hareketine yanıt olarak istenmelidir. - Mobilde
new Notification()kullanmak. Çoğu mobil tarayıcıdaTypeErrorfırlatır; service worker veshowNotification()kullanın. Notification.permissiondeğerine bakmadan bildirim oluşturmak."default"ve"denied"durumunda bildirim gösterilmez.- HTTP sitede bildirim izni istemek. MDN'e göre bazı tarayıcılar güvenli bağlam olmadan izin istemine izin vermez.
- Her mesaj için ayrı bildirim göndermek. Aynı türdeki bildirimleri
tagile birleştirin. renotify: trueveriptageklememek ya dasilent: trueilevibratebirlikte vermek. İkisi deTypeErrornedenidir.- Bildirimi sabit bir süre sonra
close()ile kapatmak. Bildirim tepsiden de silinir ve kullanıcı sonradan göremez. notificationclickiçinde pencere açma işiniwaitUntil()ile sarmamak. Service worker iş bitmeden durdurulabilir.
Sık Sorulan Sorular
Kullanıcı izni reddettiyse yeniden sorabilir miyim?
Notification.permission "denied" olduğunda kullanıcı açıkça reddetmiş demektir. MDN'in örneği bu durumda bildirim yerine sayfa içi bir mesajla yetinir ve düğmeyi görünür bırakarak kullanıcının fikrini değiştirmesine alan tanır. İzin kararı genellikle tarayıcı ayarlarından değiştirilir.
Sayfa kapalıyken bildirim gösterebilir miyim?
Sayfa tarafındaki Notification() ile hayır; ömrü sayfaya bağlıdır. Service worker'dan showNotification() ile gösterilen kalıcı bildirimler sayfanın ömrünü aşabilir. Sunucunun tetiklediği bildirimler ise Push API ile service worker'ı uyandırmayı gerektirir.
Bildirime tıklayınca belirli bir sayfayı nasıl açarım?
Kalıcı bildirimde data seçeneğine adresi koyup notificationclick içinde clients.openWindow(event.notification.data.url) çağırabilirsiniz. Alternatif olarak navigate seçeneği, olay işleyici yazmadan doğrudan adrese gitmeyi sağlar; desteğini MDN uyumluluk tablosundan kontrol edin.
Bildirim kendiliğinden kapanıyor, açık kalmasını sağlayabilir miyim?
requireInteraction: true seçeneği, bildirimin kullanıcı tıklayana ya da kapatana kadar açık kalması gerektiğini belirtir. Son kararı yine platform ve tarayıcı verir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Web API öğrenme rehberi · Push bildirim nedir · Service worker kaydı · PWA ve manifest · İzin ve güvenli bağlam hataları