iOS'ta bir web uygulamasını (PWA) Ana Ekrana eklettirip App Store'a hiç uğramadan bildirim gönderebilir misin? Kısa cevap: 2023'ten beri evet, ama sınırları net çizilmiş bir "evet". Bu yazıda Safari'nin gerçekten neye izin verdiğini, neyi hâlâ vermediğini ve bu sınırların hangi ürün tipi için yeterli olduğunu WebKit ve Apple'ın kendi dokümanlarından, uydurma yüzde ya da anekdot katmadan öğreneceksin.
💡 Pro Tip: iOS'ta web push kurmadan önce tek bir şeyi test et: kullanıcı uygulamayı Ana Ekrana eklemeden önce izin isteği göstermeyi dene. Görmeyeceksin — çünkü Web Push yalnızca Ana Ekrana eklenmiş web app'lerde var; üstelik izin isteği doğrudan bir dokunuşa bağlı olmak zorunda, sayfa yüklenir yüklenmez ya da arka planda tetiklenemiyor.
İçindekiler
- iOS'ta PWA neyi yapabiliyor, neyi yapamıyor
- Web push: kurulum koşulu, izin akışı ve teslim garantisi
- Service worker, önbellek ve yaşam döngüsü kısıtları
- Ana ekrana ekleme dönüşümünü ölçmek
- Hangi ürün tipinde PWA yeterli, hangisinde değil
- Hibrit yol: PWA + ince native kabuk
- SSS
- iOS'ta PWA'ya push bildirimi gönderilebilir mi?
- PWA ile native uygulama arasındaki gerçek fark ne?
- Hangi ürün için PWA yeterli olur?
- Push izni reddedilirse ne olur?
- iOS'ta web push için sunucu tarafında farklı bir kod yazmam gerekir mi?
- iOS'ta PWA kurulumunu teşvik eden bir banner gösterebilir miyim?
- Güncelleme (Eylül 2026)
- Sonuç
- Kaynaklar
iOS'ta PWA neyi yapabiliyor, neyi yapamıyor
Safari 16.4 ile (27 Mart 2023) iOS ve iPadOS'ta Ana Ekrana eklenmiş web uygulamaları için standart tabanlı Web Push desteği geldi. WebKit'in kendi duyurusu net: "Today marks the release of iOS and iPadOS 16.4 beta 1... comes support for Web Push... for Home Screen web apps." Bu aynı zamanda yeni bir teknoloji değil — WebKit ekibi bunun "aynı W3C standartları tabanlı Web Push" olduğunu, macOS Ventura'da Safari 16.1 ile bir önceki sonbahardan (2022) beri var olduğunu belirtiyor.
16.4 ile gelen web app yetenekleri tek başına push'tan ibaret değil:
- Badging API:
navigator.setAppBadge()venavigator.clearAppBadge()ile Ana Ekran ikonunda sayı rozeti gösterebiliyorsun. - Manifest
idalanı: Aynı origin'den birden fazla web app kurulumunu ayırt etmeyi ve Focus senkronunu mümkün kılıyor. - Focus entegrasyonu: Ana Ekran web app'lerinin bildirimleri Focus (Odak) ile bütünleşiyor; kullanıcı bunları ne zaman ve nerede alacağını hassas şekilde yapılandırabiliyor.
- Native bildirim yüzeyi: WebKit'in ifadesiyle web app bildirimleri "diğer uygulamalardan gelen bildirimlerle birebir aynı şekilde çalışır" — Kilit Ekranı, Bildirim Merkezi ve eşleştirilmiş Apple Watch dahil.
Manifest id alanı pratikte şöyle görünür:
json
1{2 "id": "/app/",3 "name": "Örnek Web App",4 "start_url": "/app/?source=homescreen",5 "display": "standalone"6}Badging API'yi kullanmak için ayrı bir izin istemene gerek yok; push izni verilmiş bir web app'te doğrudan çağırabilirsin:
js
1// Okunmamış öğe sayısını Ana Ekran ikonunda göster2if ("setAppBadge" in navigator) {3 navigator.setAppBadge(unreadCount).catch((error) => {4 console.error("Badge güncellenemedi:", error);5 });6}7 8// Kullanıcı tüm öğeleri okuduğunda rozeti temizle9if ("clearAppBadge" in navigator) {10 navigator.clearAppBadge();11}WebKit Badging API desteğini Ana Ekrana eklenmiş web app'lere tanımlıyor: setAppBadge ve clearAppBadge, kullanıcı web app'i ön planda açık tuttuğunda ya da web app arka planda push olaylarını işlerken sayıyı değiştiriyor. Tarayıcı sekmesindeki sıradan bir sayfada bu davranışa güvenme.
Buna karşın iOS'ta hâlâ olmayan bir şey var: Chromium tarayıcılarının dayattığı otomatik kurulum teşviki. MDN'in kurulabilirlik rehberi Chromium tarafında, aralarında name/short_name, 192px+512px ikon, start_url ve display/display_override bulunan manifest alanlarının zorunlu olduğunu ve bunun beforeinstallprompt event'ini tetiklediğini anlatıyor — ama bu kriter seti Safari/iOS'a uygulanmıyor ve iOS'ta bu event hiç yok. Kurulum her zaman kullanıcının Paylaş menüsünden manuel "Ana Ekrana Ekle" adımına dayanıyor.
15 Eylül 2025'te yayımlanan iOS/iPadOS 26 bu tabloya bir madde daha ekledi: Apple'ın resmi sürüm notları "Added support for any website to become a web app on iOS or iPadOS" diyor — yani manifest'i olmayan sıradan bir site bile artık Ana Ekrana eklenip web app olarak davranabiliyor. Aynı sürümde, "Ana Ekrana Ekle" akışının sayfa verisini yükleyememesi ve yeni Ana Ekran web app'i oluşturmayı engellemesi sorunu da giderildi.
Aşağıdaki tablo, aynı yeteneğin iOS Safari ile Chromium tarayıcılarında ne zaman ve nasıl davrandığını yan yana koyuyor — kaynaksız bir "iOS her zaman kısıtlı" genellemesi yerine madde madde:
Yetenek | iOS Safari (16.4+) | Chromium tarayıcılar |
|---|---|---|
Kurulum tetikleyici | Yalnızca manuel Paylaş menüsü → Ana Ekrana Ekle | beforeinstallprompt event'i ile otomatik teşvik banner'ı |
Web app ön koşulu | Web app davranışı için manifest (display: standalone/fullscreen) gerekiyordu; iOS 26'dan itibaren manifest'siz site de web app olabiliyor | name/short_name, 192px+512px ikon, start_url, display/display_override dahil alanlar zorunlu |
Push izni tetikleyici | Yalnızca doğrudan kullanıcı etkileşimi (tap/click handler) | Sayfa yüklenirken de istenebilir (best practice olarak önerilmez ama teknik olarak mümkün) |
Bildirim yüzeyi | Native bildirimle birebir aynı (Kilit Ekranı, Bildirim Merkezi, Apple Watch) | Platform bildirim merkezine bağlı, tarayıcıdan tarayıcıya değişir |
Rozet (badge) | Badging API (setAppBadge/clearAppBadge), 16.4+ | Badging API desteği tarayıcıya göre değişir |
Web push: kurulum koşulu, izin akışı ve teslim garantisi
Kurulum sırası kesin: önce web app Ana Ekrana eklenmeli, ancak ondan sonra push izni istenebilir — ve bu istek "doğrudan kullanıcı etkileşimine yanıt olarak" tetiklenmek zorunda. Sayfa açılır açılmaz otomatik izin isteği göstermek iOS'ta çalışmaz; kullanıcının bir "bildirimleri aç" butonuna dokunması gerekir.
Sunucu tarafında ekstra bir şey öğrenmene gerek yok: Apple'ın kendi geliştirici dokümantasyonu, "Safari version 16.0 ve üzeri" için mevcut W3C Push API kodunun hem Safari'de hem diğer tarayıcılarda çalıştığını doğruluyor. Yani zaten standarda uygun (browser-sniffing yapmayan, feature-detection kullanan) bir push implementasyonun varsa iOS için ayrı bir kod yolu yazmana gerek kalmıyor.
Teslim garantisi konusunda ise abartılı rakamlara dikkat et. Apple'ın resmi çerçevesi net bir cümle kuruyor: "The system makes every attempt to deliver local and remote notifications in a timely manner, but delivery isn't guaranteed." Bu, iOS'a özgü bir kısıtlama değil — sistem genelinde, tüm bildirim türleri için geçerli bir uyarı. Herhangi bir kaynakta karşılaşacağın "%X teslim oranı" gibi sayılar Apple'ın resmi dokümanlarında yer almıyor; böyle bir iddiayla karşılaşırsan kaynağını sorgula.
js
1// Web app zaten Ana Ekrana eklenmiş, kullanıcı bir butona dokundu2async function subscribeToPush() {3 const registration = await navigator.serviceWorker.ready;4 5 // Push izni yalnızca bu fonksiyon bir "click" event handler'ı6 // içinden çağrıldığında iOS'ta çalışır — arka planda tetiklenemez7 const permission = await Notification.requestPermission();8 if (permission !== "granted") return null;9 10 const subscription = await registration.pushManager.subscribe({11 userVisibleOnly: true,12 applicationServerKey: VAPID_PUBLIC_KEY,13 });14 15 return subscription; // sunucuna gönder, APNs üzerinden iletilecek16}Service worker, önbellek ve yaşam döngüsü kısıtları
PWA'nın teknik omurgası service worker'dır ve MDN'in tanımıyla "ayrı bir thread'de çalışır" — offline önbellekleme ve arka plan görevleri bu worker üzerinden yürütülür. Bu, hesaplama açısından ağır işleri ana thread'i kilitlemeden arka planda yürütebilmeni sağlar.
Önbellekleme tarafında standart yol Cache API: MDN'in tarifiyle "Request/Response çiftleri için kalıcı depolama sağlar" ve çoğu uygulama bu kaynakları install veya fetch event handler'larında önbelleğe ekler — yani cache-first stratejisi kod düzeyinde bu iki event'e bağlı.
js
1const CACHE_NAME = "app-shell-v1";2const ASSETS = ["/", "/styles.css", "/app.js", "/offline.html"];3 4self.addEventListener("install", (event) => {5 event.waitUntil(6 caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS)),7 );8});9 10self.addEventListener("fetch", (event) => {11 event.respondWith(12 caches13 .match(event.request)14 .then((cached) => cached || fetch(event.request)),15 );16});Asıl sınır önbelleğin boyutunda değil, worker'ın ömründe. MDN'in offline/background rehberi bunu açıkça yazıyor: "This doesn't mean service workers run all the time: browsers may stop service workers when they think it is appropriate. For example, if a service worker has been inactive for a while, it will be stopped." Aynı rehber "ne kadar uzun sürenin fazla olduğu"nun tarayıcıya göre değiştiğini söyleyip Chrome için somut eşikler veriyor: 30 saniye boşta kalmak, 30 saniye senkron JavaScript çalıştırmak ya da waitUntil() ile verilen promise'in 5 dakikadan uzun sürmesi worker'ın kapatılmasına yol açıyor. waitUntil() da bir garanti değil: işlem uzarsa worker durduruluyor, handler bir sonraki sync olayında baştan çalışıyor.
Bunun pratik sonucu: kritik veriyi yalnızca Cache API ya da IndexedDB'ye güvenip sunucu tarafında bir yedeği olmadan saklama. Uzun süreli, kullanıcı etkileşimi olmadan tetiklenmesi gereken senkronizasyon ihtiyaçların varsa (örneğin gece yarısı toplu veri güncellemesi), bunu web platformunun garanti ettiği bir yetenek olarak değil, "kullanıcı uygulamayı açtığında tazelenir" modeliyle tasarlamak daha güvenli.
Ana ekrana ekleme dönüşümünü ölçmek
Chromium tarayıcılarında kurulum ölçümü nettir: beforeinstallprompt event'i tetiklenir, sen bunu dinler, kullanıcı kabul/red kararını event nesnesinden okursun. iOS'ta bu event hiç mevcut değil — MDN'in kurulabilirlik kriterleri listesi tamamen bu event'in var olduğu tarayıcılar için yazılmış, Safari için ayrı bir kriter ya da event tanımlanmamış.
Bunun pratik sonucu şu: iOS'ta "Ana Ekrana Ekle" dönüşümünü doğrudan bir API ile ölçemezsin. Elindeki tek güvenilir sinyal, uygulamanın zaten standalone modda mı yoksa tarayıcı sekmesinde mi açıldığı:
js
1function isRunningAsInstalledApp() {2 // iOS Safari'de web app modunda navigator.standalone true döner3 const iosStandalone = window.navigator.standalone === true;4 // Diğer tarayıcılarda display-mode media query kullanılır5 const displayModeStandalone = window.matchMedia(6 "(display-mode: standalone)",7 ).matches;8 return iosStandalone || displayModeStandalone;9}Bu sinyali analitik olayına ekleyip "kaç oturum standalone modda başladı" diye izleyebilirsin — ama bu, kurulum anını değil, zaten kurulmuş kullanıcının sonraki oturumlarını gösterir. Kurulum anının kendisi (kullanıcı Paylaş menüsünde "Ana Ekrana Ekle"ye dokunduğu an) iOS'ta JavaScript'e hiç sızmaz.
Hangi ürün tipinde PWA yeterli, hangisinde değil
Ürün ihtiyacı | iOS'ta PWA ile karşılanır mı | Kaynak/gerekçe |
|---|---|---|
Bildirim gönderme (sipariş, hatırlatma, kampanya) | Evet | Web Push + Badging + Focus entegrasyonu, native ile aynı yüzeyde |
Offline sayfa görüntüleme, temel form doldurma | Evet | Service worker + Cache API, install/fetch event'leri |
Arka planda sürekli konum takibi | Hayır | Service worker yaşam döngüsü bu tür sürekli arka plan görevini desteklemiyor |
Bluetooth ile eşleşen cihaz entegrasyonu | Hayır | Web Bluetooth iOS Safari'de desteklenmiyor |
Kurulumu App Store'a bağlamadan dağıtmak | Evet | Ana Ekrana Ekle, App Store onay sürecinin dışında |
Otomatik kurulum teşviki (banner/prompt) | Hayır | beforeinstallprompt iOS'ta yok, kurulum tamamen manuel |
Bildirim-ağırlıklı, orta karmaşıklıktaki ürünler için (haber uygulaması, sepet hatırlatma, randevu bildirimi) tablo net: PWA artık gerçek bir native alternatifi. Derin donanım entegrasyonu ya da sürekli arka plan senkronu isteyen ürünler için service worker'ın MDN'de tarif edilen yaşam döngüsü sınırları (MDN'in Chrome için verdiği eşiklerle 30 sn boşta kapanma ve waitUntil() için 5 dk tavan, ardından kesilen işin baştan çalışması) yetersiz kalıyor.
Kararı verirken kendine şu soruları sor: Ürünün ana değeri bir bildirimle mi tetikleniyor (yeni mesaj, fiyat düşüşü, randevu hatırlatması)? Kullanıcı oturumu genelde birkaç dakikalık mı, yoksa uygulamanın arka planda saatlerce açık kalması mı gerekiyor? Cevap "bildirim + kısa oturum" ise PWA'nın kapsamı (service worker + Push API + Badging API) büyük ölçüde yetiyor. Cevap "sürekli arka plan + donanım" ise service worker'ın MDN'de tarif edilen sınırlı yaşam döngüsü seni App Store'a geri götürüyor — bu durumda PWA'yı tamamen atlamak yerine, aşağıdaki hibrit yaklaşımı değerlendirmek daha ucuz olabilir.
Hibrit yol: PWA + ince native kabuk
İki gelişme, dağıtım sürtünmesini son dönemde azalttı. Birincisi, iOS 26'nın "herhangi bir site web app olabilir" genişlemesi — manifest'i olmayan sitelerin bile Ana Ekrana eklenip web app gibi davranabilmesi. İkincisi, Safari 16.4 ile üçüncü parti tarayıcıların da Paylaş menüsünden "Ana Ekrana Ekle" sunabilmesi; WebKit'in kendi ifadesiyle "third-party web browsers can offer 'Add to Home Screen' in the Share menu."
Bu ikisi birlikte, App Store dışı bir dağıtım stratejisini daha savunulabilir kılıyor: temel deneyimi (bildirim, offline, temel etkileşim) PWA'da tutup yalnızca gerçekten gerekli olan (derin donanım erişimi, StoreKit 2 üzerinden uygulama içi satın alma, platform-spesifik deep linking) parçalar için ince bir native kabuk eklemek. Bu, sıfırdan native yazmaktan farklı bir karar — PWA'nın kapsamını bilerek çizip geri kalanını native'e devretmek.
Pratikte bu hibrit yaklaşım genelde iki aşamalı ilerliyor. İlk aşamada tüm ürün PWA olarak yayınlanır: bildirim, offline sayfa görüntüleme ve temel form akışları web app'te kalır, App Store onay süreci hiç devreye girmez. İkinci aşamada, kullanıcı verisi PWA'nın yeterli olmadığı bir ihtiyacı (örneğin uygulama içi satın alma ya da derin platform entegrasyonu) doğrularsa, yalnızca o parça için native bir kabuk (WKWebView üzerine ince bir native katman ya da tamamen ayrı bir native ekran) eklenir. Bu sıralama, en baştan native yazıp sonradan "aslında PWA yeterliymiş" demekten çok daha ucuza geliyor — çünkü ilk aşamanın maliyeti bir web projesi maliyetiyle sınırlı kalıyor.
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Okuyucu Ödülü
Bu yazıyı buraya kadar okuduysan iOS'ta web push kurarken gözden kaçırılan noktaların çoğunu artık biliyorsun. Aşağıdaki kısa kontrol listesi, canlıya çıkmadan önce son bir tur atman için.
SSS
iOS'ta PWA'ya push bildirimi gönderilebilir mi?
Evet, Safari 16.4'ten (27 Mart 2023) beri gönderilebilir. Web app önce Ana Ekrana eklenmeli, ardından push izni doğrudan bir kullanıcı etkileşimiyle istenmeli. Bildirimler APNs üzerinden iletilir ve bunun için Apple Developer Program üyeliği gerekmez.
PWA ile native uygulama arasındaki gerçek fark ne?
Bildirim, offline çalışma ve rozet gösterimi açısından fark artık küçük — bunların hepsi web app'te de var. Asıl fark, derin donanım erişimi (Bluetooth, sürekli arka plan konum takibi gibi) ve kurulumun App Store üzerinden otomatik teşvik edilip edilememesinde: iOS'ta beforeinstallprompt yok, kurulum her zaman manuel Paylaş menüsü adımı.
Hangi ürün için PWA yeterli olur?
Bildirim-ağırlıklı, orta karmaşıklıktaki ürünler (haber, e-ticaret hatırlatma, randevu bildirimi, içerik uygulamaları) için PWA iOS'ta yeterli. Derin donanım entegrasyonu ya da sürekli arka plan senkronu gerektiren ürünler için service worker'ın kapsamı yetersiz kalır.
Push izni reddedilirse ne olur?
Reddedilen bir izni tarayıcı üzerinden tekrar otomatik isteyemezsin; kullanıcının izni kendisinin açması gerekir. WebKit, web app bildirimi izinlerinin web app başına Bildirim Ayarları'ndan yönetildiğini belirtiyor — kullanıcıyı oraya yönlendiren net bir yönerge göstermen gerekiyor. Bu yüzden izin isteğini kullanıcının değeri gördüğü bir ana ertelemek risk azaltır.
iOS'ta web push için sunucu tarafında farklı bir kod yazmam gerekir mi?
Hayır. Apple'ın kendi dokümantasyonu, Safari 16.0 ve üzeri için mevcut standart Push API kodunun (VAPID, applicationServerKey, pushManager.subscribe) hem Safari'de hem diğer tarayıcılarda aynı şekilde çalıştığını doğruluyor. Browser-sniffing yapmadığın sürece ek bir dal yazmana gerek yok.
iOS'ta PWA kurulumunu teşvik eden bir banner gösterebilir miyim?
Hayır, en azından Chromium'daki beforeinstallprompt event'i anlamında değil — bu event iOS Safari'de hiç yok. Yapabileceğin tek şey, kendi tasarladığın bir arayüz öğesiyle (ör. sayfanın altında sabit bir şerit) kullanıcıya Paylaş menüsünden "Ana Ekrana Ekle" adımını manuel olarak anlatmak; kurulumun kendisini tetikleyecek bir API çağrın olmuyor.
Güncelleme (Eylül 2026)
Bu yazının ilk hâli 16 Aralık 2025'te yayımlandı. Aradan geçen dokuz ayda WebKit'in duyurduğu, web push izin akışını, arka plan teslimatını, Badging API'yi ya da Ana Ekrana Ekle zorunluluğunu değiştiren köklü bir kısıt kaldırma bulunmuyor. Safari 27.0 sürüm notlarında (Web API, Networking, Storage bölümleri dahil) "push", "Notification" ya da "badge" ile ilgili yeni bir özellik (New Features) maddesi yer almıyor; Notification tarafındaki tek kayıt bir URL ayrıştırma düzeltmesi (176762955).
Bu döngüde asıl somut gelişme PWA'lar için ama push tarafında değil: Safari 27.0, Service Worker Static Routing API desteği ekledi. WebKit'in tarifiyle bu API, "service worker'ın belirli istekler için browser'ın service worker'ı tamamen atlamasına izin veren routing kuralları tanımlamasına olanak tanır" — yani yüksek performanslı PWA'larda gereksiz service worker devreye girişini azaltarak yükü düşürüyor. Bu bir performans iyileştirmesi, web push ya da bildirim yeteneklerinde yeni bir kapı açmıyor.
Kısacası: iOS'ta web push'un temel kuralları (Ana Ekrana ekleme şartı, kullanıcı etkileşimiyle sınırlı izin isteği, teslim garantisi vermeyen sistem) Aralık 2025'ten bu yana değişmedi.
Sonuç
iOS'ta PWA artık "eksik native" değil, net sınırları olan ayrı bir dağıtım seçeneği. Web push, Badging API ve Focus entegrasyonu ile bildirim-ağırlıklı ürünler için gerçek bir alternatif sunuyor; ama otomatik kurulum teşviki, sürekli arka plan görevleri ve donanım erişimi gibi alanlarda native'in yerini tutmuyor. Karar verirken ürününün hangi kategoriye girdiğini net çiz: sadece bildirim ve temel etkileşimse PWA yeterli, derin platform entegrasyonu şartsa ince bir native kabuk ekle.
İlgili konularda derinleşmek istersen: bildirim tarafının native APNs kısmını Advanced Push Notifications yazısında, uygulama içi satın alma kararını StoreKit 2 Production Rehberi'nde, çevrimdışı mimariyi iOS Offline-First Mimari'de, platformlar arası deep linking'i Deep Linking ve Universal Links'te, yeni materyal sistemini iOS 26 Liquid Glass'te bulabilirsin.
Kaynaklar
- Web Push for Web Apps on iOS and iPadOS — WebKit — Safari 16.4'te gelen Web Push, Badging API ve manifest id desteğinin resmi duyurusu.
- WebKit Features in Safari 16.4 — WebKit — Üçüncü parti tarayıcıların Share menüsünden Ana Ekrana Ekle sunabilmesi dahil 16.4'ün tam özellik listesi.
- UserNotifications — Apple Developer Documentation — Safari 16.0+ için sunucu taraflı Push API desteği ve "delivery isn't guaranteed" teslim garantisi notu.
- Safari 26.0 Release Notes — Apple Developer — "Added support for any website to become a web app on iOS or iPadOS" maddesi ve "Ana Ekrana Ekle" akışındaki düzeltme.
- Offline and background operation — MDN — Service worker'ın ayrı thread yapısı ve arka plan görev kapsamı.
- Caching — MDN Progressive web apps — Cache API ve install/fetch event tabanlı cache-first stratejisi.
- Making PWAs installable — MDN — Chromium'un kurulabilirlik kriterleri ve
beforeinstallpromptevent'i. - WebKit Features for Safari 27.0 — WebKit — Service Worker Static Routing API ve Eylül 2026 itibarıyla push/bildirim tarafında yeni madde bulunmadığının kaynağı.

