Ana içeriğe geç

OneSignal'dan geçiş

Open Notification bilerek OneSignal'ın zihinsel modelini yansıtır — external id'li ve tag'li kullanıcılar, login/logout, segmentler, kampanya sihirbazı, ulaştı/açıldı/tıklandı raporları — dolayısıyla ekibinizin bildiği çoğu şey çalışmaya devam eder. Geçişin zor kısmı API değil, token'lardır.

Ne taşınabilir

VeriTaşınırNeden
APNs cihaz token'larıBundle ID'nize bağlıdır; kendi .p8'iniz onlara gönderir.
FCM registration token'larıSizin Firebase projenize aittir — OneSignal sizin service account'unuzu kullanıyordu.
Web push abonelikleriEndpoint'ler OneSignal'ın VAPID public key'ine bağlıdır; dışa aktarmazlar. Yeniden toplayın.
Tag'ler, external id'ler, dil, saat dilimi, ülkeCSV export'tan.
Kampanya geçmişi⚠️Yalnızca toplam sayılar, olay bazında değil.
Web push sıfırdan başlar

Her tarayıcı aboneliği, oluşturulduğu VAPID anahtarına kriptografik olarak bağlıdır. Kesimden haftalar önce, OneSignal göndermeye devam ederken kendi anahtarınızla abonelik toplamaya başlayın — ikisi yan yana sorunsuz çalışır.

Kavram eşlemesi

OneSignalOpen Notification
AppUygulama
User / external_idexternalId'li Kullanıcı
Subscription (push token)Abonelik
OneSignal.login(id) / logout()login(externalId) / logout() — aynı merge semantiği
addTags / removeTagssetTags (merge) / removeTags (null siler)
Segmentlerde data tagsegment oluşturucuda tags.<key> alanları
Kayıtlı segmentlerSegmentler kampanya başına satır içidir; yeniden kullanacaksanız JSON'u kendiniz saklayın
Message → "Send to particular users"target.externalIds ile POST /v1/notifications
Intelligent deliveryschedule.type = "user_timezone"
Frequency cappingTeslimat kuralları
A/B testA/B testi
REST API keysk_live_… sunucu anahtarı
App ID (client)pk_live_… public anahtar
Notification Service ExtensioniOS'ta hâlâ gerekli — bizimki iOS SDK'sında şablon olarak gelir

CSV export'tan token içe aktarma

OneSignal export'unda şu sütunlar var: identifier (push token), device_type (0 iOS, 1 Android, 5 Chrome web…), external_user_id, tags, language, timezone_id, country, last_active, notification_types (-2 = çıkmış).

Paneli kullanın: Abonelikler › İçe aktar, biçim OneSignal, dosyayı bırakın. Her satır SDK'ların kullandığı upsert'ten geçer, kullanıcılar ve tag'ler doğru çıkar; çıkmış ve geçersiz satırlar atlanır, anahtarlarıyla web satırları da aktarılır, sonuç kartı reddedilen satırları listeler. Bkz. Abone içe aktarma.

Betikle yapmayı yeğlerseniz (özel bir export, yolda bir dönüşüm) public API aynı işi satır başına bir POST /v1/subscriptions ile yapar:

// import-onesignal.ts — bun ile çalıştırın
import { parse } from "csv-parse/sync";

const rows = parse(await Bun.file("players.csv").text(), { columns: true });
const API = "https://push.example.com";
const KEY = process.env.PUBLIC_KEY!; // pk_live_…

for (const row of rows) {
if (!row.identifier || row.notification_types === "-2") continue;
if (row.device_type !== "0" && row.device_type !== "1") continue; // web içe aktarılamaz

const tags = row.tags ? JSON.parse(row.tags) : {};
const res = await fetch(`${API}/v1/subscriptions`, {
method: "POST",
headers: { "x-app-key": KEY, "content-type": "application/json" },
body: JSON.stringify({
platform: row.device_type === "0" ? "ios" : "android",
token: row.identifier,
externalId: row.external_user_id || undefined,
tags,
language: row.language || undefined,
timezone: row.timezone_id || undefined,
country: row.country || undefined,
}),
});
if (!res.ok) console.error(row.identifier.slice(-6), await res.text());
}

Hızı sınırlayın: public anahtar sır olmadığı için subscribe ucu istemci IP'si başına sınırlıdır (SUBSCRIBE_RATE_LIMIT, varsayılan 10/dk). İçe aktarım için sınırı geçici olarak yükseltin ya da script'i API sunucusunun kendisinde çalıştırın.

İlk gerçek kampanyadan önce doğrulayın

İçe aktarımdaki ölü token'lar ilk teslimat oranınızı berbat gösterir. İçe aktardıktan sonra herkese bir sessiz kampanya gönderin (sihirbazda Sessiz push ya da boş data ile "silent": true) — worker yol üstünde her 410/Unregistered/UNREGISTERED aboneliği geçersizler ve raporun Başarısızlık nedenleri tablosu export'un ne kadarının zaten ölü olduğunu söyler.

Paralel çalışma planı

Hafta 1–2 Open Notification SDK'sını OneSignal'ınkinin yanına ekleyin. Token
toplar, olay raporlar; henüz onunla bir şey göndermezsiniz.
Sürümü yayınlayıp çoğu kullanıcıya ulaşmasını bekleyin.

Hafta 3 Oturumların ~%90'ı yeni sürümdeyken kalan OneSignal token'larını
CSV'den içe aktarın (API token'a göre upsert eder; SDK'nın zaten
kaydettiği cihazlar yalnızca güncellenir).

Hafta 4 Trafiği kaydırın: kampanyaların %10 → %50 → %100'ü. Her adımda
platform başına teslimat oranını OneSignal'ınkiyle karşılaştırın.

Hafta 5 OneSignal SDK'sını kaldırın. Hesabı kapatın.

iOS'ta iki SDK demek APNs token'ını iki şeyin istemesi demek — sorun değil; ikisi de aynı token'ı alır. Android'de ikisi de bir FirebaseMessagingService kaydeder; yalnızca biri mesaj alabilir. Ya OneSignal'ın servisinden onMessageReceived'i OpenNotificationMessagingService.handle(message)'a iletin ya da Android gönderimlerini 4. haftaya kadar OneSignal'da tutun.

Bilerek farklı olanlar

  • Açılma oranı sent'e değil delivered'a bölünür. OneSignal'ın rakamları aynı kampanya için bizimkinden yüksek görünür. Dürüst olan bizimki: hiç ulaşmayan bir push açılamaz.
  • Android mesajları data-only'dir. Bildirimi uygulamanız çizer (SDK yapar); delivered'ı izlenebilir kılan budur. Zorla durdurulmuş uygulamalar ve agresif OEM pil tasarrufu data mesajlarını düşürebilir; SDK bunu en aza indirmek için priority: high ile gönderir.
  • E-posta, SMS ya da in-app kanalı yok. Yalnızca push.
  • Segmentler kayıtlı nesne değildir. Kampanya kendi segment JSON'unu taşır; sihirbazdan kampanyalar arasında kopyalayın ya da kendi kodunuzda tutun.