Pushizo Docs
Rehberler

OneSignal'den Pushizo'ya göç

Pushizo, OneSignal'in kavram modelini (app, abonelik, kullanıcı/alias, tag, segment, şablon, journey) ve SDK yüzeyini (initialize → login → User.addTags → Notifications.requestPermission → Session.sendEvent) bilinçli…

Pushizo, OneSignal'in kavram modelini (app, abonelik, kullanıcı/alias, tag, segment, şablon, journey) ve SDK yüzeyini (initialize → login → User.addTags → Notifications.requestPermission → Session.sendEvent) bilinçli olarak korur. Bu rehber mevcut bir OneSignal uygulamasını kesintisiz taşımanın adımlarını, alan/uç eşlemelerini ve SDK değişikliklerini anlatır.

Araçlar: npm run migrate:onesignal (scripts/migrate-onesignal.ts), CSV içe aktarıcı (packages/db/src/data-transfer.ts → mapOneSignalRow), Postman koleksiyonu (api/postman_collection.json).

1. Genel plan

AdımSüreÇıktı
1. Hesap, organizasyon ve app oluşturma10 dkapp_… kimliği
2. Kanal kimlik bilgileri (APNs .p8, FCM servis hesabı, VAPID, e-posta/SMS)30 dkKanallar active
3. Player/abonelik göçü (migrate:onesignal → CSV → içe aktarma)dosya boyutuna göreKullanıcılar, tag'ler, iOS/Android/e-posta/SMS abonelikleri
4. Sunucu entegrasyonu (REST → Pushizo public API / sunucu SDK'ları)1–3 günBildirim, kullanıcı, olay çağrıları
5. İstemci SDK değişimi (Web/iOS/Android/Flutter, React Native/Capacitor/Cordova/.NET MAUI/Unity)1–2 günYeni sürüm yayını
6. Çift yazma dönemi ve kesinti2–4 haftaOneSignal kapatılır

2. Hesap ve app oluşturma

  1. Dashboard'da kayıt olun (/register), e-posta doğrulaması ve isteğe bağlı MFA'yı tamamlayın. Her hesap bir organizasyon altında çalışır; organizasyon OneSignal'deki "hesap", app ise OneSignal app'inin karşılığıdır.
  2. Başlangıç sihirbazı (/<org>/getting-started) ile app'i oluşturun ya da public API'den: POST /v1/apps (org geneli admin anahtarı gerekir).
  3. Organizasyon → API anahtarları'ndan bir sunucu anahtarı (hs_live_…) üretin. Kapsamlar OneSignal REST API anahtarından daha incedir: notifications:write, users:read, users:write, events:write, segments:read, analytics:read, admin. Göç için admin kapsamlı, IP izin listeli ve bitiş tarihli bir anahtar önerilir.
  4. Kanallar sayfasında OneSignal'de kullandığınız kimlik bilgilerini aynen girin:
OneSignal ayarıPushizo kanalıNotlar
Apple → .p8 anahtarı, Key ID, Team ID, Bundle IDiOS Push (ios_push)Ortam sandbox / production; aynı .p8 her iki tarafta çalışır.
Google → Firebase servis hesabı JSONAndroid Push (android_push)Aynı Firebase projesi kullanılır; cihaz token'ları geçerliliğini korur.
Web → Safari/Chrome ayarlarıWeb Push (web_push)Pushizo kendi VAPID çiftini üretir; mevcut tarayıcı abonelikleri taşınamaz (bkz. §4.3).
E-posta (SendGrid vb.)E-posta (email)SMTP / Amazon SES / Resend; gönderici alan adını yeniden doğrulayın (SPF/DKIM/DMARC).
SMS (Twilio)SMS (sms)Twilio hesap bilgileri aynen; Netgsm de desteklenir.

Her kanalda Doğrula düğmesi (POST /v1/apps/{app_id}/channels/{channel}/validate) sağlayıcıya test bağlantısı yapar.

3. Player (abonelik) göçü

3.1 npm run migrate:onesignal

Araç OneSignal "View devices" API'sinden (GET /players, 300'lük sayfalar) ya da büyük uygulamalar için POST /players/csv_export ile cihazları çeker, Pushizo'nun onesignal_players CSV biçimine yazar ve istenirse doğrudan içe aktarmayı başlatıp tamamlanana kadar izler.

# Yalnızca CSV üret
npm run migrate:onesignal -- --onesignal-app-id <ONESIGNAL_APP_ID> --onesignal-key <REST_API_KEY> --out players.csv

# Büyük uygulama: OneSignal csv_export (gz) kullan
npm run migrate:onesignal -- --onesignal-app-id <id> --onesignal-key <key> --csv-export --out players.csv

# CSV üret ve Pushizo'ya içe aktar (iş tamamlanana kadar bekler)
npm run migrate:onesignal -- --onesignal-app-id <id> --onesignal-key <key> \
  --hs-api-url https://api.pushizo.com --hs-api-key hs_live_… --hs-app-id app_…

Ortam değişkenleri de kabul edilir: ONESIGNAL_APP_ID, ONESIGNAL_REST_API_KEY, HS_API_URL, HS_API_KEY, HS_APP_ID. Çıktı stdout'a JSON olarak yazılır: { players, file, importId, importStatus, stats }.

CSV başlıkları OneSignal'in dışa aktarma biçimiyle aynıdır (id, identifier, session_count, language, timezone, game_version, device_os, device_type, device_model, ad_id, tags, last_active, playtime, amount_spent, created_at, invalid_identifier, badge_count, external_user_id, notification_types). OneSignal panelinden indirdiğiniz "Export" dosyasını da aracı kullanmadan doğrudan yükleyebilirsiniz.

3.2 CSV'yi elle içe aktarma

curl -X POST "https://api.example.com/v1/apps/app_…/imports" \
  -H "Authorization: Bearer hs_live_…" \
  -F type=onesignal_players -F file=@players.csv
# → { "id": "imp_…", "status": "queued" }
curl "https://api.example.com/v1/apps/app_…/imports/imp_…" -H "Authorization: Bearer hs_live_…"
# → { "status": "completed", "stats": { "processed", "created_users", "updated_users", "created_subscriptions", "skipped", "errors" }, "error_report_url": "…" }

Dashboard eşdeğeri: Kitle → Dışa / İçe Aktarım. Dosya sınırı 50 MB ve 500.000 satırdır; daha büyük dosyaları bölün. İçe aktarma idempotenttir: aynı dosya ikinci kez yüklendiğinde kullanıcı ve abonelik yinelenmez.

3.3 Alan eşleme tablosu (mapOneSignalRow)

OneSignal sütunuPushizo alanıKural
external_user_idexternal_idBoşsa ve identifier varsa anonim kullanıcı oluşturulur; ikisi de boşsa satır hata raporuna düşer.
identifierabonelik tokenPush token / e-posta / telefon. E-posta küçük harfe, telefon E.164'e normalize edilir; geçersizse satır atlanır.
device_typeabonelik channel0 → ios_push; 1, 2, 13 → android_push; 11 → email; 14 → sms; 5, 7, 8, 9, 10 (web) → yalnızca kullanıcı oluşturulur (bkz. aşağı). Diğer değerler: abonelik yok.
invalid_identifier = tabonelik status: invalid
notification_types < 0abonelik status: unsubscribedAksi halde subscribed.
tags (JSON)kullanıcı tagsDeğerler metne çevrilir (nesne/dizi JSON metni olur, null atlanır). Geçersiz JSON → satır hatası.
languageproperties.language, device.locale
timezone (UTC'den saniye)device.timezoneTam saat ise Etc/GMT∓h (UTC+3 → Etc/GMT-3), değilse boş.
device_model, device_os, game_versiondevice.model, device.os_version, device.app_version
session_count, created_at, last_activesession_count, first_seen_at, last_active_at
id, ad_id, playtime, amount_spent, badge_count—Aktarılmaz.

Web push abonelikleri CSV ile taşınamaz: OneSignal dışa aktarımı p256dh/auth anahtarlarını içermez ve VAPID anahtar çifti değiştiği için tarayıcı abonelikleri yeniden oluşturulmalıdır. Web ziyaretçileri Pushizo Web SDK'sı yüklendiğinde (autoResubscribe: true varsayılanıyla) izin zaten verilmişse sessizce yeniden abone olur; bu yüzden web için çift yazma dönemini uzun tutun.

3.4 Göç sonrası kontrol

  • Abonelikler sayfasında kanal dağılımını OneSignal "Audience" sayılarıyla karşılaştırın.
  • Bir cihazı Test cihazı yapıp Mesajlar → Test push gönder ile gerçek teslimatı doğrulayın (OneSignal'den gelen APNs/FCM token'ları Pushizo'dan de çalışır).
  • error_report_url dosyasındaki satırları inceleyin (line, error, row).

4. API eşleme tablosu

Kimlik doğrulama: OneSignal Authorization: Basic <REST_API_KEY> → Pushizo Authorization: Bearer hs_live_…. Hata zarfı { "error": { "code": "HS_…", "message", "details", "request_id" } } (hata kataloğu). Sayfalama OneSignal'deki offset/limit yerine cursor/limit (next_cursor, has_more).

4.1 Uçlar

OneSignal RESTPushizo public APIFark
POST /notificationsPOST /v1/notificationsGövdede app_id; yanıt 202 { id, status, recipients_estimate }. Idempotency için Idempotency-Key başlığı ya da idempotency_key alanı (OneSignal external_id).
GET /notifications?app_id=GET /v1/notifications?app_id=Cursor sayfalama, status filtresi.
GET /notifications/{id}GET /v1/notifications/{message_id}counts nesnesi (queued, sent, delivered, failed, opened, clicked, suppressed…).
DELETE /notifications/{id}DELETE /v1/notifications/{message_id}Yalnızca zamanlanmış/kuyruktaki mesaj iptal edilir.
GET /notifications/{id}/historyGET /v1/notifications/{message_id}/historyCSV işi; tamamlanınca download_url.
POST /notifications/{id}/export_eventsPOST /v1/notifications/{message_id}/export_eventsCSV işi; download_url.
GET /players (view devices)GET /v1/apps/{app_id}/users + GET /v1/apps/{app_id}/subscriptions/{id}Cihaz kavramı yerine kullanıcı ve abonelik; aboneliğin sahibi GET …/subscriptions/{id}/user/identity.
GET /players/{id}GET /v1/apps/{app_id}/subscriptions/{subscription_id}Alanlar: channel, status, token_masked, device, user_id.
POST /players / PUT /players/{id}POST /v1/apps/{app_id}/users (aboneliklerle) / PATCH …/subscriptions/{id}Sunucu tarafı cihaz kaydı için users.upsert + subscriptions[].
PUT /players/{id} (tag güncelleme)PATCH /v1/apps/{app_id}/users/by/{label}/{value}Merge-patch tags, properties, deltas. null değer tag'i siler.
POST /players/csv_exportPOST /v1/apps/{app_id}/exports (type: users | subscriptions | events | deliveries)GET …/exports/{id} → download_url.
GET /users/by/{alias_label}/{alias_id}GET /v1/apps/{app_id}/users/by/{label}/{value}Aynı yol; hs_id OneSignal onesignal_id'nin karşılığıdır.
POST /usersPOST /v1/apps/{app_id}/usersexternal_id, tags, properties, language, subscriptions[].
PATCH /users/by/{label}/{value}PATCH /v1/apps/{app_id}/users/by/{label}/{value}
DELETE /users/by/{label}/{value}DELETE /v1/apps/{app_id}/users/by/{label}/{value}Abonelikler silinir, olaylar anonimleşir.
GET/PATCH /users/by/{label}/{value}/identityGET/PATCH /v1/apps/{app_id}/users/by/{label}/{value}/identityAlias ekleme; DELETE …/identity/{alias_label} kaldırır.
POST /users/by/{label}/{value}/subscriptionsPOST /v1/apps/{app_id}/users/by/{label}/{value}/subscriptions{ channel, token, device? }.
PATCH /subscriptions/{id}PATCH /v1/apps/{app_id}/subscriptions/{subscription_id}opted_in, device, test_device.
DELETE /subscriptions/{id}DELETE /v1/apps/{app_id}/subscriptions/{subscription_id}
PATCH /subscriptions_by_token/{token_type}/{token}PATCH /v1/apps/{app_id}/subscriptions_by_token/{token_type}/{token}OneSignal tür adları (iOSPush, AndroidPush, ChromePush, FirefoxPush, SafariPush, Email, SMS) da kabul edilir.
POST /subscriptions/{id}/ownerPOST /v1/apps/{app_id}/subscriptions/{subscription_id}/owner{ external_id }.
GET /subscriptions/{id}/user/identityGET /v1/apps/{app_id}/subscriptions/{subscription_id}/user/identity
POST /apps/{app_id}/custom_eventsPOST /v1/apps/{app_id}/events[{ external_id | subscription_id, name, properties, value, occurred_at }], en fazla 500.
GET /apps/{app_id}/outcomesGET /v1/apps/{app_id}/analytics/conversionsDönüşüm olayı event_definitions.is_conversion ile işaretlenir (PATCH …/events/definitions/{name}).
GET/POST /apps/{app_id}/segments, DELETE …/segments/{id}GET/POST /v1/apps/{app_id}/segments, PATCH/DELETE …/{id}Filtre AST ({ field, op, value } koşulları, all/any/none grupları; ör. tags.plan, properties.city, language, event); POST …/segments/preview sayım + örnek kullanıcılar.
GET/POST /templatesGET/POST /v1/apps/{app_id}/templates, PATCH/DELETE …/{id}, POST …/{id}/renderLiquid; sürüm geçmişi …/versions, başka app'e kopya …/copy_to_app.
GET /apps, GET /apps/{id}GET /v1/apps, GET /v1/apps/{app_id}PATCH /v1/apps/{app_id} ayarları günceller.
POST /appsPOST /v1/appsOrg geneli admin anahtarı.
Journeys (yalnızca panel)GET/POST /v1/apps/{app_id}/journeys, …/draft, …/publish, …/runsAPI ile tasarlanabilir ve tetiklenebilir (journey'ler).
In-App Messages (yalnızca panel)GET/POST /v1/apps/{app_id}/in-app-messagesBlok tabanlı; HTML yok.
Live Activities—v2 kapsamı (ADR-0017).

Postman koleksiyonu (api/postman_collection.json) tüm bu uçları {{baseUrl}}, {{apiKey}}, {{appId}} değişkenleriyle içerir.

4.2 POST /notifications gövdesi

Hedefleme alanları Pushizo'da target nesnesi altında toplanır; içerik alanlarının çoğu aynı adı taşır.

OneSignalPushizoNot
included_segments / excluded_segmentstarget.included_segments / target.excluded_segmentsSegment kimlikleri (seg_…) ya da adları.
include_aliases: { external_id: [] }target.include_aliases veya target.include_external_idsEn fazla 2000.
include_subscription_ids (eski include_player_ids)target.include_subscription_ids
include_email_tokenstarget.email_toAboneliği olmayan adres için anonim kullanıcı + abonelik oluşturulur.
include_phone_numberstarget.include_phone_numbersE.164.
filterstarget.filtersSegment AST (OneSignal field/relation/value yerine { field: "tags.plan", op: "eq", value: "pro" } ve all/any/none grupları).
target_channel: "push" | "email" | "sms"target.channels: ["ios_push", "android_push", "web_push", "email", "sms"]Verilmezse içerikten çıkarılır; SMS yalnızca açıkça.
isIos, isAndroid, isAnyWebtarget.channels
headings, contents, subtitle, url, app_url, data, buttons, big_picture, ios_attachments, ios_sound, ios_category, thread_id, ios_relevance_score, target_content_identifier, android_channel_id, android_group, android_sound, small_icon, large_icon, android_accent_color, android_visibility, chrome_web_icon, chrome_web_image, chrome_web_badge, web_push_topic, web_buttons, content_available, mutable_content, template_id, custom_data, send_after, delayed_option, delivery_time_of_day, ttl, priority, collapse_id, email_subject, email_body, email_preheader, email_from_name, email_from_address, email_reply_to_address, disable_email_click_tracking, sms_from, sms_media_urls, include_unsubscribed, nameaynı adpriority OneSignal'deki gibi 5 (normal) ya da 10 (yüksek); ttl saniye.
ios_badgeType, ios_badgeCountios_badge_type, ios_badge_countsnake_case.
ios_interruption_levelios_interruption_levelpassive, active, time-sensitive, critical (critical alert rehberi).
external_id (idempotency)idempotency_key ya da Idempotency-Key başlığıAynı anahtar + aynı gövde aynı yanıtı döndürür; farklı gövde 409 HS_IDEMPOTENCY_CONFLICT.
send_after + delayed_option: "timezone"aynıdelivery_time_of_day: "09:00".
throttle_rate_per_minutethrottle_rate_per_minute
email_mjmlemail_mjmlOneSignal'de yok; MJML derlemesi Pushizo'ya özgüdür.
—add_to_inbox, inbox_ttl, category, labels, one_per_user, frequency_cap_exempt, quiet_hours_exempt, require_interactionPushizo ek alanları.

Örnek (Node sunucu SDK'sı):

import { Pushizo } from '@pushizo/node';
const hs = new Pushizo({ apiKey: process.env.HS_API_KEY!, appId: process.env.HS_APP_ID, baseUrl: 'https://api.example.com' });

await hs.notifications.create({
  idempotency_key: `order-${order.id}`,
  target: { include_aliases: { external_id: [userId] } },
  headings: { tr: 'Siparişiniz yola çıktı', en: 'Your order has shipped' },
  contents: { tr: 'Kargo takip bağlantısı içeride', en: 'Tracking link inside' },
  url: `https://example.com/orders/${order.id}`,
  data: { order_id: order.id },
});

4.3 Webhook'lar

OneSignal "Event Streams" yerine Pushizo webhook endpoint'leri (/v1/apps/{app_id}/webhooks) HMAC imzalı (Pushizo-Signature: t=…,v1=…) olaylar gönderir: delivery.*, subscription.*, user.*, event.received, conversion.created, campaign.*, journey.*, in_app.*. İmza doğrulama ve yeniden deneme planı için webhook'lar.

5. SDK değişim rehberi

Tüm istemci SDK'larında gizli anahtar yoktur; yalnızca App ID (ve kendi API adresiniz) kullanılır. identity verification zorunluysa login ikinci parametre olarak sunucunuzun ürettiği identity_hash = HMAC-SHA256(sdk_secret, external_id) değerini alır (OneSignal'deki JWT yerine).

5.1 Web

OneSignal v16 (Web)Pushizo Web SDK (@pushizo/web)
<script src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js"> + OneSignalDeferred.push(async (OneSignal) => { await OneSignal.init({ appId }) })<script src="https://api.example.com/sdk-web/PushizoSDK.js" async> + PushizoDeferred.push(async (Pushizo) => { await Pushizo.init({ appId: 'app_…', apiUrl: 'https://api.example.com' }) })
OneSignalSDKWorker.js site kökündePushizoSDKWorker.js site kökünde (importScripts(apiUrl + '/sdk-web/PushizoSDKWorker.js')); serviceWorkerPath / serviceWorkerScope seçenekleri aynı anlamda
OneSignal.login(externalId, jwtToken?)Pushizo.login(externalId, identityHash?)
OneSignal.logout()Pushizo.logout()
OneSignal.User.addTag / addTags / removeTag / removeTags / getTagsaynı adlar: Pushizo.User.addTag / addTags / removeTag / removeTags / getTags
OneSignal.User.addAlias / addAliases / removeAliasaynı adlar
OneSignal.User.addEmail / removeEmail / addSms / removeSmsaynı adlar (adres istemcide normalize edilir)
OneSignal.User.setLanguagePushizo.User.setLanguage
OneSignal.User.PushSubscription.optIn / optOut / id / token / optedIn + addEventListener('change')Pushizo.User.pushSubscription.optIn / optOut / id / optedIn / state + addObserver(cb) (geri dönen fonksiyon dinleyiciyi kaldırır)
OneSignal.Notifications.requestPermission() / permissionPushizo.Notifications.requestPermission() / permission ('default' | 'granted' | 'denied' | 'unsupported')
OneSignal.Notifications.addEventListener('click', cb)Pushizo.Notifications.addClickListener(({ notification, result }) => …)
OneSignal.Notifications.addEventListener('foregroundWillDisplay', cb)Pushizo.Notifications.addForegroundLifecycleListener((e) => e.preventDefault())
OneSignal.Slidedown.promptPush / promptEmail / promptSms / promptPushCategoriesPushizo.Slidedown.promptPush / promptEmail / promptSms / promptEmailAndSms (kategori tercihleri için User.setPreferences)
promptOptions.slidedown, welcomeNotification, notificationClickHandlerMatch/Action, notifyButtonslidedown, welcomeNotification, notificationClickHandlerMatch / notificationClickHandlerAction, bell (init seçenekleri)
OneSignal.Session.sendOutcome / sendUniqueOutcome / sendOutcomeWithValuePushizo.Session.sendEvent(name, properties?, value?)
OneSignal.User.PushSubscription bildirim kutusu yokPushizo.Inbox.list / markRead / markAllRead / archive / unreadCount / addObserver
In-app (yalnızca mobil)Pushizo.InAppMessages.addTrigger / addTriggers / removeTrigger / clearTriggers / setScreen / paused / addClickListener / addLifecycleListener (web dahil)
OneSignal.setConsentRequired(true) + setConsentGiven(true)init({ requiresPrivacyConsent: true }) + Pushizo.setConsentGiven(true)
OneSignal.Debug.setLogLevelPushizo.Debug.setLogLevel('debug')

Ayrıntı: Web SDK, çatı entegrasyonları: React, Vue, Angular, iOS Safari PWA: iOS web push.

5.2 iOS

OneSignal iOS SDK 5Pushizo iOS SDK (Pushizo, PushizoExtension)
OneSignal.initialize("APP_ID", withLaunchOptions:)Pushizo.initialize("app_…", launchOptions:) { options in options.apiUrl = "https://api.example.com" }
Swizzling ile tokenSwizzling yok: didRegisterForRemoteNotificationsWithDeviceToken içinde Pushizo.setDeviceToken(deviceToken), hata durumunda Pushizo.setDeviceTokenError(error)
OneSignal.login("id") / logout()Pushizo.login("id", identityHash: nil) / Pushizo.logout()
OneSignal.User.addTag/addTags/removeTag/getTags/setLanguageaynı adlar
OneSignal.User.addEmail/addSms/removeEmail/removeSmsaynı adlar
OneSignal.User.pushSubscription.optIn()/optOut()/id/token/optedIn + addObserverPushizo.User.pushSubscription.optIn()/optOut()/id/token, await state(), addObserver { state in }
OneSignal.Notifications.requestPermission(_:fallbackToSettings:)Pushizo.Notifications.requestPermission { granted in } (await permission() ile okuma)
OneSignal.Notifications.addPermissionObserveraddPermissionObserver { granted in } → HSListenerToken; removePermissionObserver(token)
addClickListener / addForegroundLifecycleListeneraynı adlar; belirteç döndürür (removeClickListener(token))
OneSignalNotificationServiceExtensionPushizoNotificationServiceExtension(appId:apiUrl:appGroup:) → didReceive, serviceExtensionTimeWillExpire
OneSignal.InAppMessages.addTrigger/removeTrigger/clearTriggers/pausedaynı adlar + setScreen, addClickListener, addLifecycleListener
OneSignal.Session.sendOutcome(_:)Pushizo.Session.sendEvent("name", properties:, value:)
OneSignal.setConsentRequired/setConsentGivenoptions.requiresPrivacyConsent = true + Pushizo.setConsentGiven(true)
OneSignal.Notifications.clearAll()Pushizo.Notifications.clearAll(), removeGroupedNotifications, removeNotification(identifier:)
Live Activitiesv2

Aynı APNs .p8 anahtarı kullanıldığından mevcut cihaz token'ları Pushizo'dan de teslim alır; SDK ilk açılışta token'ı POST /subscriptions ile kaydeder (göçte aktarılmış abonelikle (app, channel, token) üzerinden birleşir). Ayrıntı: iOS SDK.

5.3 Android

OneSignal Android SDK 5Pushizo Android SDK (com.pushizo:pushizo-android)
OneSignal.initWithContext(this, "APP_ID")Pushizo.initialize(this, "app_…", Pushizo.Options(apiUrl = "https://api.example.com")) (Application onCreate)
OneSignal.login("id") / logout()Pushizo.login("id", identityHash = null) / Pushizo.logout()
OneSignal.User.addTag/addTags/removeTag/getTags/setLanguageaynı adlar
OneSignal.User.addEmail/addSms/removeEmail/removeSmsaynı adlar (emails, smsNumbers listeleri)
OneSignal.User.pushSubscription.optIn()/optOut()/id/token/optedIn + addObserveraynı adlar (state ek)
OneSignal.Notifications.requestPermission(fallbackToSettings) (coroutine)Pushizo.Notifications.requestPermission(activity) + onRequestPermissionsResult içinde Pushizo.Notifications.onPermissionResult() (PERMISSION_REQUEST_CODE)
addPermissionObserveraddPermissionObserver(observer) / removePermissionObserver(observer)
addClickListener / addForegroundLifecycleListeneraynı adlar
OneSignal.InAppMessages.addTrigger/…/pausedaynı adlar + setScreen, addClickListener, addLifecycleListener
OneSignal.Session.sendOutcomePushizo.Session.sendEvent("name", mapOf(...), value)
OneSignal.consentRequired = true / consentGiven = trueOptions(requiresPrivacyConsent = true) + Pushizo.setConsentGiven(true)
OneSignal.Notifications.clearAllNotifications()Pushizo.Notifications.clearAll(), removeNotification, removeGroupedNotifications
Bildirim kanalları (panelden)Dashboard → Ayarlar → Android bildirim kategorileri (android_channels); android_channel_id ile seçilir

Aynı Firebase projesi kullanıldığı sürece FCM token'ları değişmez. Ayrıntı: Android SDK.

5.4 Flutter

onesignal_flutterpushizo_flutter
OneSignal.initialize("APP_ID")await Pushizo.initialize('app_…', apiUrl: 'https://api.example.com')
OneSignal.login/logoutPushizo.login(externalId, identityHash: null) / Pushizo.logout()
OneSignal.User.addTags/removeTag/getTags/setLanguageaynı adlar (hepsi Future)
OneSignal.User.addEmail/addSms/removeEmail/removeSmsaynı adlar
OneSignal.User.pushSubscription.optIn/optOut/id/token/optedIn + addObserverPushizo.User.pushSubscription.optIn()/optOut(), await state, changes.listen(...)
OneSignal.Notifications.requestPermission(true)await Pushizo.Notifications.requestPermission()
OneSignal.Notifications.addPermissionObserverPushizo.Notifications.addPermissionObserver(fn) ya da permissionStream.listen(...)
addClickListener / addForegroundWillDisplayListenerPushizo.Notifications.clickStream.listen(...) / foregroundStream.listen(...)
OneSignal.InAppMessages.addTrigger/…/paused(bool)aynı adlar + setScreen, setPaused(bool), clickStream, lifecycleStream, setNavigatorKey
OneSignal.Session.sendOutcomePushizo.Session.sendEvent(name, properties:, value:)
OneSignal.consentRequired(true) / consentGiven(true)initialize(..., requiresPrivacyConsent: true) + Pushizo.setConsentGiven(true)
—Pushizo.Inbox.list/markRead/markAllRead/archive/unreadCount, Pushizo.User.getPreferences/setPreferences

Ayrıntı: Flutter SDK.

5.5 Köprü SDK'ları için ortak notlar

Aşağıdaki tablolarda OneSignal sütunu ilgili paketin v5 API adlarını esas alır; daha eski (v3/v4) bir OneSignal sürümünden geçiyorsanız önce çağrıları v5 karşılıklarına eşleyin. Tüm köprü SDK'larında:

  • Paket değişimi tek seferdedir: OneSignal paketini (ve Expo için onesignal-expo-plugin) kaldırıp Pushizo paketini ekleyin, yerel projeyi yeniden üretin (pod install, npx cap sync, cordova prepare, expo prebuild). Pushizo iOS'ta UNUserNotificationCenter delegesini üstlendiğinden aynı sürümde iki push SDK'sı birlikte bulunmamalıdır.
  • initialize App ID'nin yanında kendi API adresinizi (apiUrl) alır; REST API anahtarı istemciye gömülmez.
  • OneSignal "outcome" çağrıları (addOutcome, addUniqueOutcome, addOutcomeWithValue ve C# karşılıkları) tek bir Session.sendEvent(name, properties?, value?) çağrısına dönüşür; aynı ad in-app event tetiklerini de çalıştırır. Tekillik (unique) gerekiyorsa uygulamada ya da journey/segment koşulunda sağlayın.
  • Bildirim kutusu (Inbox) ve kategori tercihleri (User.getPreferences / setPreferences) OneSignal'de karşılığı olmayan eklemelerdir (bkz. 5.11).

5.6 React Native

react-native-onesignal 5@pushizo/react-native
Expo: ["onesignal-expo-plugin", { "mode": "development" }]["@pushizo/react-native", { "mode": "development", "appId": "app_…" }] (plugin pakete dahildir; NSE hedefi PushizoNotificationServiceExtension)
Bare iOS: token swizzling ile alınırSwizzling yok: AppDelegate içinde Pushizo.setDeviceToken(deviceToken) / Pushizo.setDeviceTokenError(error) (Expo plugin otomatik ekler)
OneSignal.initialize('APP_ID')await Pushizo.initialize('app_…', { apiUrl: 'https://api.example.com' })
OneSignal.login(externalId) / OneSignal.logout()Pushizo.login(externalId, identityHash?) / Pushizo.logout()
OneSignal.User.addTag / addTags / removeTag / removeTags / getTagsaynı adlar
OneSignal.User.addAlias / addAliases / removeAliasaynı adlar
OneSignal.User.addEmail / removeEmail / addSms / removeSms, setLanguageaynı adlar
OneSignal.User.getExternalId() / getOnesignalId()Pushizo.User.getExternalId() / getPushizoId()
OneSignal.User.pushSubscription.getIdAsync / getTokenAsync / getOptedInAsync / optIn / optOut + addEventListener('change', …)aynı adlar ({ previous, current })
OneSignal.Notifications.requestPermission(fallbackToSettings)Pushizo.Notifications.requestPermission()
OneSignal.Notifications.getPermissionAsync()Pushizo.Notifications.getPermissionAsync() (eşzamanlı son değer: permission)
OneSignal.Notifications.addEventListener('click' | 'foregroundWillDisplay' | 'permissionChange', …)aynı olay adları; e.preventDefault() ve e.getNotification().display() aynı
OneSignal.Notifications.clearAll()Pushizo.Notifications.clearAll()
OneSignal.InAppMessages.addTrigger / addTriggers / removeTrigger / removeTriggers / clearTriggers / setPaused / getPausedaynı adlar + getTriggers, setScreen
OneSignal.InAppMessages.addEventListener('click' | 'willDisplay' | 'didDisplay' | 'willDismiss' | 'didDismiss', …)aynı olay adları; olay gövdesi { messageId, actionId, url } / { messageId }
OneSignal.Session.addOutcome / addUniqueOutcome / addOutcomeWithValuePushizo.Session.sendEvent(name, properties?, value?)
OneSignal.setConsentRequired(true) + setConsentGiven(true)initialize(…, { requiresPrivacyConsent: true }) + Pushizo.setConsentGiven(true)
OneSignal.Debug.setLogLevel(LogLevel.Verbose)Pushizo.Debug.setLogLevel(LogLevel.Debug)
—Pushizo.Inbox.*, Pushizo.User.getPreferences / setPreferences

Ayrıntı: React Native SDK.

5.7 Capacitor (Ionic)

OneSignal Ionic/Capacitor uygulamalarında onesignal-cordova-plugin paketini kullanır; Pushizo'da ayrı bir Capacitor eklentisi vardır (web'de @pushizo/web'e devreder).

onesignal-cordova-plugin 5 (Capacitor)@pushizo/capacitor
npm install onesignal-cordova-pluginnpm install @pushizo/capacitor (+ web için @pushizo/web), npx cap sync
iOS token swizzling ile alınırAppDelegate.swift içinde capacitorDidRegisterForRemoteNotifications / capacitorDidFailToRegisterForRemoteNotifications bildirimlerini gönderin
OneSignal.initialize('APP_ID')await Pushizo.initialize('app_…', { apiUrl: 'https://api.example.com' })
OneSignal.login / logoutPushizo.login(externalId, identityHash?) / Pushizo.logout() (Promise)
OneSignal.User.addTag / addTags / removeTag / removeTags / getTags, addAlias / addAliases / removeAlias, addEmail / removeEmail / addSms / removeSms, setLanguageaynı adlar (hepsi Promise)
OneSignal.User.pushSubscription.getIdAsync / getTokenAsync / getOptedInAsync / optIn / optOutPushizo.User.pushSubscription.getId / getToken / getOptedIn / getState / optIn / optOut
OneSignal.User.pushSubscription.addEventListener('change', cb)Pushizo.User.pushSubscription.addObserver((state) => …) (dönen fonksiyon aboneliği kaldırır)
OneSignal.Notifications.requestPermission(true)await Pushizo.Notifications.requestPermission()
OneSignal.Notifications.addEventListener('click', cb)Pushizo.Notifications.addClickListener(({ notification, result }) => …)
OneSignal.Notifications.addEventListener('foregroundWillDisplay', cb)Pushizo.Notifications.addForegroundLifecycleListener((e) => e.preventDefault()); erteleyip göstermek için await e.display()
OneSignal.Notifications.addEventListener('permissionChange', cb)Pushizo.Notifications.addPermissionObserver(({ permission }) => …)
OneSignal.Notifications.clearAll()Pushizo.Notifications.clearAll(), removeGroupedNotifications, removeNotification (yalnızca Android)
OneSignal.InAppMessages.addTrigger / addTriggers / removeTrigger / removeTriggers / clearTriggers / setPaused / getPausedaynı adlar + getTriggers, setScreen
OneSignal.InAppMessages.addEventListener('click' | 'willDisplay' | …, cb)Pushizo.InAppMessages.addClickListener(cb) / addLifecycleListener({ willDisplay, didDisplay, willDismiss, didDismiss })
OneSignal.Session.addOutcome / addUniqueOutcome / addOutcomeWithValuePushizo.Session.sendEvent(name, properties?, value?)
OneSignal.setConsentRequired(true) + setConsentGiven(true)initialize(…, { requiresPrivacyConsent: true }) + await Pushizo.setConsentGiven(true)
OneSignal.Debug.setLogLevel(…)await Pushizo.Debug.setLogLevel('debug')

Ayrıntı: Capacitor SDK.

5.8 Cordova

onesignal-cordova-plugin 5cordova-plugin-pushizo
cordova plugin add onesignal-cordova-plugin, window.plugins.OneSignalcordova plugin add cordova-plugin-pushizo, window.Pushizo (ve window.plugins.Pushizo)
Android Gradle ayarı gerekmezconfig.xml → GradlePluginKotlinEnabled ve GradlePluginGoogleServicesEnabled (köprü Kotlin'dir)
OneSignal.initialize('APP_ID') (deviceready içinde)await Pushizo.initialize('app_…', { apiUrl: 'https://api.example.com' })
Diğer tüm çağrılarCapacitor tablosuyla (5.7) birebir aynı; tüm metotlar Promise döndürür, hatalar PushizoError (code)

iOS'ta APNs token geri çağrıları eklenti tarafından AppDelegate'e çalışma zamanında eklenir; ek kod gerekmez. Ayrıntı: Cordova SDK.

5.9 .NET MAUI

OneSignalSDK.DotNet 5Pushizo.Maui
dotnet add package OneSignalSDK.DotNet, using OneSignalSDK.DotNet;dotnet add package Pushizo.Maui, using PushizoSdk.Maui;
OneSignal.Initialize("APP_ID")builder.UsePushizo("app_…", o => o.ApiUrl = "https://api.example.com") (MauiProgram.cs) ya da Pushizo.Initialize("app_…", options)
iOS token swizzling ile alınırAppDelegate içinde PushizoIos.RegisteredForRemoteNotifications(deviceToken) / FailedToRegisterForRemoteNotifications(error)
OneSignal.Login("id") / OneSignal.Logout()Pushizo.Login("id", identityHash) / Pushizo.Logout()
OneSignal.User.AddTag / AddTags / RemoveTag / RemoveTags, AddAlias / AddAliases / RemoveAlias, AddEmail / RemoveEmail / AddSms / RemoveSmsaynı adlar + GetTags(), SetLanguage("tr")
OneSignal.User.PushSubscription.OptIn() / OptOut() / Id / Token / OptedIn + Changedaynı adlar (e.Previous, e.Current)
await OneSignal.Notifications.RequestPermissionAsync(true)await Pushizo.Notifications.RequestPermissionAsync(fallbackToSettings: true)
OneSignal.Notifications.Clicked / ForegroundWillDisplay / PermissionChangedaynı olay adları (EventHandler); tıklamada e.Notification, e.ActionId, e.Url; ön planda e.PreventDefault()
OneSignal.Notifications.ClearAllNotifications()Pushizo.Notifications.ClearAll()
OneSignal.InAppMessages.AddTrigger / AddTriggers / RemoveTrigger / RemoveTriggers / ClearTriggers / Paused + Clicked / WillDisplay / DidDisplay / WillDismiss / DidDismissaynı adlar + GetTriggers(), SetScreen(name)
OneSignal.Session.AddOutcome / AddUniqueOutcome / AddOutcomeWithValuePushizo.Session.SendEvent(name, properties, value)
OneSignal.ConsentRequired = true + OneSignal.ConsentGiven = trueo.RequiresPrivacyConsent = true + Pushizo.SetConsentGiven(true)
OneSignal.Debug.LogLevel = …Pushizo.Debug.SetLogLevel(LogLevel.Debug)
—Pushizo.Inbox.ListAsync / MarkReadAsync / MarkAllReadAsync / ArchiveAsync / UnreadCountAsync, Pushizo.User.GetPreferencesAsync / SetPreferencesAsync

Ayrıntı: .NET MAUI SDK.

5.10 Unity

OneSignal Unity SDK 5com.pushizo.unity
OneSignal UPM paketleri, using OneSignalSDK;Git URL ile UPM paketi (https://github.com/exec0de/pushizo.git?path=sdk/unity#sdk-v0.1.0), using PushizoSdk;; Project Settings → Pushizo (App ID, App Group, google-services.json yolu)
OneSignal.Initialize("APP_ID")Pushizo.Initialize("app_…", new PushizoOptions { ApiUrl = "https://api.example.com" })
OneSignal.Login("id") / OneSignal.Logout()Pushizo.Login("id", identityHash) / Pushizo.Logout()
OneSignal.User.AddTag / AddTags / RemoveTag / RemoveTags, AddAlias / AddAliases / RemoveAlias, AddEmail / RemoveEmail / AddSms / RemoveSmsaynı adlar + GetTags(), SetLanguage("tr")
OneSignal.User.PushSubscription.OptIn() / OptOut() / Id / Token / OptedIn + Changedaynı adlar
await OneSignal.Notifications.RequestPermissionAsync(true)await Pushizo.Notifications.RequestPermissionAsync(fallbackToSettings: true)
OneSignal.Notifications.Clicked / ForegroundWillDisplay / PermissionChanged += (sender, e) => …aynı olay adları, Action<T> imzası: Clicked += e => …, PermissionChanged += granted => … (olaylar ana iş parçacığında gelir)
OneSignal.Notifications.ClearAllNotifications()Pushizo.Notifications.ClearAll()
OneSignal.InAppMessages.AddTrigger / AddTriggers / RemoveTrigger / RemoveTriggers / ClearTriggers / Paused + Clicked / WillDisplay / DidDisplay / WillDismiss / DidDismissaynı adlar + GetTriggers(), SetScreen(name)
OneSignal.Session.AddOutcome / AddUniqueOutcome / AddOutcomeWithValuePushizo.Session.SendEvent(name, properties, value)
OneSignal.ConsentRequired = true + OneSignal.ConsentGiven = truenew PushizoOptions { RequiresPrivacyConsent = true } + Pushizo.SetConsentGiven(true)
OneSignal.Debug.LogLevel = …Pushizo.Debug.SetLogLevel(LogLevel.Debug)
—Pushizo.Inbox.*Async, Pushizo.User.GetPreferencesAsync / SetPreferencesAsync

Android bağımlılıkları EDM4U ile çözülür ve Assets/google-services.json derlemede işlenir (Firebase Unity SDK'sı gerekmez); iOS'ta Push yeteneği, NSE hedefi ve Podfile derleme sonrası işlemle eklenir. Ayrıntı: Unity SDK.

5.11 Bildirim kutusu ve tercihler (OneSignal'de olmayanlar)

  • Bildirim kutusu: add_to_inbox: true ile gönderilen mesajlar kullanıcıya özel kutuda listelenir (Inbox.list, markRead, markAllRead, archive, unreadCount); OneSignal'de karşılığı olmadığından taşınacak veri yoktur.
  • Kategori tercihleri: OneSignal "push categories" slidedown'ı yerine dashboard'da Kategoriler tanımlanır; SDK'lar User.getPreferences() / setPreferences([...]) ile kullanıcı × kanal opt-in yazar. OneSignal'de tag ile yönettiğiniz tercihleri (tags.promo_optin = "0") göç sonrasında bir kerelik PUT /v1/apps/{app_id}/users/by/external_id/{id}/preferences çağrısıyla gerçek tercihe çevirebilirsiniz.

6. Kesinti planı (çift yazma dönemi)

  1. Hafta 0 — hazırlık: kanallar doğrulanmış, player göçü tamamlanmış, sunucu entegrasyonu Pushizo'ya de yazıyor (çift yazma: her bildirim/olay OneSignal ve Pushizo'ya birlikte gider; Pushizo'da test_devices_only: true ile yalnızca test cihazlarına gönderim yapın ya da hedefi küçük bir segmentle sınırlayın).
  2. Hafta 1–2 — istemci yayını: Pushizo SDK'sını içeren mobil sürümü yayınlayın, web'de SDK'yı canlıya alın. Her iki SDK aynı uygulamada çalışabilir; ancak push izni istemini yalnızca Pushizo'dan yapın (iki SDK birden izin isterse kullanıcı kafa karışıklığı yaşar) ve Android'de yalnızca birinin ön plan bildirimi göstermesine izin verin (addForegroundLifecycleListener + preventDefault()).
  3. Hafta 2–3 — trafik kaydırma: işlemsel bildirimleri (sipariş, OTP) Pushizo'dan, kampanyaları dashboard'dan göndermeye başlayın. OneSignal'den gönderimi segment bazında azaltın; Analitik → Teslimat raporu ve Sağlayıcı sağlığı sayfalarından teslim/açılma oranlarını karşılaştırın.
  4. Hafta 3–4 — kesinti: OneSignal gönderimlerini durdurun, migrate:onesignal ile son bir fark çekimi yapın (içe aktarma idempotenttir; yeni player'lar eklenir, mevcutlar güncellenir), OneSignal webhook/Event Stream'lerini kapatın, REST API anahtarını iptal edin.
  5. Eski uygulama sürümleri: OneSignal SDK'sı içeren eski sürümler hâlâ OneSignal'e token kaydeder; bu kullanıcılar için haftalık fark çekimini sürümün kullanım payı %1'in altına inene kadar sürdürün.
  6. Geri alma: çift yazma döneminde OneSignal yapılandırmasını silmeyin; kritik bir sorun olursa gönderimi OneSignal'e geri alabilirsiniz. Kesintiden sonra .p8/servis hesabı anahtarlarını OneSignal'den kaldırın.

7. Sık karşılaşılan farklar

KonuOneSignalPushizo
Kimlikonesignal_id + external_idhs_id + external_id + özel alias'lar (users/by/{label}/{value})
Cihaz birleştirmelogin cihazı kullanıcıya bağlarAynı; anonim kullanıcı birleştirilir, user.merged webhook'u üretilir
Hata biçimi{ "errors": [...] }{ "error": { "code": "HS_…", … } }, x-request-id
Hız sınırısabitPlan bazlı (api_rps), X-RateLimit-* başlıkları, 429 HS_RATE_LIMITED + Retry-After
Sessiz saatler / frekans sınırıpanelApp ayarları; mesaj başına quiet_hours_exempt, frequency_cap_exempt
Şablon dili{{ tag }} basit değişkenlerLiquid ({{ user.tags.name }}, filtreler, koşullar)
Web push kimliğiOneSignal VAPIDKendi VAPID çiftiniz (kanal kaydında üretilir); abonelikler yeniden oluşur
Veri yerleşimiOneSignal bulutuKendi altyapınız (self-hosted)

Bu sayfada